@cdevhub/ngx-tw 0.8.0 → 0.9.0
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/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +7 -7
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-popover-testing.mjs +32 -123
- package/fesm2022/cdevhub-ngx-tw-popover-testing.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tooltip-testing.mjs +26 -118
- package/fesm2022/cdevhub-ngx-tw-tooltip-testing.mjs.map +1 -1
- package/index.json +1 -1
- package/package.json +1 -1
- package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +7 -7
- package/types/cdevhub-ngx-tw-popover-testing.d.ts +13 -62
- package/types/cdevhub-ngx-tw-tooltip-testing.d.ts +14 -62
package/package.json
CHANGED
|
@@ -80,8 +80,8 @@ declare class CommandPaletteHarness extends ComponentHarness {
|
|
|
80
80
|
*
|
|
81
81
|
* **The overlay is still attached when this resolves.** The component defers
|
|
82
82
|
* the detach behind a leave animation, so a caller asserting on `isOpen()`
|
|
83
|
-
* immediately afterwards will still see `true`. Wait for the
|
|
84
|
-
* asserting —
|
|
83
|
+
* immediately afterwards will still see `true`. Wait for the detach before
|
|
84
|
+
* asserting — by reading the document, never by polling a harness method.
|
|
85
85
|
*
|
|
86
86
|
* That caveat is deliberate rather than hidden behind a poll. An earlier
|
|
87
87
|
* version looped on `isOpen()` until the panel detached, which reads better
|
|
@@ -92,11 +92,11 @@ declare class CommandPaletteHarness extends ComponentHarness {
|
|
|
92
92
|
* failing it. A harness that can hang is worse than one that makes the caller
|
|
93
93
|
* wait explicitly.
|
|
94
94
|
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
95
|
+
* Wait by polling the document for the panel to leave, under your own
|
|
96
|
+
* deadline — `document.querySelector('tw-command-palette-overlay') === null`
|
|
97
|
+
* needs no stabilization, so it can neither hang nor burn a fixed sleep. The
|
|
98
|
+
* `closes with Escape` case in `command-palette-harness.spec.ts` is the
|
|
99
|
+
* worked example, and is this method's coverage.
|
|
100
100
|
*/
|
|
101
101
|
close(): Promise<void>;
|
|
102
102
|
/** Moves the active descendant down one row. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentHarness,
|
|
1
|
+
import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
2
|
|
|
3
3
|
/** Filters accepted by `PopoverHarness.with`. */
|
|
4
4
|
interface PopoverHarnessFilters extends BaseHarnessFilters {
|
|
@@ -8,40 +8,6 @@ interface PopoverHarnessFilters extends BaseHarnessFilters {
|
|
|
8
8
|
/**
|
|
9
9
|
* Harness for a `[twPopover]` trigger and the panel it opens.
|
|
10
10
|
*
|
|
11
|
-
* ## Nothing here awaits application stabilization, and that is load-bearing
|
|
12
|
-
*
|
|
13
|
-
* `TestbedHarnessEnvironment` routes every `TestElement` operation through
|
|
14
|
-
* `forceStabilize()` — `fixture.detectChanges()` then
|
|
15
|
-
* `await fixture.whenStable()` — and that await resolves only when Angular's
|
|
16
|
-
* `PendingTasks` set is empty. Under full-suite contention it was observed
|
|
17
|
-
* **not to resolve at all**, and everything built on it hung for the whole test
|
|
18
|
-
* budget instead of failing. This harness was withdrawn twice for that.
|
|
19
|
-
*
|
|
20
|
-
* Every method body therefore runs inside CDK's `manualChangeDetection()`,
|
|
21
|
-
* which sets the flag `forceStabilize()` early-returns on, and so does
|
|
22
|
-
* acquisition, via {@link load} / {@link loadAll}. The spec beside this file
|
|
23
|
-
* adds the third piece: it never awaits `fixture.whenStable()` either, not even
|
|
24
|
-
* in `beforeEach`. All three were needed — each of the two CI failures during
|
|
25
|
-
* this restoration was traced to one of them, and the second landed on
|
|
26
|
-
* `tooltip` rather than here, which is how it became clear the fault belongs to
|
|
27
|
-
* whichever harness spec lands in the unlucky worker slot rather than to any
|
|
28
|
-
* one component. `grep -c whenStable` over this file and its spec returns zero,
|
|
29
|
-
* which is the whole claim and is checkable in one command rather than by
|
|
30
|
-
* counting green runs. The spec pins the rest with tests that hold a real
|
|
31
|
-
* `PendingTasks` entry open across acquisition and every method.
|
|
32
|
-
*
|
|
33
|
-
* Why the application stops stabilizing is **not** known; this removes the
|
|
34
|
-
* dependency rather than curing it.
|
|
35
|
-
*
|
|
36
|
-
* The cost is that change detection is not forced on your behalf. Instead every
|
|
37
|
-
* method spends one macrotask on the scheduler (see {@link afterSchedulerTick}),
|
|
38
|
-
* which covers everything already scheduled — including the panel's first
|
|
39
|
-
* render. What it does not cover is state behind the component's own timers:
|
|
40
|
-
* {@link close} dispatches Escape and returns, and the panel detaches only after
|
|
41
|
-
* the 120 ms leave window in `popover.ts`. Wait for that by polling the DOM —
|
|
42
|
-
* `document.querySelector` needs no stabilization and so can neither hang nor
|
|
43
|
-
* burn a fixed interval — and only then read through the harness.
|
|
44
|
-
*
|
|
45
11
|
* ## Loading it
|
|
46
12
|
*
|
|
47
13
|
* The host is the trigger, which lives in the fixture, so the ordinary
|
|
@@ -57,6 +23,17 @@ interface PopoverHarnessFilters extends BaseHarnessFilters {
|
|
|
57
23
|
* against `aria-haspopup="dialog"` — which the two date-picker triggers also
|
|
58
24
|
* carry — is needed.
|
|
59
25
|
*
|
|
26
|
+
* ## Waiting for the panel
|
|
27
|
+
*
|
|
28
|
+
* Every method stabilizes the fixture the way CDK harnesses always do, which
|
|
29
|
+
* covers change detection but **not** the component's own timers: `popover.ts`
|
|
30
|
+
* detaches the panel behind a hard-coded 120 ms leave window driven by a plain
|
|
31
|
+
* `setTimeout`, which Angular's `PendingTasks` does not track, so
|
|
32
|
+
* `whenStable()` does not wait for it. {@link close} therefore dispatches
|
|
33
|
+
* Escape and returns while the panel is still attached. Poll the DOM for its
|
|
34
|
+
* removal — `document.querySelector('tw-popover-overlay')` — and only then read
|
|
35
|
+
* through the harness.
|
|
36
|
+
*
|
|
60
37
|
* ## The panel is detached, not disposed
|
|
61
38
|
*
|
|
62
39
|
* Unlike `tw-select`, closing a popover **detaches** the portal and keeps the
|
|
@@ -66,29 +43,6 @@ interface PopoverHarnessFilters extends BaseHarnessFilters {
|
|
|
66
43
|
*/
|
|
67
44
|
declare class PopoverHarness extends ComponentHarness {
|
|
68
45
|
static hostSelector: string;
|
|
69
|
-
/**
|
|
70
|
-
* Acquires one harness without waiting for the application to stabilize —
|
|
71
|
-
* the counterpart to the guarantee the methods below make.
|
|
72
|
-
*
|
|
73
|
-
* `loader.getHarness(...)` is CDK's own acquisition path and it stabilizes:
|
|
74
|
-
* `getAllRawElements` calls `forceStabilize()`, and `HarnessPredicate`
|
|
75
|
-
* filtering routes through `parallel()`, which asks *every* active fixture in
|
|
76
|
-
* the worker to settle. Both await `fixture.whenStable()`, which is the one
|
|
77
|
-
* thing this harness exists to avoid — and the failure that withdrew it was
|
|
78
|
-
* observed there, at acquisition, before any method had run.
|
|
79
|
-
*
|
|
80
|
-
* So acquisition is wrapped too, and `manualChangeDetection()` nests: the
|
|
81
|
-
* inner `parallel()` sees the flag already set and skips the stabilization
|
|
82
|
-
* entirely. **Render the fixture first** (`fixture.detectChanges()`), because
|
|
83
|
-
* nothing here will do it for you; an unrendered fixture fails loudly with
|
|
84
|
-
* CDK's "failed to find element" rather than returning something wrong.
|
|
85
|
-
*
|
|
86
|
-
* Plain `loader.getHarness(PopoverHarness)` still works and is still supported.
|
|
87
|
-
* This is the path to use when a suite must not be able to hang.
|
|
88
|
-
*/
|
|
89
|
-
static load(loader: HarnessLoader, options?: PopoverHarnessFilters): Promise<PopoverHarness>;
|
|
90
|
-
/** {@link load} for every matching trigger rather than the first. */
|
|
91
|
-
static loadAll(loader: HarnessLoader, options?: PopoverHarnessFilters): Promise<PopoverHarness[]>;
|
|
92
46
|
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
93
47
|
static with(options?: PopoverHarnessFilters): HarnessPredicate<PopoverHarness>;
|
|
94
48
|
/** The text currently rendered in the trigger, trimmed. */
|
|
@@ -122,10 +76,7 @@ declare class PopoverHarness extends ComponentHarness {
|
|
|
122
76
|
* while the popover is closed, because the panel does not exist then.
|
|
123
77
|
*/
|
|
124
78
|
hasArrow(): Promise<boolean>;
|
|
125
|
-
/**
|
|
126
|
-
* The panel element, or `null` when the popover is closed. Callers are already
|
|
127
|
-
* inside `manualChangeDetection`.
|
|
128
|
-
*/
|
|
79
|
+
/** The panel element, or `null` when the popover is closed. */
|
|
129
80
|
private getPanel;
|
|
130
81
|
/**
|
|
131
82
|
* The id of this trigger's own panel, or `null` when closed. Scoping by
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentHarness,
|
|
1
|
+
import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
2
|
|
|
3
3
|
/** Filters accepted by `TooltipHarness.with`. */
|
|
4
4
|
interface TooltipHarnessFilters extends BaseHarnessFilters {
|
|
@@ -13,44 +13,6 @@ interface TooltipHarnessFilters extends BaseHarnessFilters {
|
|
|
13
13
|
* configuration, not state, and a harness method for any of them would freeze an
|
|
14
14
|
* API that may still move — so none is offered.
|
|
15
15
|
*
|
|
16
|
-
* ## Nothing here awaits application stabilization, and that is load-bearing
|
|
17
|
-
*
|
|
18
|
-
* `TestbedHarnessEnvironment` routes every `TestElement` operation through
|
|
19
|
-
* `forceStabilize()` — `fixture.detectChanges()` then
|
|
20
|
-
* `await fixture.whenStable()` — and that await resolves only when Angular's
|
|
21
|
-
* `PendingTasks` set is empty. Under full-suite contention it was observed
|
|
22
|
-
* **not to resolve at all**, and everything built on it hung for the whole test
|
|
23
|
-
* budget instead of failing. This harness was withdrawn once for that, on five
|
|
24
|
-
* green local runs followed by one red CI run.
|
|
25
|
-
*
|
|
26
|
-
* Every method body therefore runs inside CDK's `manualChangeDetection()`,
|
|
27
|
-
* which sets the flag `forceStabilize()` early-returns on, and so does
|
|
28
|
-
* acquisition, via {@link load} / {@link loadAll}. The spec beside this file
|
|
29
|
-
* adds the third piece: it never awaits `fixture.whenStable()` either, not even
|
|
30
|
-
* in `beforeEach`. All three were needed — each of the two CI failures during
|
|
31
|
-
* this restoration was traced to one of them, and the second landed on
|
|
32
|
-
* `popover` rather than here, which is how it became clear the fault belongs to
|
|
33
|
-
* whichever harness spec lands in the unlucky worker slot rather than to any
|
|
34
|
-
* one component. `grep -c whenStable` over this file and its spec returns zero,
|
|
35
|
-
* which is the whole claim and is checkable in one command rather than by
|
|
36
|
-
* counting green runs. The spec pins the rest with tests that hold a real
|
|
37
|
-
* `PendingTasks` entry open across acquisition and every method.
|
|
38
|
-
*
|
|
39
|
-
* Why the application stops stabilizing is **not** known; this removes the
|
|
40
|
-
* dependency rather than curing it.
|
|
41
|
-
*
|
|
42
|
-
* The cost is that change detection is not forced on your behalf. Instead every
|
|
43
|
-
* method spends one macrotask on the scheduler (see {@link afterSchedulerTick}),
|
|
44
|
-
* which covers everything already scheduled — including the panel's first
|
|
45
|
-
* render, which is why {@link getTooltipText} does not come back empty on a
|
|
46
|
-
* tooltip that has only just attached. What it does not cover is state behind
|
|
47
|
-
* the component's own timers: {@link show} and {@link hide} dispatch the
|
|
48
|
-
* interaction and return, and the panel appears or detaches only once
|
|
49
|
-
* `twTooltipShowDelay` (200 ms by default) or `twTooltipHideDelay` (150 ms)
|
|
50
|
-
* elapses. Set both to `0` in a fixture, poll the DOM for the panel —
|
|
51
|
-
* `document.querySelector` needs no stabilization and so can neither hang nor
|
|
52
|
-
* burn a fixed interval — and only then read through the harness.
|
|
53
|
-
*
|
|
54
16
|
* ## Loading it
|
|
55
17
|
*
|
|
56
18
|
* The host is the trigger, which lives in the fixture, so the ordinary
|
|
@@ -71,34 +33,24 @@ interface TooltipHarnessFilters extends BaseHarnessFilters {
|
|
|
71
33
|
* panel is resolved as "the tooltip showing in the document". That is exact for
|
|
72
34
|
* the hover/focus model, where only one tooltip is visible at a time, but a test
|
|
73
35
|
* that forces two open at once cannot tell them apart.
|
|
36
|
+
*
|
|
37
|
+
* ## Waiting for the panel
|
|
38
|
+
*
|
|
39
|
+
* Every method stabilizes the fixture the way CDK harnesses always do, which
|
|
40
|
+
* covers change detection but **not** the component's own timers: show and hide
|
|
41
|
+
* are driven by plain `setTimeout`s behind `twTooltipShowDelay` (200 ms by
|
|
42
|
+
* default) and `twTooltipHideDelay` (150 ms), which Angular's `PendingTasks`
|
|
43
|
+
* does not track, so `whenStable()` does not wait for them — not even at a delay
|
|
44
|
+
* of `0`. {@link show} and {@link hide} therefore dispatch the interaction and
|
|
45
|
+
* return before anything has attached or detached. Set both delays to `0` in the
|
|
46
|
+
* fixture, poll the DOM for the panel —
|
|
47
|
+
* `document.querySelector('tw-tooltip-overlay')` — and only then read through
|
|
48
|
+
* the harness.
|
|
74
49
|
*/
|
|
75
50
|
declare class TooltipHarness extends ComponentHarness {
|
|
76
51
|
static hostSelector: string;
|
|
77
52
|
/** Resolves the tooltip panel, which lives outside this harness's host. */
|
|
78
53
|
private readonly panel;
|
|
79
|
-
/**
|
|
80
|
-
* Acquires one harness without waiting for the application to stabilize —
|
|
81
|
-
* the counterpart to the guarantee the methods below make.
|
|
82
|
-
*
|
|
83
|
-
* `loader.getHarness(...)` is CDK's own acquisition path and it stabilizes:
|
|
84
|
-
* `getAllRawElements` calls `forceStabilize()`, and `HarnessPredicate`
|
|
85
|
-
* filtering routes through `parallel()`, which asks *every* active fixture in
|
|
86
|
-
* the worker to settle. Both await `fixture.whenStable()`, which is the one
|
|
87
|
-
* thing this harness exists to avoid — and the failure that withdrew it was
|
|
88
|
-
* observed there, at acquisition, before any method had run.
|
|
89
|
-
*
|
|
90
|
-
* So acquisition is wrapped too, and `manualChangeDetection()` nests: the
|
|
91
|
-
* inner `parallel()` sees the flag already set and skips the stabilization
|
|
92
|
-
* entirely. **Render the fixture first** (`fixture.detectChanges()`), because
|
|
93
|
-
* nothing here will do it for you; an unrendered fixture fails loudly with
|
|
94
|
-
* CDK's "failed to find element" rather than returning something wrong.
|
|
95
|
-
*
|
|
96
|
-
* Plain `loader.getHarness(TooltipHarness)` still works and is still supported.
|
|
97
|
-
* This is the path to use when a suite must not be able to hang.
|
|
98
|
-
*/
|
|
99
|
-
static load(loader: HarnessLoader, options?: TooltipHarnessFilters): Promise<TooltipHarness>;
|
|
100
|
-
/** {@link load} for every matching trigger rather than the first. */
|
|
101
|
-
static loadAll(loader: HarnessLoader, options?: TooltipHarnessFilters): Promise<TooltipHarness[]>;
|
|
102
54
|
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
103
55
|
static with(options?: TooltipHarnessFilters): HarnessPredicate<TooltipHarness>;
|
|
104
56
|
/** The text currently rendered in the trigger, trimmed. */
|