Vitest: All 'describe' logic runs prior to all 'it'
The logic within the describe blocks is executed BEFORE any of the IT blocks are touched.
Think of describe logic as declaration that that gets processed before any of the IT implementation logic runs. Typically putting logic directly into describe blocks in vitest is NOT recommended.
Vitest: describe and beforeAll to power GIVEN/WHEN/THEN
With vitest we cannot put logic inside describe for GIVEN/WHEN/THEN setup as with-describe
However, we can use beforeAll to power GIVEN/WHEN/THEN:
GT-Sandbox-Snapshot
Code
import { describe, it, expect, beforeAll, afterAll } from 'vitest';/** * NOTE: There is a quirk in Vitest where console.log() statements inside beforeAll() * hooks get buffered separately and appear under "unknown test" in the output, making * them appear out of order even though execution happens correctly. This executionLog * array tracks the actual execution order and prints it at the end via afterAll() to * prove the GIVEN/WHEN/THEN flow executes as expected. */const executionLog: string[] = [];describe('GIVEN a user account', () => { let account: any; beforeAll(() => { executionLog.push("1) GIVEN - Setting up account context"); account = {balance: 0, transactions: []}; }); describe('WHEN depositing money', () => { beforeAll(() => { executionLog.push("2) WHEN - Depositing $100"); account.balance += 100; account.transactions.push({type: 'deposit', amount: 100}); }); it('THEN balance should increase', () => { executionLog.push("3) THEN - Checking balance"); expect(account.balance).toBe(100); }); it('THEN transaction should be recorded', () => { executionLog.push("4) THEN - Checking transaction"); expect(account.transactions).toHaveLength(1); expect(account.transactions[0].type).toBe('deposit'); }); describe('WHEN withdrawing money', () => { beforeAll(() => { executionLog.push("5) WHEN - Withdrawing $30"); account.balance -= 30; account.transactions.push({type: 'withdrawal', amount: 30}); }); it('THEN balance should reflect withdrawal', () => { executionLog.push("6) THEN - Checking new balance"); expect(account.balance).toBe(70); }); it('THEN both transactions should be recorded', () => { executionLog.push("7) THEN - Checking all transactions"); expect(account.transactions).toHaveLength(2); }); }); }); describe('WHEN checking balance without deposits', () => { let cleanAccount: any; beforeAll(() => { executionLog.push("8) WHEN - Creating clean account"); cleanAccount = {balance: 0, transactions: []}; }); it('THEN balance should be zero', () => { executionLog.push("9) THEN - Checking zero balance"); expect(cleanAccount.balance).toBe(0); }); }); afterAll(() => { console.log("\n=== EXECUTION ORDER ==="); executionLog.forEach(log => console.log(log)); console.log("======================\n"); });});
Command to reproduce:
gt.sandbox.checkout.commit 2f99590ccd576a626a1c \&& cd "${GT_SANDBOX_REPO}" \&& cmd.run.announce "./run.sh"
Recorded output of command:
up to date, audited 182 packages in 614ms33 packages are looking for funding run `npm fund` for details2 moderate severity vulnerabilitiesTo address all issues (including breaking changes), run: npm audit fix --forceRun `npm audit` for details.> glassthought-sandbox@1.0.0 test> vitest run RUN v0.34.6 /home/nickolaykondratyev/git_repos/glassthought-sandbox ✓ src/main.test.ts (5 tests) 3msstdout | unknown test=== EXECUTION ORDER ===1) GIVEN - Setting up account context2) WHEN - Depositing $1003) THEN - Checking balance4) THEN - Checking transaction5) WHEN - Withdrawing $306) THEN - Checking new balance7) THEN - Checking all transactions8) WHEN - Creating clean account9) THEN - Checking zero balance====================== Test Files 1 passed (1) Tests 5 passed (5) Start at 11:39:40 Duration 463ms (transform 33ms, setup 0ms, collect 16ms, tests 3ms, environment 0ms, prepare 79ms)
Notes
it blocks that are in the outer level THEN describe.beforeAll will have priority in order of execution.
describe.beforeAll will execute once for that describe block.
Any code that you would like to put directly into describe block likely belongs in describe.beforeAll to act as you would expect (See with-describe)