Skip to content
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

fix(jest-circus): reverse order of afterEach, afterAll hooks #12861

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

- `[jest-worker]` Make `JestWorkerFarm` helper type to include methods of worker module that take more than one argument ([#12839](https://github.com/facebook/jest/pull/12839))
- `[jest-docblock]` Handle multiline comments in parseWithComments ([#12845](https://github.com/facebook/jest/pull/12845))
- `[jest-circus]` Run `afterAll` and `afterEach` hooks in the correct order ([#12861](https://github.com/facebook/jest/pull/12861))

### Chore & Maintenance

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,68 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`afterEach & afterAll run in reverse order 1`] = `
"add_hook: beforeAll
add_hook: afterAll
add_hook: beforeEach
add_hook: afterEach
add_test:
start_describe_definition: Scoped / Nested block
add_hook: beforeAll
add_hook: afterAll
add_hook: beforeEach
add_hook: afterEach
add_test:
finish_describe_definition: Scoped / Nested block
run_start
run_describe_start: ROOT_DESCRIBE_BLOCK
hook_start: beforeAll
1 - beforeAll
hook_success: beforeAll
test_start:
hook_start: beforeEach
1 - beforeEach
hook_success: beforeEach
test_fn_start:
1 - test
test_fn_success:
hook_start: afterEach
1 - afterEach
hook_success: afterEach
test_done:
run_describe_start: Scoped / Nested block
hook_start: beforeAll
2 - beforeAll
hook_success: beforeAll
test_start:
hook_start: beforeEach
1 - beforeEach
hook_success: beforeEach
hook_start: beforeEach
2 - beforeEach
hook_success: beforeEach
test_fn_start:
2 - test
test_fn_success:
hook_start: afterEach
2 - afterEach
hook_success: afterEach
hook_start: afterEach
1 - afterEach
hook_success: afterEach
test_done:
hook_start: afterAll
2 - afterAll
hook_success: afterAll
run_describe_finish: Scoped / Nested block
hook_start: afterAll
1 - afterAll
hook_success: afterAll
run_describe_finish: ROOT_DESCRIBE_BLOCK
run_finish

unhandledErrors: 0"
`;

exports[`beforeAll is exectued correctly 1`] = `
"start_describe_definition: describe 1
add_hook: beforeAll
Expand Down
19 changes: 19 additions & 0 deletions packages/jest-circus/src/__tests__/hooks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,22 @@ test('beforeAll is exectued correctly', () => {

expect(stdout).toMatchSnapshot();
});

test('afterEach & afterAll run in reverse order', () => {
const {stdout} = runTest(`
beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));
test('', () => console.log('1 - test'));
describe('Scoped / Nested block', () => {
beforeAll(() => console.log('2 - beforeAll'));
afterAll(() => console.log('2 - afterAll'));
beforeEach(() => console.log('2 - beforeEach'));
afterEach(() => console.log('2 - afterEach'));
test('', () => console.log('2 - test'));
});
`);

expect(stdout).toMatchSnapshot();
});
28 changes: 25 additions & 3 deletions packages/jest-circus/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ export const getAllHooksForDescribe = (
}
}

// afterAll hooks should run in reverse order
// https://jestjs.io/docs/setup-teardown#scoping
result.afterAll.reverse();

return result;
};

Expand All @@ -141,20 +145,38 @@ export const getEachHooksForTest = (test: Circus.TestEntry): TestHooks => {

do {
const beforeEachForCurrentBlock = [];
const afterEachForCurrentBlock = [];
for (const hook of block.hooks) {
switch (hook.type) {
case 'beforeEach':
beforeEachForCurrentBlock.push(hook);
break;
case 'afterEach':
result.afterEach.push(hook);
afterEachForCurrentBlock.push(hook);
break;
}
}
// 'beforeEach' hooks are executed from top to bottom, the opposite of the
// way we traversed it.

// For simplicity, get both hook types in declaration order.
// This comment shows the iteration order:
//
// describe(() => { // <-- block.parent
// beforeEach() // 3
// beforeEach() // 4
// describe(() => { // <-- test.parent
// beforeEach() // 1
// beforeEach() // 2
// test() // <-- we start here
// })
// })
result.beforeEach = [...beforeEachForCurrentBlock, ...result.beforeEach];
result.afterEach = [...afterEachForCurrentBlock, ...result.afterEach];
} while ((block = block.parent));

// afterAll hooks should run in reverse order
// https://jestjs.io/docs/setup-teardown#scoping
result.afterEach.reverse();

return result;
};

Expand Down