• English
  • Testing

    @praha/byethrow-testing provides custom test matchers for asserting Result types, making your tests more expressive and readable.

    Installation

    npm install -D @praha/byethrow-testing

    Setup

    Jest

    Add the following to your Jest setup file (e.g. jest.setup.ts):

    jest.setup.ts
    import { 
    const expect: JestExpect
    expect
    } from '@jest/globals';
    import {
    import resultMatchers
    resultMatchers
    } from '@praha/byethrow-testing';
    import type {
    interface ResultMatchers<T>
    ResultMatchers
    } from '@praha/byethrow-testing';
    declare module 'expect' { interface
    interface Matchers<R extends void | Promise<void>, T = unknown>
    Matchers
    <
    function (type parameter) R in Matchers<R extends void | Promise<void>, T = unknown>
    R
    > extends
    interface ResultMatchers<T>
    ResultMatchers
    <
    function (type parameter) R in Matchers<R extends void | Promise<void>, T = unknown>
    R
    > {}
    }
    const expect: JestExpect
    expect
    .
    BaseExpect.extend(matchers: MatchersObject): void
    extend
    (
    import resultMatchers
    resultMatchers
    );

    Then reference the setup file in your Jest config:

    jest.setup.ts
    export default {
      
    setupFilesAfterEnv: string[]
    setupFilesAfterEnv
    : ['./jest.setup.ts'],
    };

    Vitest

    Add the following to your Vitest setup file (e.g. vitest.setup.ts):

    vitest.setup.ts
    import { 
    import resultMatchers
    resultMatchers
    } from '@praha/byethrow-testing';
    import {
    const expect: ExpectStatic
    expect
    } from 'vitest';
    import type {
    interface ResultMatchers<T>
    ResultMatchers
    } from '@praha/byethrow-testing';
    declare module 'vitest' { interface
    interface Matchers<T = any>
    Matchers
    <
    function (type parameter) T in Matchers<T = any>
    T
    > extends
    interface ResultMatchers<T>
    ResultMatchers
    <
    function (type parameter) T in Matchers<T = any>
    T
    > {}
    }
    const expect: ExpectStatic
    expect
    .
    ExpectStatic.extend: (expects: MatchersObject) => void
    extend
    (
    import resultMatchers
    resultMatchers
    );

    Then reference the setup file in your Vitest config:

    vitest.setup.ts
    import { 
    function defineConfig(config: UserConfig): UserConfig (+4 overloads)
    defineConfig
    } from 'vitest/config';
    export default
    function defineConfig(config: UserConfig): UserConfig (+4 overloads)
    defineConfig
    ({
    UserConfig.test?: InlineConfig | undefined

    Options for Vitest

    test
    : {
    InlineConfig.setupFiles?: string | string[] | undefined

    Path to setup files

    setupFiles
    : ['./vitest.setup.ts'],
    }, });

    Rstest

    Add the following to your Rstest setup file (e.g. rstest.setup.ts):

    rstest.setup.ts
    import { 
    import resultMatchers
    resultMatchers
    } from '@praha/byethrow-testing';
    import {
    const expect: ExpectStatic
    expect
    } from '@rstest/core';
    import type {
    interface ResultMatchers<T>
    ResultMatchers
    } from '@praha/byethrow-testing';
    declare module '@rstest/core' { interface
    interface Matchers<T>
    Matchers
    <
    function (type parameter) T in Matchers<T>
    T
    > extends
    interface ResultMatchers<T>
    ResultMatchers
    <
    function (type parameter) T in Matchers<T>
    T
    > {}
    }
    const expect: ExpectStatic
    expect
    .
    ExpectStatic_2.extend: (expects: MatchersObject<MatcherState>) => void
    extend
    (
    import resultMatchers
    resultMatchers
    );

    Then reference the setup file in your Rstest config:

    rstest.setup.ts
    import { 
    function defineConfig(config: RstestConfig): RstestConfig (+3 overloads)

    This function helps you to autocomplete configuration types. It accepts a Rstest config object, or a function that returns a config.

    defineConfig
    } from '@rstest/core';
    export default
    function defineConfig(config: RstestConfig): RstestConfig (+3 overloads)

    This function helps you to autocomplete configuration types. It accepts a Rstest config object, or a function that returns a config.

    defineConfig
    ({
    RstestConfig.setupFiles?: string | string[] | undefined

    Path to setup files. They will be run before each test file.

    setupFiles
    : ['./rstest.setup.ts'],
    });

    Matchers

    toBeSuccess(callback?)

    Asserts that the received value is a success Result. An optional callback receives the success value for further assertions.

    Without a callback, it only checks that the result is a success:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    import {
    const test: TestAPI

    Defines a test case with a given name and test function. The test function can optionally be configured with test options.

    @paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example
    // Define a simple test
    test('should add two numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    @example
    // Define a test with options
    test('should subtract two numbers', { retry: 3 }, () => {
      expect(subtract(5, 2)).toBe(3);
    });
    test
    ,
    const expect: ExpectStatic
    expect
    } from 'vitest';
    test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)

    Defines a test case with a given name and test function. The test function can optionally be configured with test options.

    @paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example
    // Define a simple test
    test('should add two numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    @example
    // Define a test with options
    test('should subtract two numbers', { retry: 3 }, () => {
      expect(subtract(5, 2)).toBe(3);
    });
    test
    ('result is success', () => {
    const
    const result: Result.Result<42, never>
    result
    =
    import Result
    Result
    .
    const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload)
    succeed
    (42);
    expect<Result.Result<42, never>>(actual: Result.Result<42, never>, message?: string): Assertion<Result.Result<42, never>> (+1 overload)
    expect
    (
    const result: Result.Result<42, never>
    result
    ).
    ResultMatchers<Result<42, never>>.toBeSuccess: (callback?: ((value: 42) => void) | undefined) => void
    toBeSuccess
    ();
    });

    With a callback, the success value is passed to it for further assertions:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    import {
    const test: TestAPI

    Defines a test case with a given name and test function. The test function can optionally be configured with test options.

    @paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example
    // Define a simple test
    test('should add two numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    @example
    // Define a test with options
    test('should subtract two numbers', { retry: 3 }, () => {
      expect(subtract(5, 2)).toBe(3);
    });
    test
    ,
    const expect: ExpectStatic
    expect
    } from 'vitest';
    test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)

    Defines a test case with a given name and test function. The test function can optionally be configured with test options.

    @paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example
    // Define a simple test
    test('should add two numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    @example
    // Define a test with options
    test('should subtract two numbers', { retry: 3 }, () => {
      expect(subtract(5, 2)).toBe(3);
    });
    test
    ('result is success with value', () => {
    const
    const result: Result.Result<42, never>
    result
    =
    import Result
    Result
    .
    const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload)
    succeed
    (42);
    expect<Result.Result<42, never>>(actual: Result.Result<42, never>, message?: string): Assertion<Result.Result<42, never>> (+1 overload)
    expect
    (
    const result: Result.Result<42, never>
    result
    ).
    ResultMatchers<Result<42, never>>.toBeSuccess: (callback?: ((value: 42) => void) | undefined) => void
    toBeSuccess
    ((
    value: 42
    value
    ) => {
    expect<42>(actual: 42, message?: string): Assertion<42> (+1 overload)
    expect
    (
    value: 42
    value
    ).
    JestAssertion<42>.toBe: <number>(expected: number) => void

    Checks that a value is what you expect. It calls Object.is to compare values. Don't use toBe with floating-point numbers.

    @exampleexpect (result).toBe(42); expect(status).toBe(true);
    toBe
    (42);
    }); });

    toBeFailure(callback?)

    Asserts that the received value is a failure Result. An optional callback receives the error value for further assertions.

    Without a callback, it only checks that the result is a failure:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    import {
    const test: TestAPI

    Defines a test case with a given name and test function. The test function can optionally be configured with test options.

    @paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example
    // Define a simple test
    test('should add two numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    @example
    // Define a test with options
    test('should subtract two numbers', { retry: 3 }, () => {
      expect(subtract(5, 2)).toBe(3);
    });
    test
    ,
    const expect: ExpectStatic
    expect
    } from 'vitest';
    test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)

    Defines a test case with a given name and test function. The test function can optionally be configured with test options.

    @paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example
    // Define a simple test
    test('should add two numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    @example
    // Define a test with options
    test('should subtract two numbers', { retry: 3 }, () => {
      expect(subtract(5, 2)).toBe(3);
    });
    test
    ('result is failure', () => {
    const
    const result: Result.Result<never, Error>
    result
    =
    import Result
    Result
    .
    const fail: <Error>(error: Error) => Result.Result<never, Error> (+1 overload)
    fail
    (new
    var Error: ErrorConstructor
    new (message?: string, options?: ErrorOptions) => Error (+1 overload)
    Error
    ('something went wrong'));
    expect<Result.Result<never, Error>>(actual: Result.Result<never, Error>, message?: string): Assertion<Result.Result<never, Error>> (+1 overload)
    expect
    (
    const result: Result.Result<never, Error>
    result
    ).
    ResultMatchers<Result<never, Error>>.toBeFailure: (callback?: ((error: Error) => void) | undefined) => void
    toBeFailure
    ();
    });

    With a callback, the error value is passed to it for further assertions:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    import {
    const test: TestAPI

    Defines a test case with a given name and test function. The test function can optionally be configured with test options.

    @paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example
    // Define a simple test
    test('should add two numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    @example
    // Define a test with options
    test('should subtract two numbers', { retry: 3 }, () => {
      expect(subtract(5, 2)).toBe(3);
    });
    test
    ,
    const expect: ExpectStatic
    expect
    } from 'vitest';
    test<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)

    Defines a test case with a given name and test function. The test function can optionally be configured with test options.

    @paramname - The name of the test or a function that will be used as a test name.@paramoptionsOrFn - Optional. The test options or the test function if no explicit name is provided.@paramoptionsOrTest - Optional. The test function or options, depending on the previous parameters.@throws{Error} If called inside another test function.@example
    // Define a simple test
    test('should add two numbers', () => {
      expect(add(1, 2)).toBe(3);
    });
    @example
    // Define a test with options
    test('should subtract two numbers', { retry: 3 }, () => {
      expect(subtract(5, 2)).toBe(3);
    });
    test
    ('result is failure with error', () => {
    const
    const result: Result.Result<never, Error>
    result
    =
    import Result
    Result
    .
    const fail: <Error>(error: Error) => Result.Result<never, Error> (+1 overload)
    fail
    (new
    var Error: ErrorConstructor
    new (message?: string, options?: ErrorOptions) => Error (+1 overload)
    Error
    ('something went wrong'));
    expect<Result.Result<never, Error>>(actual: Result.Result<never, Error>, message?: string): Assertion<Result.Result<never, Error>> (+1 overload)
    expect
    (
    const result: Result.Result<never, Error>
    result
    ).
    ResultMatchers<Result<never, Error>>.toBeFailure: (callback?: ((error: Error) => void) | undefined) => void
    toBeFailure
    ((
    error: Error
    error
    ) => {
    expect<string>(actual: string, message?: string): Assertion<string> (+1 overload)
    expect
    (
    error: Error
    error
    .
    Error.message: string
    message
    ).
    JestAssertion<string>.toBe: <string>(expected: string) => void

    Checks that a value is what you expect. It calls Object.is to compare values. Don't use toBe with floating-point numbers.

    @exampleexpect (result).toBe(42); expect(status).toBe(true);
    toBe
    ('something went wrong');
    }); });