@cerios/playwright-expectly
v1.4.0
Published
Comprehensive Playwright test matchers for strings, numbers, dates, arrays, objects, and locators. Simplify your E2E tests with intuitive assertions like toBeAlphanumeric, toHaveAscendingOrder, toBeInTheFuture, and 50+ more matchers.
Downloads
388
Readme
🎭 Playwright Expectly | By Cerios
Comprehensive Playwright test matchers for strings, numbers, dates, arrays, objects, and locators. Simplify your E2E tests with intuitive assertions like toBeAlphanumeric, toHaveAscendingOrder, toBeInTheFuture, and 50+ more matchers.
Features
- 🎯 50+ Custom Matchers — extensive validation for all data types
- 🔤 String Validation — email, URL, UUID, alphanumeric, and more
- 🔢 Number Arrays — sorting, statistics, ranges, and patterns
- 📅 Date Operations — comparisons, ranges, quarters, and business logic
- 🎨 Locator Assertions — DOM element validation and text formatting
- 📦 Object Arrays — sorting, uniqueness, and property validation
- 🤖 Fuzzy Matching — AI-generated text validation (separate
@cerios/playwright-expectly-fuzzypackage) - 💪 Type-Safe — full TypeScript support
- ⚡ Lightweight — only Playwright required
Installation
npm install @cerios/playwright-expectly --save-devPeer dependency: requires
@playwright/testto be installed.
Quick Start
Recommended: a single tests/support module for native expect
Create ONE shared module in your own project that extends Playwright's expect and captures the return value, then re-exports it. Every fixture file and spec file imports test/expect from this module — never straight from @playwright/test.
// tests/support/expect.ts
import "@cerios/playwright-expectly";
import { expect as baseExpect, test as base } from "@playwright/test";
import { expectlyMatchers } from "@cerios/playwright-expectly";
// MUST capture the return value — never call `.extend()` and discard it.
export const expect = baseExpect.extend(expectlyMatchers);
export const test = base;import { expect, test } from "./support/expect";
test("extended expect example", async ({ page }) => {
expect("[email protected]").toBeValidEmail();
expect([1, 2, 3, 4]).toHaveAscendingOrder();
expect(new Date("2025-01-02")).toBeCloseTo(new Date("2025-01-01"), { days: 1 });
await expect(page.locator(".username")).toBeAlphanumeric();
});Capturing the return value is the key detail. Playwright only mutates the original expect in place for matcher names that do not collide with built-ins. The Date matcher toBeCloseTo collides with Playwright's native numeric toBeCloseTo, so the Date version only exists on the value returned by .extend(...).
Standalone expectly
import { expectly } from "@cerios/playwright-expectly";
expectly("[email protected]").toBeValidEmail();
expectly([1, 2, 3, 4, 5]).toHaveAscendingOrder();
expectly(new Date()).toBeInTheFuture(new Date("2020-01-01"));
await expectly(page.locator(".username")).toBeAlphanumeric();Combining with @cerios/playwright-expectly-fuzzy, or your own matchers, via mergeExpects():
// tests/support/expect.ts
import { expect as baseExpect, mergeExpects, test as base } from "@playwright/test";
import { expectlyMatchers } from "@cerios/playwright-expectly";
import { expectlyFuzzyMatchers } from "@cerios/playwright-expectly-fuzzy";
const expectlyExpect = baseExpect.extend(expectlyMatchers);
const fuzzyExpect = baseExpect.extend(expectlyFuzzyMatchers);
export const expect = mergeExpects(baseExpect, expectlyExpect, fuzzyExpect);
export const test = base;If you only need the standalone package exports, the shorter form is also valid:
import { expectly } from "@cerios/playwright-expectly";
import { expectlyFuzzy } from "@cerios/playwright-expectly-fuzzy";
import { expect as baseExpect, mergeExpects, test as base } from "@playwright/test";
export const expect = mergeExpects(baseExpect, expectly, expectlyFuzzy);
export const test = base;Note: you may see a
setupExpectly()function in older docs or code — it is deprecated. Playwright'sexpect.extend()only mutates the originalexpectobject in place for matcher names that don't collide with a Playwright built-in.toBeCloseTocollides with Playwright's own built-in numeric matcher, sosetupExpectly()can never make the DatetoBeCloseTomatcher work, regardless of where it's called. Thetests/supportpattern above always works correctly.
Available Matchers
- String —
toBeValidEmail(),toBeValidUrl(),toBeUUID(),toBeAlphanumeric(),toStartWith(),toEndWith(),toMatchPattern(), and more — 📖 docs - Number Array —
toHaveAscendingOrder(),toHaveAverage(),toBeAllPositive(),toBeMonotonic(), and more — 📖 docs - Date —
toBeCloseTo(),toBeInTheFuture(),toBeSameDay(),toBeInQuarter(), and more — 📖 docs - Locator —
toBeAlphanumeric(),toBeUpperCase(),toHaveSrc(),toHaveHref(), and more — 📖 docs - Object Array —
toHaveObjectsInAscendingOrderBy(),toHaveOnlyUniqueObjects(), and more — 📖 docs - String Array —
toHaveAscendingOrder(),toHaveStrictlyAscendingOrder(),toHaveUniqueValues(), and more — 📖 docs - Generic —
toBeInteger(),toBeAnyOf(),toEqualPartially(),toBeNullish(), and more — 📖 docs
Links
License
MIT © Cerios
