-
Notifications
You must be signed in to change notification settings - Fork 24.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(core): support fakeAsync.wrap() functionality across multiple test cases. #40611
Conversation
What happens when developer forgets to invoke An alternative approach may be something as shown below. Have you consider it? What do you think are advantages/disadvantages of the two approaches?
|
@mhevery, yeah, I like your idea,
I will update the PR |
ee3ccbb
to
b599041
Compare
b599041
to
c36741a
Compare
aio/content/examples/testing/src/app/auth/auth.component.spec.ts
Outdated
Show resolved
Hide resolved
aio/content/examples/testing/src/app/auth/auth.component.spec.ts
Outdated
Show resolved
Hide resolved
aio/content/examples/testing/src/app/auth/auth.component.spec.ts
Outdated
Show resolved
Hide resolved
By the way, should the hooks be |
c36741a
to
17582fd
Compare
@petebacondarwin , yes, you are right, |
d34964d
to
fe770f6
Compare
You can preview fe770f6 at https://pr40611-fe770f6.ngbuilds.io/. |
fe770f6
to
0f8d2ac
Compare
You can preview 0f8d2ac at https://pr40611-0f8d2ac.ngbuilds.io/. |
0f8d2ac
to
153891e
Compare
You can preview 153891e at https://pr40611-153891e.ngbuilds.io/. |
153891e
to
4382afc
Compare
bedc39e
to
f7b9aeb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reviewed-for: public-api
Hi @JiaLiPassion, it looks like the issue you linked was closed by 0652b29. Is this still necessary? That question aside, I'm not sure I see why this specific thing should be a feature provided by the
The above is actually shorter than your example using this new feature. |
@atscott thank you for the review.
the |
@JiaLiPassion Okay, I think that makes sense. Could you please update the documentation to describe this better? The way it is now, it seems to imply what I wrote should work fine. "without hook functions, we need to write test like this" Unless I'm missing something, the example after that sentence is exactly what I wrote in my comment. Also, I'm still curious about 0652b29 and if it makes this PR obsolete. If not, the commit message should be changed to reflect that this solves a different issue (one that's not closed). |
/** | ||
* Wrap the `fakeAsync()` function with the `beforeEach()/afterEach()` hooks. | ||
* | ||
* TODO: add code samples |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the example code supposed to be here rather than fake-async-test.ts
? Or should it be in both locations
@atscott , got it, I will update the commit message, and about the |
995672d
to
3547ad2
Compare
…()/afterEach()` hooks. Close angular#40387 Provide the new `fakeAsync.wrap()` function with the `beforeEach()/afterEach()` hooks. Given the AppComponent: @component({...}) export class AppComponent { timerId: number; ngOnInit() { this.timerId = setTimeout(() => {}); } ngOnDestroy() { clearTimeout(this.timerId); } } And without hook functions, we need to write test like this. describe('AppComponent test', () => { let fixture: ComponentFixture<AppComponent>; beforeEach(() => { ... fixture = TestBed.createComponent(AppComponent); }); it('test case1', fakeAsync(() => { fixture.detectChanges(); // do some test with fixture fixture.destroy(); })); it('test case2', fakeAsync(() => { fixture.detectChanges(); // do some test with fixture fixture.destroy(); })); }); We need to call `fixture.destroy()` inside each tests, since each `it()` use it's own fakeAsync() and we need to clean up the timerId created in that FakeAsyncZone. With the hook functions, we can write case in this way. describe('AppComponent test', () => { let fixture: ComponentFixture<AppComponent>; const fakeAsyncWithFixture = fakeAsync.wrap({ beforeEach: () => { fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); } afterEach: () => fixture.destroy(); }); it('test case1', fakeAsyncWithFixture(() => { // do some test with fixture })); it('test case2', fakeAsyncWithFixture(() => { // do some test with fixture })); }); Also the wrap() function support nesting. describe('AppComponent test', () => { let fixture: ComponentFixture<AppComponent>; const fakeAsyncWithFixture = fakeAsync.wrap({ beforeEach: () => { fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); } afterEach: () => fixture.destroy(); }); it('test case1', fakeAsyncWithFixture(() => { // do some test with fixture })); it('test case2', fakeAsyncWithFixture(() => { // do some test with fixture })); describe('AppComponent sub test: auth test', () => { const fakeAsyncNested = fakeAsyncWithFeature.wrap({ beforeEach: () => fixture.componentInstance.login(), afterEach: () => fixture.componentInstance.logout(); }); it('should show user info', () => { // do some test with fixture with authenticated user. }); }); }); This feature is useful when we want to do some common initial/cleanup when the component has some `async` tasks (especially `setInterval`) running by 3rd party library.
`zone.js` provides a new API `fakeAsync.wrap()` to support `hooks` of `fakeAsync()` to allow user to write common `begin`/'after` logic. This commit add the new `wrap()` API to `@angular/core/testing`.
1. add `fakeAsync.wrap()` example code. 1. add `fakeAsync.wrap()` doc in the `testing-components-scenarios.md` doc.
3547ad2
to
9ab9d0a
Compare
@JiaLiPassion I've moved this back to a draft since it doesn't seem ready for review |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Close #40387
Enable global
fakeAsync()
feature by introducing hooks functions.fakeAsync.wrap({beforeEach?: () => void, afterEach?: () => void)
;Motivation
Consider the similar function from
jest.useFakeTimers()
, we can write test cases like this.So with
jest.useFakeTimers()
, all the following tests are automatically using the fake timers, and the developers can write the commoninit
,cleanup
logic inbeforeEach()/afterEach()
.But with
fakeAsync()
, we can not do the same thing for now.For example, we have a Component like this.
We need to call
fixture.destroy()
inside each tests, since each it() useit's own fakeAsync() and we need to clean up the timerId created in that
FakeAsyncZoneSpec. Otherwise the
fakeAsync()
will throwthere are still pending timers
error.Solution
So in this PR, there are two hooks functions are introduced.
With the hook functions, we can write case in this way.
This feature will be useful when we want to do some global cleanup
in
afterEach()
when the component have someasync
tasks(especially
setInterval
) running by 3rd party library.