@cdevhub/ngx-tw 0.7.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 +122 -0
- package/fesm2022/cdevhub-ngx-tw-popover-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tooltip-testing.mjs +103 -0
- package/fesm2022/cdevhub-ngx-tw-tooltip-testing.mjs.map +1 -0
- package/index.json +1 -1
- package/package.json +9 -1
- package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +7 -7
- package/types/cdevhub-ngx-tw-popover-testing.d.ts +89 -0
- package/types/cdevhub-ngx-tw-tooltip-testing.d.ts +83 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdevhub/ngx-tw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Angular component library for Tailwind CSS v4 — accessible, signal-based, built on Angular CDK.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -193,6 +193,10 @@
|
|
|
193
193
|
"types": "./types/cdevhub-ngx-tw-popover.d.ts",
|
|
194
194
|
"default": "./fesm2022/cdevhub-ngx-tw-popover.mjs"
|
|
195
195
|
},
|
|
196
|
+
"./popover/testing": {
|
|
197
|
+
"types": "./types/cdevhub-ngx-tw-popover-testing.d.ts",
|
|
198
|
+
"default": "./fesm2022/cdevhub-ngx-tw-popover-testing.mjs"
|
|
199
|
+
},
|
|
196
200
|
"./progress-bar": {
|
|
197
201
|
"types": "./types/cdevhub-ngx-tw-progress-bar.d.ts",
|
|
198
202
|
"default": "./fesm2022/cdevhub-ngx-tw-progress-bar.mjs"
|
|
@@ -305,6 +309,10 @@
|
|
|
305
309
|
"types": "./types/cdevhub-ngx-tw-tooltip.d.ts",
|
|
306
310
|
"default": "./fesm2022/cdevhub-ngx-tw-tooltip.mjs"
|
|
307
311
|
},
|
|
312
|
+
"./tooltip/testing": {
|
|
313
|
+
"types": "./types/cdevhub-ngx-tw-tooltip-testing.d.ts",
|
|
314
|
+
"default": "./fesm2022/cdevhub-ngx-tw-tooltip-testing.mjs"
|
|
315
|
+
},
|
|
308
316
|
"./transfer": {
|
|
309
317
|
"types": "./types/cdevhub-ngx-tw-transfer.d.ts",
|
|
310
318
|
"default": "./fesm2022/cdevhub-ngx-tw-transfer.mjs"
|
|
@@ -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. */
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/** Filters accepted by `PopoverHarness.with`. */
|
|
4
|
+
interface PopoverHarnessFilters extends BaseHarnessFilters {
|
|
5
|
+
/** Match by the text rendered in the trigger. */
|
|
6
|
+
triggerText?: string | RegExp;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Harness for a `[twPopover]` trigger and the panel it opens.
|
|
10
|
+
*
|
|
11
|
+
* ## Loading it
|
|
12
|
+
*
|
|
13
|
+
* The host is the trigger, which lives in the fixture, so the ordinary
|
|
14
|
+
* `TestbedHarnessEnvironment.loader(fixture)` is correct. The panel renders into
|
|
15
|
+
* the CDK overlay container outside the fixture, and this harness resolves it
|
|
16
|
+
* internally via `documentRootLocatorFactory()` — a consumer never needs
|
|
17
|
+
* `documentRootLoader`.
|
|
18
|
+
*
|
|
19
|
+
* The host selector is the directive's static `data-tw-popover-trigger` marker.
|
|
20
|
+
* `[twPopover]` cannot be used: it takes a required `TemplateRef` or component
|
|
21
|
+
* type, so it is always property-bound and Angular renders no attribute for a
|
|
22
|
+
* bound input. The marker also makes the match exact, so no disambiguation
|
|
23
|
+
* against `aria-haspopup="dialog"` — which the two date-picker triggers also
|
|
24
|
+
* carry — is needed.
|
|
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
|
+
*
|
|
37
|
+
* ## The panel is detached, not disposed
|
|
38
|
+
*
|
|
39
|
+
* Unlike `tw-select`, closing a popover **detaches** the portal and keeps the
|
|
40
|
+
* `OverlayRef` for reuse; it is only rebuilt when `twPopoverBackdrop` or
|
|
41
|
+
* `twPopoverScrollStrategy` changes. The panel element is therefore absent while
|
|
42
|
+
* closed and present again after a reopen, on the same overlay.
|
|
43
|
+
*/
|
|
44
|
+
declare class PopoverHarness extends ComponentHarness {
|
|
45
|
+
static hostSelector: string;
|
|
46
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
47
|
+
static with(options?: PopoverHarnessFilters): HarnessPredicate<PopoverHarness>;
|
|
48
|
+
/** The text currently rendered in the trigger, trimmed. */
|
|
49
|
+
getTriggerText(): Promise<string>;
|
|
50
|
+
/** Whether the popover is open, read from the trigger's `aria-expanded`. */
|
|
51
|
+
isOpen(): Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Opens the popover by clicking the trigger. No-op when already open.
|
|
54
|
+
*
|
|
55
|
+
* This is the gesture for the default `twPopoverTriggerOn="click"`. A
|
|
56
|
+
* `'focus'`- or `'manual'`-triggered popover is opened through the directive's
|
|
57
|
+
* own `open()` (reachable via `exportAs: 'twPopover'`), not through a click.
|
|
58
|
+
*/
|
|
59
|
+
open(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Closes the popover by sending Escape to the trigger — the one dismissal
|
|
62
|
+
* that works for click, focus and manual triggers alike. No-op when already
|
|
63
|
+
* closed, and deliberately inert when `twPopoverCloseOnEscape` is `false`.
|
|
64
|
+
*
|
|
65
|
+
* Returns as soon as the key is dispatched. The panel detaches only after the
|
|
66
|
+
* 120 ms leave window; poll the DOM for its removal before asserting.
|
|
67
|
+
*/
|
|
68
|
+
close(): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Text rendered inside the panel, trimmed, or `null` when the popover is
|
|
71
|
+
* closed and the panel is detached.
|
|
72
|
+
*/
|
|
73
|
+
getText(): Promise<string | null>;
|
|
74
|
+
/**
|
|
75
|
+
* Whether the panel renders its directional arrow (`twPopoverArrow`). `false`
|
|
76
|
+
* while the popover is closed, because the panel does not exist then.
|
|
77
|
+
*/
|
|
78
|
+
hasArrow(): Promise<boolean>;
|
|
79
|
+
/** The panel element, or `null` when the popover is closed. */
|
|
80
|
+
private getPanel;
|
|
81
|
+
/**
|
|
82
|
+
* The id of this trigger's own panel, or `null` when closed. Scoping by
|
|
83
|
+
* `aria-controls` keeps sibling popovers apart.
|
|
84
|
+
*/
|
|
85
|
+
private getPanelId;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { PopoverHarness };
|
|
89
|
+
export type { PopoverHarnessFilters };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/** Filters accepted by `TooltipHarness.with`. */
|
|
4
|
+
interface TooltipHarnessFilters extends BaseHarnessFilters {
|
|
5
|
+
/** Match by the text rendered in the trigger. */
|
|
6
|
+
triggerText?: string | RegExp;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Harness for a `[twTooltip]` trigger and the panel it shows.
|
|
10
|
+
*
|
|
11
|
+
* Deliberately narrow: a tooltip's whole observable surface is *whether it is
|
|
12
|
+
* showing and what it says*. Position, delays, color, size and arrow are
|
|
13
|
+
* configuration, not state, and a harness method for any of them would freeze an
|
|
14
|
+
* API that may still move — so none is offered.
|
|
15
|
+
*
|
|
16
|
+
* ## Loading it
|
|
17
|
+
*
|
|
18
|
+
* The host is the trigger, which lives in the fixture, so the ordinary
|
|
19
|
+
* `TestbedHarnessEnvironment.loader(fixture)` is correct. The panel renders into
|
|
20
|
+
* the CDK overlay container outside the fixture, and this harness resolves it
|
|
21
|
+
* internally via `documentRootLocatorFactory()` — a consumer never needs
|
|
22
|
+
* `documentRootLoader`.
|
|
23
|
+
*
|
|
24
|
+
* The host selector is the directive's static `data-tw-tooltip-trigger` marker,
|
|
25
|
+
* which matches both spellings of the input: `twTooltip="literal"` and the bound
|
|
26
|
+
* `[twTooltip]="expr()"`, for which Angular renders no attribute at all. A
|
|
27
|
+
* harness matching the directive's own selector would silently miss every bound
|
|
28
|
+
* trigger.
|
|
29
|
+
*
|
|
30
|
+
* Unlike `MenuHarness` and `PopoverHarness`, a tooltip trigger carries no
|
|
31
|
+
* `aria-controls` linking it to its panel (`aria-describedby` points at CDK
|
|
32
|
+
* `AriaDescriber`'s shared hidden message element for string content), so the
|
|
33
|
+
* panel is resolved as "the tooltip showing in the document". That is exact for
|
|
34
|
+
* the hover/focus model, where only one tooltip is visible at a time, but a test
|
|
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.
|
|
49
|
+
*/
|
|
50
|
+
declare class TooltipHarness extends ComponentHarness {
|
|
51
|
+
static hostSelector: string;
|
|
52
|
+
/** Resolves the tooltip panel, which lives outside this harness's host. */
|
|
53
|
+
private readonly panel;
|
|
54
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
55
|
+
static with(options?: TooltipHarnessFilters): HarnessPredicate<TooltipHarness>;
|
|
56
|
+
/** The text currently rendered in the trigger, trimmed. */
|
|
57
|
+
getTriggerText(): Promise<string>;
|
|
58
|
+
/** Whether a tooltip panel is currently showing. */
|
|
59
|
+
isOpen(): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* The tooltip's message, trimmed, or `null` when nothing is showing. Works
|
|
62
|
+
* for string and `TemplateRef` content alike.
|
|
63
|
+
*/
|
|
64
|
+
getTooltipText(): Promise<string | null>;
|
|
65
|
+
/** Hovers the trigger. The panel appears once `twTooltipShowDelay` elapses. */
|
|
66
|
+
show(): Promise<void>;
|
|
67
|
+
/** Moves the pointer off the trigger. The panel detaches once `twTooltipHideDelay` elapses. */
|
|
68
|
+
hide(): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Focuses the trigger — the keyboard equivalent of {@link show}, and the path
|
|
71
|
+
* WCAG 2.1 SC 1.4.13 requires to work.
|
|
72
|
+
*
|
|
73
|
+
* Moves real DOM focus *and* dispatches `focusin`, because a programmatic
|
|
74
|
+
* `focus()` does not reliably raise `focusin` in every test DOM. The directive
|
|
75
|
+
* treats a repeated show as a no-op, so the belt-and-braces pair is safe.
|
|
76
|
+
*/
|
|
77
|
+
focusTrigger(): Promise<void>;
|
|
78
|
+
/** Blurs the trigger — the keyboard equivalent of {@link hide}. */
|
|
79
|
+
blurTrigger(): Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export { TooltipHarness };
|
|
83
|
+
export type { TooltipHarnessFilters };
|