@blotch/angular-lynx-testing-library 22.2.1 → 22.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -17
- package/dist/render.d.ts +5 -4
- package/dist/render.d.ts.map +1 -1
- package/dist/setup.js +42 -1
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -5,27 +5,43 @@ Testing utilities for [AngularLynx](https://github.com/Blotch-Smart-Frames/Angul
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
|
|
9
|
-
@lynx-js/testing-environment \
|
|
10
|
-
@testing-library/dom \
|
|
11
|
-
@testing-library/jest-dom \
|
|
12
|
-
vitest jsdom
|
|
8
|
+
ng generate @blotch/angular-lynx:add-testing
|
|
13
9
|
```
|
|
14
10
|
|
|
11
|
+
It installs this package (and Vitest and jsdom, if the project doesn't have them; `ng new` adds both) and makes sure `ng test` runs through AngularLynx's unit-test builder. To install it by hand: `npm install --save-dev @blotch/angular-lynx-testing-library`.
|
|
12
|
+
|
|
15
13
|
## Setup
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
None. Tests run with `ng test`, whose builder (`@blotch/angular-lynx-build:unit-test`, which `ng add` sets up) loads this package's setup before the tests whenever the project has it. There is no Vitest config or setup file to write.
|
|
16
|
+
|
|
17
|
+
The setup:
|
|
18
|
+
|
|
19
|
+
- Enables Angular JIT compilation (`@angular/compiler`), for components compiled at runtime
|
|
20
|
+
- Installs `LynxTestingEnv` on the jsdom window
|
|
21
|
+
- Switches to the Lynx main thread (where PAPI functions live)
|
|
22
|
+
- Polyfills PAPI functions the testing environment doesn't implement (`__GetParent`, `__QuerySelector`, etc.)
|
|
23
|
+
- Installs `@testing-library/jest-dom` matchers
|
|
24
|
+
|
|
25
|
+
`ng test` compiles the tests ahead of time, like the app, and checks templates strictly, as the Angular Language Service does: a component that uses Lynx elements imports `LYNX_ELEMENTS` from `@blotch/angular-lynx`. The examples below do.
|
|
26
|
+
|
|
27
|
+
### Without Angular CLI
|
|
28
|
+
|
|
29
|
+
Under plain Vitest, load the setup yourself and define the compile-time flags the AngularLynx runtime reads (the rsbuild plugin defines them in the app, and `ng test` sets them too):
|
|
18
30
|
|
|
19
31
|
```ts
|
|
20
32
|
// vitest.config.ts
|
|
21
33
|
import { defineConfig } from 'vitest/config';
|
|
22
|
-
import path from 'node:path';
|
|
23
34
|
|
|
24
35
|
export default defineConfig({
|
|
25
36
|
define: {
|
|
26
37
|
__DEV__: JSON.stringify(true),
|
|
27
38
|
__MAIN_THREAD__: JSON.stringify(true),
|
|
39
|
+
__WEB__: JSON.stringify(false),
|
|
40
|
+
__PROFILE__: JSON.stringify(false),
|
|
41
|
+
__ENABLE_SSR__: JSON.stringify(false),
|
|
28
42
|
},
|
|
43
|
+
// Angular's JIT compiler reads the metadata of legacy decorators.
|
|
44
|
+
oxc: { decorator: { legacy: true } },
|
|
29
45
|
test: {
|
|
30
46
|
environment: 'jsdom',
|
|
31
47
|
globals: true,
|
|
@@ -34,14 +50,6 @@ export default defineConfig({
|
|
|
34
50
|
});
|
|
35
51
|
```
|
|
36
52
|
|
|
37
|
-
The setup file:
|
|
38
|
-
|
|
39
|
-
- Enables Angular JIT compilation (`@angular/compiler`)
|
|
40
|
-
- Installs `LynxTestingEnv` on the jsdom window
|
|
41
|
-
- Switches to the Lynx main thread (where PAPI functions live)
|
|
42
|
-
- Polyfills PAPI functions the testing environment doesn't implement (`__GetParent`, `__QuerySelector`, etc.)
|
|
43
|
-
- Installs `@testing-library/jest-dom` matchers
|
|
44
|
-
|
|
45
53
|
## API
|
|
46
54
|
|
|
47
55
|
### `render(component, options?)`
|
|
@@ -144,10 +152,12 @@ console.log(Object.keys(eventMap));
|
|
|
144
152
|
|
|
145
153
|
```ts
|
|
146
154
|
import { Component } from '@angular/core';
|
|
155
|
+
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
|
|
147
156
|
import { render } from '@blotch/angular-lynx-testing-library';
|
|
148
157
|
|
|
149
158
|
@Component({
|
|
150
159
|
selector: 'greeting',
|
|
160
|
+
imports: [LYNX_ELEMENTS],
|
|
151
161
|
template: `<text>Hello, {{ name }}!</text>`,
|
|
152
162
|
})
|
|
153
163
|
class GreetingComponent {
|
|
@@ -163,13 +173,15 @@ it('renders the greeting', async () => {
|
|
|
163
173
|
### Injecting providers
|
|
164
174
|
|
|
165
175
|
```ts
|
|
166
|
-
import { InjectionToken, inject } from '@angular/core';
|
|
176
|
+
import { Component, InjectionToken, inject } from '@angular/core';
|
|
177
|
+
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
|
|
167
178
|
import { render } from '@blotch/angular-lynx-testing-library';
|
|
168
179
|
|
|
169
180
|
const GREETING = new InjectionToken<string>('GREETING');
|
|
170
181
|
|
|
171
182
|
@Component({
|
|
172
183
|
selector: 'test-greeting',
|
|
184
|
+
imports: [LYNX_ELEMENTS],
|
|
173
185
|
template: `<text>{{ greeting() }}</text>`,
|
|
174
186
|
})
|
|
175
187
|
class GreetingComponent {
|
|
@@ -190,12 +202,14 @@ Define the signal outside the component so both the component and the test can a
|
|
|
190
202
|
|
|
191
203
|
```ts
|
|
192
204
|
import { Component, signal, ChangeDetectionStrategy } from '@angular/core';
|
|
205
|
+
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
|
|
193
206
|
import { render, waitForUpdate } from '@blotch/angular-lynx-testing-library';
|
|
194
207
|
|
|
195
208
|
const count = signal(0);
|
|
196
209
|
|
|
197
210
|
@Component({
|
|
198
211
|
selector: 'test-counter',
|
|
212
|
+
imports: [LYNX_ELEMENTS],
|
|
199
213
|
template: `<text>{{ count() }}</text>`,
|
|
200
214
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
201
215
|
})
|
|
@@ -220,6 +234,7 @@ AngularLynx event bindings use Lynx prefixes: `(bindtap)`, `(catchtap)`, `(bindi
|
|
|
220
234
|
|
|
221
235
|
```ts
|
|
222
236
|
import { Component, signal, ChangeDetectionStrategy } from '@angular/core';
|
|
237
|
+
import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
|
|
223
238
|
import {
|
|
224
239
|
render,
|
|
225
240
|
fireEvent,
|
|
@@ -228,6 +243,7 @@ import {
|
|
|
228
243
|
|
|
229
244
|
@Component({
|
|
230
245
|
selector: 'test-button',
|
|
246
|
+
imports: [LYNX_ELEMENTS],
|
|
231
247
|
template: `
|
|
232
248
|
<view (bindtap)="increment()">
|
|
233
249
|
<text>{{ count() }}</text>
|
|
@@ -260,6 +276,7 @@ it('shows content conditionally', async () => {
|
|
|
260
276
|
|
|
261
277
|
@Component({
|
|
262
278
|
selector: 'test-if',
|
|
279
|
+
imports: [LYNX_ELEMENTS],
|
|
263
280
|
template: `@if (visible()) {
|
|
264
281
|
<text>Hello</text>
|
|
265
282
|
}`,
|
|
@@ -286,6 +303,7 @@ it('renders a dynamic list', async () => {
|
|
|
286
303
|
|
|
287
304
|
@Component({
|
|
288
305
|
selector: 'test-for',
|
|
306
|
+
imports: [LYNX_ELEMENTS],
|
|
289
307
|
template: `@for (item of items(); track item) {
|
|
290
308
|
<text>{{ item }}</text>
|
|
291
309
|
}`,
|
|
@@ -361,7 +379,7 @@ Template binding → PAPI registration → DOM listener key:
|
|
|
361
379
|
| Auto-cleanup env var | `PTL_SKIP_AUTO_CLEANUP` | — | `ATL_SKIP_AUTO_CLEANUP` |
|
|
362
380
|
| `renderHook()` | ✓ | — | — |
|
|
363
381
|
| Snapshot serializer | ✓ (RefProxy) | — | — |
|
|
364
|
-
| Vitest plugin | ✓ | — | —
|
|
382
|
+
| Vitest plugin | ✓ | — | — (`ng test` sets up) |
|
|
365
383
|
| Named fireEvent helpers | 30+ | 16 | 16 |
|
|
366
384
|
| Thread-aware fireEvent | ✓ | ✓ | — (single thread) |
|
|
367
385
|
| Async state helper | `waitSchedule()` | `waitForUpdate()` | `waitForUpdate()` |
|
package/dist/render.d.ts
CHANGED
|
@@ -48,10 +48,11 @@ export type RenderResult<Q extends Queries = typeof domQueries> = {
|
|
|
48
48
|
* - `componentRef.injector.get(Token)` — retrieve a service provided to the app.
|
|
49
49
|
* - `componentRef.instance.someSignal.set(v)` — drive writable signal state directly.
|
|
50
50
|
*
|
|
51
|
-
* Note: `componentRef.setInput()`
|
|
52
|
-
* signal inputs (input())
|
|
53
|
-
*
|
|
54
|
-
*
|
|
51
|
+
* Note: `componentRef.setInput()` needs the input metadata that ahead-of-time
|
|
52
|
+
* compilation registers for signal inputs (input()) and @Input() decorators.
|
|
53
|
+
* `ng test` compiles tests that way, so it works there. Under plain Vitest,
|
|
54
|
+
* which compiles components just in time, that metadata isn't available;
|
|
55
|
+
* expose writable signals on the component instance instead.
|
|
55
56
|
*/
|
|
56
57
|
componentRef: ComponentRef<unknown>;
|
|
57
58
|
} & BoundFunctions<typeof domQueries> & BoundFunctions<Q>;
|
package/dist/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EAEb,KAAK,IAAI,EACV,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,OAAO,IAAI,UAAU,EAEtB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,UAAU,IAAI;IACjE,SAAS,CAAC,EAAE,CAAC,QAAQ,GAAG,oBAAoB,CAAC,EAAE,CAAC;IAChD;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,UAAU,IAAI;IAChE;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;OAGG;IACH,QAAQ,EAAE,CAAC,CAAC,SAAS,OAAO,GAAG,CAAC,EAC9B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,EACxB,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,KACvB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B;;OAEG;IACH,UAAU,EAAE,MAAM,gBAAgB,CAAC;IACnC
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EAEb,KAAK,IAAI,EACV,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,OAAO,IAAI,UAAU,EAEtB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,UAAU,IAAI;IACjE,SAAS,CAAC,EAAE,CAAC,QAAQ,GAAG,oBAAoB,CAAC,EAAE,CAAC;IAChD;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,UAAU,IAAI;IAChE;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;OAGG;IACH,QAAQ,EAAE,CAAC,CAAC,SAAS,OAAO,GAAG,CAAC,EAC9B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,EACxB,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,KACvB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B;;OAEG;IACH,UAAU,EAAE,MAAM,gBAAgB,CAAC;IACnC;;;;;;;;;;;;OAYG;IACH,YAAY,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;CACrC,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,GACnC,cAAc,CAAC,CAAC,CAAC,CAAC;AAIpB,eAAO,MAAM,OAAO,QAAO,IAM1B,CAAC;AAEF,eAAO,MAAM,MAAM,GAAU,CAAC,SAAS,OAAO,GAAG,OAAO,UAAU,EAChE,eAAe,IAAI,CAAC,OAAO,CAAC,EAC5B,UAAS,aAAa,CAAC,CAAC,CAA0B,KACjD,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAkDzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,IAAI,CAKlD,CAAC"}
|
package/dist/setup.js
CHANGED
|
@@ -41,7 +41,48 @@ if (typeof Element.prototype.animate !== 'function') {
|
|
|
41
41
|
Element.prototype.animate = () => ({ cancel: () => { }, finished: Promise.resolve() });
|
|
42
42
|
}
|
|
43
43
|
// ─── Install LynxTestingEnv ──────────────────────────────────────────────────
|
|
44
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Turns the globals the testing environment is about to write into plain data
|
|
46
|
+
* properties, so the writes stay on the global object.
|
|
47
|
+
*
|
|
48
|
+
* Vitest's jsdom environment defines each jsdom window property on the global
|
|
49
|
+
* as an accessor. Since Vitest 5 its setter also writes the value through to
|
|
50
|
+
* the jsdom window. A thread switch copies every thread global onto the
|
|
51
|
+
* global, and two of those writes break the window: jsdom 30's
|
|
52
|
+
* `window.document` has no setter, so assigning it threw "Cannot set property
|
|
53
|
+
* document of [object Window] which has only a getter", and `_globalProxy` is
|
|
54
|
+
* the object jsdom returns as `dom.window`, so overwriting it made Vitest's
|
|
55
|
+
* teardown fail with "dom.window.close is not a function". The thread
|
|
56
|
+
* globals' values are the window's own (`document`, `Event`) or replace them
|
|
57
|
+
* only for the test (`requestAnimationFrame`), so keeping them on the global
|
|
58
|
+
* matches what Vitest 4 did.
|
|
59
|
+
*/
|
|
60
|
+
const keepWritesOffWindow = (keys) => {
|
|
61
|
+
for (const key of keys) {
|
|
62
|
+
const descriptor = Object.getOwnPropertyDescriptor(globalThis, key);
|
|
63
|
+
if (!descriptor?.set)
|
|
64
|
+
continue;
|
|
65
|
+
Object.defineProperty(globalThis, key, {
|
|
66
|
+
value: globalThis[key],
|
|
67
|
+
writable: true,
|
|
68
|
+
configurable: true,
|
|
69
|
+
enumerable: descriptor.enumerable,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
class AngularLynxTestingEnv extends LynxTestingEnv {
|
|
74
|
+
switchToMainThread() {
|
|
75
|
+
keepWritesOffWindow(Object.getOwnPropertyNames(this.mainThread.globalThis));
|
|
76
|
+
super.switchToMainThread();
|
|
77
|
+
}
|
|
78
|
+
switchToBackgroundThread() {
|
|
79
|
+
keepWritesOffWindow(Object.getOwnPropertyNames(this.backgroundThread.globalThis));
|
|
80
|
+
super.switchToBackgroundThread();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const lynxTestingEnv = new AngularLynxTestingEnv({
|
|
84
|
+
window: globalThis.window,
|
|
85
|
+
});
|
|
45
86
|
globalThis.lynxTestingEnv = lynxTestingEnv;
|
|
46
87
|
// Expose Node so @testing-library/dom detects element types correctly.
|
|
47
88
|
globalThis.Node = globalThis.window.Node;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blotch/angular-lynx-testing-library",
|
|
3
|
-
"version": "22.2.
|
|
3
|
+
"version": "22.2.2",
|
|
4
4
|
"description": "Testing utilities for AngularLynx apps",
|
|
5
5
|
"homepage": "https://github.com/Blotch-Smart-Frames/AngularLynx#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -43,14 +43,14 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@lynx-js/testing-environment": "^0.3.4",
|
|
46
|
-
"@testing-library/dom": "^10.4.1"
|
|
46
|
+
"@testing-library/dom": "^10.4.1",
|
|
47
|
+
"@testing-library/jest-dom": "^6.9.1"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@angular/compiler": "^22.2.1",
|
|
50
51
|
"@angular/core": "^22.2.1",
|
|
51
52
|
"@angular/platform-browser": "^22.2.1",
|
|
52
53
|
"@blotch/angular-lynx": "*",
|
|
53
|
-
"@testing-library/jest-dom": "^6.9.1",
|
|
54
54
|
"@types/node": "^22.0.0",
|
|
55
55
|
"jsdom": "^25.0.0",
|
|
56
56
|
"typescript": "~6.0.0"
|
|
@@ -60,5 +60,14 @@
|
|
|
60
60
|
"@angular/core": "^22.2.0",
|
|
61
61
|
"@angular/platform-browser": "^22.2.0",
|
|
62
62
|
"@blotch/angular-lynx": "^22.2.0"
|
|
63
|
+
},
|
|
64
|
+
"ng-update": {
|
|
65
|
+
"packageGroup": [
|
|
66
|
+
"@blotch/angular-lynx",
|
|
67
|
+
"@blotch/angular-lynx-build",
|
|
68
|
+
"@blotch/angular-lynx-testing-library",
|
|
69
|
+
"@blotch/rsbuild-plugin-angular-lynx",
|
|
70
|
+
"@blotch/angular-lynx-native"
|
|
71
|
+
]
|
|
63
72
|
}
|
|
64
73
|
}
|