Skip to content
Merged
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
42 changes: 31 additions & 11 deletions packages/db/tests/expected-failure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import { describe, expect, it } from 'vitest'
import { expectAssertionFailure } from './expected-failure.js'
import { TraceAssertionError } from './trace-runner.js'

function assertionMismatch(checkpoint: number): Promise<void> {
try {
expect(`observed`).toBe(`expected`)
return Promise.resolve()
} catch (error) {
return Promise.reject(new TraceAssertionError(checkpoint, error))
}
}

describe(`expected failure guard`, () => {
it(`accepts an assertion mismatch at the expected checkpoint`, async () => {
const guarded = expectAssertionFailure(
() => {
try {
expect(`observed`).toBe(`expected`)
return Promise.resolve()
} catch (error) {
return Promise.reject(new TraceAssertionError(2, error))
}
},
{ checkpoint: 2 },
)
const guarded = expectAssertionFailure(() => assertionMismatch(2), {
checkpoint: 2,
})

await guarded()
})
Expand Down Expand Up @@ -43,6 +44,25 @@ describe(`expected failure guard`, () => {
await expect(guarded()).rejects.toBeInstanceOf(Error)
})

it(`accepts an assertion mismatch with the expected difference`, async () => {
const guarded = expectAssertionFailure(() => assertionMismatch(2), {
checkpoint: 2,
classify: ({ actual, expected }) =>
actual === `observed` && expected === `expected`,
})

await guarded()
})

it(`rejects an assertion mismatch with a different shape`, async () => {
const guarded = expectAssertionFailure(() => assertionMismatch(2), {
checkpoint: 2,
classify: ({ actual }) => actual === `different`,
})

await expect(guarded()).rejects.toBeInstanceOf(Error)
})

it(`accepts an assertion mismatch with the expected message`, async () => {
const guarded = expectAssertionFailure(
() =>
Expand Down
41 changes: 39 additions & 2 deletions packages/db/tests/expected-failure.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,57 @@
import { expect } from 'vitest'

export type AssertionDifference = {
actual: unknown
expected: unknown
}

type ExpectedAssertionFailure =
| { checkpoint: number }
| {
checkpoint: number
classify?: (difference: AssertionDifference) => boolean
}
| { message: string | RegExp }

function assertionDifference(error: unknown): AssertionDifference {
if (
typeof error !== `object` ||
error === null ||
!(`cause` in error) ||
typeof error.cause !== `object` ||
error.cause === null ||
!(`actual` in error.cause) ||
!(`expected` in error.cause)
) {
throw new Error(`Expected an assertion difference`)
}

return {
actual: error.cause.actual,
expected: error.cause.expected,
}
}

export function expectAssertionFailure<TArgs extends Array<unknown>>(
assertion: (...args: TArgs) => Promise<void>,
expected: ExpectedAssertionFailure,
): (...args: TArgs) => Promise<void> {
return async (...args) => {
if (`checkpoint` in expected) {
await expect(assertion(...args)).rejects.toMatchObject({
let error: unknown
try {
await assertion(...args)
} catch (caught) {
error = caught
}

expect(error).toMatchObject({
name: `TraceAssertionError`,
checkpoint: expected.checkpoint,
cause: { name: `AssertionError` },
})
if (expected.classify) {
expect(expected.classify(assertionDifference(error))).toBe(true)
}
return
}

Expand Down
Loading
Loading