Skip to content

Work out of the box with explicit imports from '@jest/globals' #506

Closed
@MattyBalaam

Description

@MattyBalaam

We are moving away from using global imports for our tests. Partly because we use Cypress and Jest in the same packages which causes type collisions, but also just because it is much easier to reason about.

Out of the box trying to use import '@testing-library/jest-dom' when using the explicit imports import { expect } from '@jest/globals' does not work.

I have spent a while and the best solution I have cobbled together in our local packages is to paste out parts of the types and augment, but I am sure there must be a better way!

import type { BaseExpect } from 'expect';
import type { addSerializer, SnapshotMatchers } from 'jest-snapshot';
import type { AsymmetricMatchers, Matchers } from '@jest/expect';
import { expect as jestGlobalExpect } from '@jest/globals';
import * as matchers from '@testing-library/jest-dom/matchers.js';

// BE AWARE this file may need updating from time to time as @testing-library/jest-dom package or @jest/globals is updated.

declare type PromiseMatchers<T = unknown> = {
  /**
   * Unwraps the reason of a rejected promise so any other matcher can be chained.
   * If the promise is fulfilled the assertion fails.
   */
  rejects: JestMatchers<Promise<void>, T> &
    Inverse<JestMatchers<Promise<void>, T>>;
  /**
   * Unwraps the value of a fulfilled promise so any other matcher can be chained.
   * If the promise is rejected the assertion fails.
   */
  resolves: JestMatchers<Promise<void>, T> &
    Inverse<JestMatchers<Promise<void>, T>>;
};

type JestMatchers<R extends void | Promise<void>, T> = Matchers<R, T> &
  SnapshotMatchers<R, T>;

declare type Inverse<Matchers> = {
  /**
   * Inverse next matcher. If you know how to test something, `.not` lets you test its opposite.
   */
  not: Matchers;
};

type JestExpect = {
  <T = unknown>(
    actual: T,
  ): JestMatchers<void, T> &
    Inverse<JestMatchers<void, T>> &
    PromiseMatchers<T> &
    matchers.TestingLibraryMatchers<unknown, T> &
    Inverse<matchers.TestingLibraryMatchers<unknown, T>>;
  addSnapshotSerializer: typeof addSerializer;
} & BaseExpect &
  AsymmetricMatchers &
  Inverse<Omit<AsymmetricMatchers, 'any' | 'anything'>>;

jestGlobalExpect.extend(matchers);

const expect = jestGlobalExpect as unknown as JestExpect;

export { expect };

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions