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
56 changes: 28 additions & 28 deletions src/assert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { assert, Assertion } from 'chai'
import Macroable from '@poppinss/macroable'
import { AssertionError } from 'assertion-error'

import type { AssertContract, ChaiAssert } from './types.js'
import type { AnyErrorConstructor, AssertContract, ChaiAssert } from './types.js'

/**
* The Assert class is derived from chai.assert to allow support
Expand Down Expand Up @@ -1169,17 +1169,17 @@ export class Assert extends Macroable implements AssertContract {
* assert.throws(foo, 'blow up') // passes
* assert.throws(foo, 'failed') // fails
*/
throws(fn: () => void, message?: string): void
throws(fn: () => void, errType: RegExp | ErrorConstructor, message?: string): void
throws(fn: () => unknown, message?: string): void
throws(fn: () => unknown, errType: RegExp | AnyErrorConstructor, message?: string): void
throws(
fn: () => void,
constructor: ErrorConstructor,
fn: () => unknown,
constructor: AnyErrorConstructor,
regExp: RegExp | string,
message?: string
): void
throws(
fn: () => void,
errType?: RegExp | ErrorConstructor | string,
fn: () => unknown,
errType?: RegExp | AnyErrorConstructor | string,
regExp?: RegExp | string,
message?: string
): void {
Expand All @@ -1201,18 +1201,18 @@ export class Assert extends Macroable implements AssertContract {
* assert.doesNotThrow(foo, 'failed') // passes
* assert.doesNotThrow(() => {}) // passes
*/
doesNotThrow(fn: () => void, message?: string): void
doesNotThrow(fn: () => void, regExp: RegExp): void
doesNotThrow(fn: () => void, constructor: ErrorConstructor, message?: string): void
doesNotThrow(fn: () => unknown, message?: string): void
doesNotThrow(fn: () => unknown, regExp: RegExp): void
doesNotThrow(fn: () => unknown, constructor: AnyErrorConstructor, message?: string): void
doesNotThrow(
fn: () => void,
constructor: ErrorConstructor,
fn: () => unknown,
constructor: AnyErrorConstructor,
regExp: RegExp | string,
message?: string
): void
doesNotThrow(
fn: () => void,
errType?: RegExp | ErrorConstructor | string,
fn: () => unknown,
errType?: RegExp | AnyErrorConstructor | string,
regExp?: RegExp | string,
message?: string
): void {
Expand Down Expand Up @@ -1916,21 +1916,21 @@ export class Assert extends Macroable implements AssertContract {
* @example
* await assert.reject(() => throw new Error(''))
*/
async rejects(fn: () => void, message?: string): Promise<void>
async rejects(fn: () => unknown, message?: string): Promise<void>
async rejects(
fn: () => void | Promise<void>,
errType: RegExp | ErrorConstructor,
fn: () => unknown | Promise<unknown>,
errType: RegExp | AnyErrorConstructor,
message?: string
): Promise<void>
async rejects(
fn: () => void | Promise<void>,
constructor: ErrorConstructor,
fn: () => unknown | Promise<unknown>,
constructor: AnyErrorConstructor,
regExp: RegExp | string,
message?: string
): Promise<void>
async rejects(
fn: () => void | Promise<void>,
errType?: RegExp | ErrorConstructor | string,
fn: () => unknown | Promise<unknown>,
errType?: RegExp | AnyErrorConstructor | string,
regExp?: RegExp | string,
message?: string
): Promise<void> {
Expand Down Expand Up @@ -2056,21 +2056,21 @@ export class Assert extends Macroable implements AssertContract {
* async () => return 'foo',
* ) // passes
*/
async doesNotReject(fn: () => void, message?: string): Promise<void>
async doesNotReject(fn: () => unknown, message?: string): Promise<void>
async doesNotReject(
fn: () => void | Promise<void>,
errType: RegExp | ErrorConstructor,
fn: () => unknown | Promise<unknown>,
errType: RegExp | AnyErrorConstructor,
message?: string
): Promise<void>
async doesNotReject(
fn: () => void | Promise<void>,
constructor: ErrorConstructor,
fn: () => unknown | Promise<unknown>,
constructor: AnyErrorConstructor,
regExp: RegExp | string,
message?: string
): Promise<void>
async doesNotReject(
fn: () => void | Promise<void>,
errType?: RegExp | ErrorConstructor | string,
fn: () => unknown | Promise<unknown>,
errType?: RegExp | AnyErrorConstructor | string,
regExp?: RegExp | string,
message?: string
): Promise<void> {
Expand Down
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,9 @@ export type AssertContract = Omit<
>

export type PluginConfig = {}

/**
* A more flexible error constructor than `ErrorConstructor` type that allows custom
* error classes with any constructor signature
*/
export type AnyErrorConstructor = new (...args: any[]) => Error
78 changes: 78 additions & 0 deletions tests/assert/assert.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,48 @@ test.describe('assert', function () {
}, 'blah: expected {} to be a function')
})

test('throws with custom error constructor with multiple arguments', function () {
const assert = new Assert()

class CustomError extends Error {
constructor(
public code: number,
message: string
) {
super(message)
}
}

assert.throws(() => {
throw new CustomError(500, 'Internal Server Error')
}, CustomError)

assert.throws(
() => {
throw new CustomError(404, 'Not Found')
},
CustomError,
'Not Found'
)

expectError(() => {
assert.throws(() => {
throw new CustomError(500, 'Internal Server Error')
}, TypeError)
}, "expected [Function] to throw 'TypeError' but 'Error: Internal Server Error' was thrown")
})

test('throws with function returning non-void value', function () {
const assert = new Assert()

function myThing(): string {
throw new Error('Something went wrong')
}

assert.throws(() => myThing(), Error)
assert.throws(() => myThing(), 'Something went wrong')
})

test('rejects', async function () {
const assert = new Assert()

Expand Down Expand Up @@ -1729,6 +1771,42 @@ test.describe('assert', function () {
}, 'blah: expected {} to be a function')
})

test('rejects with custom error constructor with multiple arguments', async function () {
const assert = new Assert()

class CustomError extends Error {
constructor(
public code: number,
message: string
) {
super(message)
}
}

await assert.rejects(async function () {
throw new CustomError(500, 'Internal Server Error')
}, CustomError)

await assert.rejects(
async function () {
throw new CustomError(404, 'Not Found')
},
CustomError,
'Not Found'
)
})

test('rejects with function returning non-void value', async function () {
const assert = new Assert()

async function myThing(): Promise<string> {
throw new Error('Something went wrong')
}

await assert.rejects(() => myThing(), Error)
await assert.rejects(() => myThing(), 'Something went wrong')
})

test('doesNotThrows', function () {
const assert = new Assert()

Expand Down
Loading