Repository navigation
[Bug]: Custom DOM matchers not re-exported or wired into expect() #8
Description
Checklist
- I have searched the existing issues and have not found a duplicate
- I have read the README and documentation and have not found a solution
- I agree to follow the OpenNG Foundation Code of Conduct
What happened?
The custom DOM matchers documented in the README (toHaveText, toHaveAttribute, toExist, toHaveClass, toBeHidden, etc.) are meant to be usable directly on expect(...) after importing from @openng/spectator/vitest or @openng/spectator/jest, without any manual expect.extend() call. This is wired up via an ambient type declaration file that augments Vitest's Assertion interface (or Jest's Matchers interface).
The compiled JS bundles still contain a reference to this file:
/// <reference types="vitest" />
/// <reference path="./lib/matchers-types.ts" preserve="true" />(present in fesm2022/openng-spectator-vitest.mjs, fesm2022/openng-spectator-jest.mjs, and the root fesm2022/openng-spectator.mjs)
However, the corresponding matchers-types.d.ts file is not included anywhere in the published package, and none of the shipped .d.ts entry points (types/openng-spectator.d.ts, types/openng-spectator-vitest.d.ts, types/openng-spectator-jest.d.ts, types/openng-spectator-internals.d.ts) carry a /// <reference path="./lib/matchers-types.ts" /> directive of their own.
The ambient interface augmentation for Assertion<T> / Matchers<R> never happens, so TypeScript has no declaration for these matchers even though the underlying functions are fully implemented and exported at runtime.
Steps to reproduce
- Setup spectator with vitest per documentation
- Create a spec and try to use any DOM Matcher like this:
import { createPipeFactory, SpectatorPipe } from '@openng/spectator/vitest';
import { MyPipe } from './my.pipe';
describe('MyPipe', () => {
const createPipe = createPipeFactory(MyPipe);
it('renders text', () => {
const spectator = createPipe(`{{ 'test' | myPipe }}`);
expect(spectator.element).toHaveText('test');
// TS2339: Property 'toHaveText' does not exist on type 'Assertion<Element>'.
});
});- Observe compile error
Expected behavior
expect(element).toHaveText(...), expect(element).toHaveAttribute(...), expect(element).toExist(), and the other documented custom matchers should type-check without errors when importing from @openng/spectator/vitest or @openng/spectator/jest, matching the behavior documented in the README.
Actual behavior
TS2339: Property 'toHaveText' does not exist on type 'Assertion<Element>'.
...and the equivalent error for every other custom matcher listed in the README (confirmed with toHaveAttribute and toExist as well), even though the underlying matcher functions are still exported and the JS bundle still references the (missing) type augmentation file.
Minimal reproduction
https://github.com/MelGidsen/spectator-missing-declaration
Library version
1.0.0
Angular version
22.0.6
Node version
24.18.0
Package manager
npm
Browser(s)
Chrome
Environment details
- Test runner: Vitest (also affects the `/jest` entry point based on the same missing reference)Angular application setup
Standalone components
Angular context
- SSR (Server-Side Rendering) is involved
- Zoneless change detection is enabled
Relevant log output
X [ERROR] TS2339: Property 'toHaveText' does not exist on type 'Assertion<Element>'. [plugin angular-compiler]
src/app/to-string.pipe.spec.ts:12:30:
12 │ expect(spectator.element).toHaveText('test');Screenshots
No response
Additional context
Locally re-declaring the missing ambient interface augmentation as a workaround:
declare module 'vitest' {
interface Assertion<T = unknown> {
toHaveText(expected: string): void;
toHaveAttribute(attr: string, value?: string): void;
// ...
}
}...immediately resolves the TS2339 errors for all affected call sites, confirming this is purely a missing declaration file issue.
Activity
test: type-check custom matcher declarations in the built package
test: type-check custom matcher declarations in the built package
dominicbachmann commentedon Jul 9, 2026
@MelGidsen Thank you for reporting this! I created a fix in #9
fix: ship custom matcher type declarations in bundled d.ts
test(spectator): assert props accepts alias names in the type tests
test(spectator): assert props accepts alias names in the type tests
test(spectator): assert props accepts alias names in the type tests
fix(spectator): resolve input aliases in props and setInput (#16)