Skip to content

setupExpectly() in playwright.config.ts does not enable Date-based toBeCloseTo on native Playwright expect #41

Open

Description

@vethman

Summary

Using setupExpectly() from @cerios/playwright-expectly inside playwright.config.ts does not reliably register the custom Date overload for toBeCloseTo in Playwright test workers.

Calls to native Playwright expect(date).toBeCloseTo(date, { minutes: 5 }) fall back to Playwright's built-in numeric matcher and fail with:

expect(received).toBeCloseTo(expected, precision)

Matcher error: expected value must be a number

Expected has type:  date
Expected has value: 2026-07-07T09:00:48.230Z

The expectation itself is correct for Expectly's Date matcher. The problem appears to be matcher registration/wiring, not the assertion intent.

Environment

  • OS: Windows
  • Node: 22.14.0
  • @playwright/test: 1.61.1
  • playwright-core: 1.61.1
  • @cerios/playwright-expectly: 1.3.5

Context

This started showing up after a dependency update.

Previous committed lockfile resolved:

  • @playwright/test: 1.60.0
  • playwright-core: 1.60.0
  • @cerios/playwright-expectly: 1.3.2

Current lockfile resolves:

  • @playwright/test: 1.61.1
  • playwright-core: 1.61.1
  • @cerios/playwright-expectly: 1.3.5

I have not fully isolated whether the regression comes from Playwright, Expectly, or the combination, but the behavior changed after this update.

Minimal reproduction

playwright.config.ts

import { setupExpectly } from "@cerios/playwright-expectly";
import { defineConfig } from "@playwright/test";

setupExpectly();

export default defineConfig({});

example.spec.ts

import { expect, test } from "@playwright/test";

test("date matcher", async () => {
	const now = new Date();
	expect(now).toBeCloseTo(new Date(now.getTime() + 1000), { seconds: 5 });
});

Actual behavior

The assertion uses Playwright's built-in numeric toBeCloseTo instead of Expectly's Date-based matcher.

expect(received).toBeCloseTo(expected, precision)

Matcher error: expected value must be a number

Expected has type:  date
Expected has value: 2026-07-07T09:00:48.230Z

Expected behavior

Expectly's custom Date matcher should be used, and the assertion should pass when the dates are within the allowed deviation.

Additional findings

The custom Date matcher itself appears to work.

This passes:

import { expectly } from "@cerios/playwright-expectly";

expectly(new Date()).toBeCloseTo(new Date(), { minutes: 5 });

This also passes:

import { expect, mergeExpects } from "@playwright/test";
import { expectlyDate } from "@cerios/playwright-expectly";

const customExpect = mergeExpects(expect, expectlyDate);
customExpect(new Date()).toBeCloseTo(new Date(), { minutes: 5 });

This suggests:

  • the Date matcher implementation exists and works
  • the failure is specific to wiring custom matchers onto native Playwright expect
  • when that wiring does not take effect, the call falls through to Playwright's built-in numeric toBeCloseTo

Relevant package note

The current published package source appears to already acknowledge this risk. The bundled setupExpectly() documentation says that calling it from playwright.config.ts is not guaranteed to affect the expect instance used inside test workers, and recommends calling it from a shared fixture/module in the same worker context.

That matches the behavior I am seeing.

Questions

  1. Is setupExpectly() in playwright.config.ts expected to work for native Playwright expect?
  2. If not, should the documentation steer users away from that pattern entirely?
  3. If yes, is this a regression in @cerios/playwright-expectly, Playwright, or the combination?

Current workaround options

  1. Use direct expectly(...) for custom matchers.
  2. Use a shared fixture/module that calls setupExpectly() in the same worker context as the tests.
  3. Use a merged expect object, for example mergeExpects(expect, expectlyDate).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions