Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 289c08b

Browse files
fix: findBy runs the detection cycle before checking
1 parent ad0b2db commit 289c08b

File tree

2 files changed

+74
-6
lines changed

2 files changed

+74
-6
lines changed

‎projects/testing-library/src/lib/testing-library.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
waitFor,
1313
waitForElementToBeRemoved,
1414
fireEvent as dtlFireEvent,
15+
screen as dtlScreen,
16+
queries as dtlQueries,
1517
} from '@testing-library/dom';
1618
import { RenderComponentOptions, RenderDirectiveOptions, RenderResult } from './models';
1719
import { createSelectOptions, createType, tab } from './user-events';
@@ -178,7 +180,7 @@ export async function render<SutType, WrapperType = SutType>(
178180
tab,
179181
waitFor: componentWaitFor,
180182
waitForElementToBeRemoved: componentWaitForElementToBeRemoved,
181-
...getQueriesForElement(fixture.nativeElement, queries),
183+
...replaceFindWithFindAndDetectChanges(fixture.nativeElement,getQueriesForElement(fixture.nativeElement, queries)),
182184
...eventsWithDetectChanges,
183185
};
184186
}
@@ -241,6 +243,30 @@ function addAutoImports({ imports, routes }: Pick<RenderComponentOptions<any>, '
241243
return [...imports, ...animations(), ...routing()];
242244
}
243245

246+
// for the findBy queries we first want to run a change detection cycle
247+
function replaceFindWithFindAndDetectChanges<T>(container: HTMLElement, originalQueriesForContainer: T): T {
248+
return Object.keys(originalQueriesForContainer).reduce(
249+
(newQueries, key) => {
250+
if (key.startsWith('find')) {
251+
const getByQuery = dtlQueries[key.replace('find', 'get')];
252+
newQueries[key] = async (text, options, waitForOptions) => {
253+
// original implementation at https://github.com/testing-library/dom-testing-library/blob/master/src/query-helpers.js
254+
const result = await waitFor(() => {
255+
detectChangesForMountedFixtures();
256+
return getByQuery(container, text, options);
257+
}, waitForOptions);
258+
return result;
259+
};
260+
} else {
261+
newQueries[key] = originalQueriesForContainer[key];
262+
}
263+
264+
return newQueries;
265+
},
266+
{} as T,
267+
);
268+
}
269+
244270
function cleanup() {
245271
mountedFixtures.forEach(cleanupAtFixture);
246272
}
@@ -258,20 +284,24 @@ if (typeof afterEach === 'function' && !process.env.ATL_SKIP_AUTO_CLEANUP) {
258284
});
259285
}
260286

287+
function detectChangesForMountedFixtures() {
288+
mountedFixtures.forEach(fixture => fixture.detectChanges());
289+
}
290+
261291
export * from '@testing-library/dom';
262292

263293
const fireEvent = Object.keys(dtlFireEvent).reduce(
264294
(events, key) => {
265295
events[key] = (element: HTMLElement, options?: {}) => {
266296
const result = dtlFireEvent[key](element, options);
267-
mountedFixtures.forEach(fixture => {
268-
fixture.detectChanges();
269-
});
297+
detectChangesForMountedFixtures();
270298
return result;
271299
};
272300
return events;
273301
},
274-
{} as FireFunction&FireObject,
302+
{} as typeofdtlFireEvent,
275303
);
276304

277-
export { fireEvent };
305+
const screen = replaceFindWithFindAndDetectChanges(document.body, dtlScreen);
306+
307+
export { fireEvent, screen };
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Component } from '@angular/core';
2+
import { timer } from 'rxjs';
3+
import { render, screen } from '../src/public_api';
4+
import { mapTo, timeout } from 'rxjs/operators';
5+
6+
@Component({
7+
selector: 'fixture',
8+
template: `
9+
<div>{{ result | async }}</div>
10+
`,
11+
})
12+
class FixtureComponent {
13+
result = timer(30).pipe(mapTo('I am visible'));
14+
}
15+
16+
describe('screen', () => {
17+
test('waits for element to be added to the DOM', async () => {
18+
await render(FixtureComponent);
19+
await expect(screen.findByText('I am visible')).resolves.toBeTruthy();
20+
});
21+
22+
test('rejects when something cannot be found', async () => {
23+
await render(FixtureComponent);
24+
await expect(screen.findByText('I am invisible', {}, { timeout: 40 })).rejects.toThrow('x');
25+
});
26+
});
27+
28+
describe('rendered component', () => {
29+
test('waits for element to be added to the DOM', async () => {
30+
const { findByText } = await render(FixtureComponent);
31+
await expect(findByText('I am visible')).resolves.toBeTruthy();
32+
});
33+
34+
test('rejects when something cannot be found', async () => {
35+
const { findByText } = await render(FixtureComponent);
36+
await expect(findByText('I am invisible', {}, { timeout: 40 })).rejects.toThrow('x');
37+
});
38+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /