diff --git a/src/hooks.ts b/src/hooks.ts index 913b54116..0b2aca5ae 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -1,18 +1,17 @@ import { createHook } from './utils/hook' import { File, Suite, Task } from './types' -import { TaskResult } from '.' -export const beforeHook = createHook() -export const afterHook = createHook() +export const beforeAllHook = createHook() +export const afterAllHook = createHook() export const beforeEachHook = createHook<[Task]>() -export const afterEachHook = createHook<[Task, TaskResult]>() -export const beforeFileHook = createHook<[string]>() +export const afterEachHook = createHook<[Task]>() +export const beforeFileHook = createHook<[File]>() export const afterFileHook = createHook<[File]>() export const beforeSuiteHook = createHook<[Suite]>() export const afterSuiteHook = createHook<[Suite]>() -export const before = beforeHook.on -export const after = afterHook.on +export const beforeAll = beforeAllHook.on +export const afterAll = afterAllHook.on export const beforeEach = beforeEachHook.on export const afterEach = afterEachHook.on export const beforeFile = beforeFileHook.on diff --git a/src/index.ts b/src/index.ts index 1883d1de1..a564aa5dc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,3 +2,5 @@ export * from './types' export * from './suite' export * from './config' export * from './chai' + +export { beforeAll, afterAll, beforeEach, afterEach, beforeFile, afterFile, beforeSuite, afterSuite } from './hooks' diff --git a/src/run.ts b/src/run.ts index 3752a3b86..3974ea78b 100644 --- a/src/run.ts +++ b/src/run.ts @@ -5,23 +5,22 @@ import fg from 'fast-glob' import { clearContext, defaultSuite } from './suite' import { context } from './context' import { File, Options, Suite, Task, TaskResult } from './types' -import { afterEachHook, afterFileHook, afterHook, afterSuiteHook, beforeEachHook, beforeFileHook, beforeHook, beforeSuiteHook } from './hooks' +import { afterEachHook, afterFileHook, afterAllHook, afterSuiteHook, beforeEachHook, beforeFileHook, beforeAllHook, beforeSuiteHook } from './hooks' import { SnapshotPlugin } from './snapshot/index' export async function runTasks(tasks: Task[]) { const results: TaskResult[] = [] for (const task of tasks) { - const result: TaskResult = { task } await beforeEachHook.fire(task) + task.result = {} try { await task.fn() } catch (e) { - result.error = e + task.result.error = e } - results.push(result) - await afterEachHook.fire(task, result) + await afterEachHook.fire(task) } return results @@ -35,7 +34,6 @@ export async function collectFiles(files: string[]) { for (const filepath of files) { clearContext() - await beforeFileHook.fire(filepath) await import(filepath) const suites = [defaultSuite, ...context.suites] const collected: [Suite, Task[]][] = [] @@ -63,6 +61,7 @@ export async function collectFiles(files: string[]) { } export async function runFile(file: File) { + await beforeFileHook.fire(file) for (const [suite, tasks] of file.collected) { await beforeSuiteHook.fire(suite) @@ -74,14 +73,14 @@ export async function runFile(file: File) { if (suite.mode === 'run' || suite.mode === 'only') { // TODO: If there is a task with 'only', skip all others - const result = await runTasks(tasks) - for (const r of result) { - if (r.error === undefined) { - log(`${' '.repeat(indent * 2)}${c.inverse(c.green(' PASS '))} ${c.green(r.task.name)}`) + await runTasks(tasks) + for (const t of tasks) { + if (t.result && t.result.error === undefined) { + log(`${' '.repeat(indent * 2)}${c.inverse(c.green(' PASS '))} ${c.green(t.name)}`) } else { - console.error(`${' '.repeat(indent * 2)}${c.inverse(c.red(' FAIL '))} ${c.red(r.task.name)}`) - console.error(' '.repeat((indent + 2) * 2) + c.red(String(r.error))) + console.error(`${' '.repeat(indent * 2)}${c.inverse(c.red(' FAIL '))} ${c.red(t.name)}`) + console.error(' '.repeat((indent + 2) * 2) + c.red(String(t.result!.error))) process.exitCode = 1 } } @@ -105,7 +104,7 @@ export async function runFile(file: File) { export async function run(options: Options = {}) { const { rootDir = process.cwd() } = options - chai.use(SnapshotPlugin({ + chai.use(await SnapshotPlugin({ rootDir, update: options.updateSnapshot, })) @@ -125,14 +124,14 @@ export async function run(options: Options = {}) { return } - await beforeHook.fire() const files = await collectFiles(paths) + await beforeAllHook.fire() for (const file of files) { log(`${relative(process.cwd(), file.filepath)}`) await runFile(file) log() } - await afterHook.fire() + await afterAllHook.fire() log() } diff --git a/src/snapshot/index.ts b/src/snapshot/index.ts index e81fe32ce..d3c206123 100644 --- a/src/snapshot/index.ts +++ b/src/snapshot/index.ts @@ -1,6 +1,6 @@ import { use as chaiUse } from 'chai' import Snap from 'jest-snapshot' -import { after, before, beforeEach } from '../hooks' +import { afterAll, beforeEach } from '../hooks' import { SnapshotManager } from './manager' const { addSerializer } = Snap @@ -15,7 +15,7 @@ export interface SnapshotOptions { update?: boolean } -export function SnapshotPlugin(options: SnapshotOptions): ChaiPlugin { +export async function SnapshotPlugin(options: SnapshotOptions): Promise { const { rootDir } = options _manager = new SnapshotManager({ @@ -23,13 +23,12 @@ export function SnapshotPlugin(options: SnapshotOptions): ChaiPlugin { update: options.update, }) + _manager.snapshotResolver = await Snap.buildSnapshotResolver({ + transform: [], + rootDir, + } as any) + return function(chai, utils) { - before(async() => { - _manager.snapshotResolver = await Snap.buildSnapshotResolver({ - transform: [], - rootDir, - } as any) - }) beforeEach((task) => { _manager.setContext({ file: task.file?.filepath || task.name, @@ -37,7 +36,7 @@ export function SnapshotPlugin(options: SnapshotOptions): ChaiPlugin { fullTitle: [task.suite.name, task.name].filter(Boolean).join(' > '), }) }) - after(() => { + afterAll(() => { _manager.saveSnap() _manager.report() }) diff --git a/src/types.ts b/src/types.ts index ed60cca9b..03a2aab31 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,16 +10,16 @@ export interface Options extends UserOptions { updateSnapshot?: boolean } +export interface TaskResult { + error?: unknown +} + export interface Task { name: string suite: Suite fn: () => Promise | void file?: File -} - -export interface TaskResult { - task: Task - error?: unknown + result?: TaskResult } export type SuiteMode = 'run' | 'skip' | 'only' | 'todo'