@cdevhub/ngx-tw 0.5.0 → 0.6.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/README.md +78 -15
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
- package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
- package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
- package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
- package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs +11 -2
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
- package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
- package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-item.mjs +18 -3
- package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
- package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
- package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
- package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
- package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
- package/fesm2022/{cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs → cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs} +3 -3
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs +23 -7
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
- package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
- package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
- package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
- package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
- package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
- package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
- package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
- package/fesm2022/{cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs → cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs} +107 -19
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs +21 -13
- package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
- package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
- package/index.json +1 -1
- package/package.json +63 -2
- package/theme/_base.css +13 -0
- package/theme/_dark.css +110 -36
- package/theme/_high-contrast-dark.css +367 -0
- package/theme/_high-contrast.css +13 -2
- package/theme/_light.css +276 -0
- package/theme/_semantic.css +47 -12
- package/theme/_typography.css +17 -0
- package/theme/index.css +86 -7
- package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
- package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
- package/types/cdevhub-ngx-tw-button.d.ts +1 -0
- package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
- package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
- package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
- package/types/cdevhub-ngx-tw-card.d.ts +11 -3
- package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
- package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
- package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
- package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
- package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
- package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
- package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
- package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
- package/types/cdevhub-ngx-tw-core.d.ts +152 -21
- package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
- package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
- package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
- package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
- package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
- package/types/cdevhub-ngx-tw-dialog.d.ts +12 -3
- package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
- package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
- package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
- package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
- package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
- package/types/cdevhub-ngx-tw-input.d.ts +5 -8
- package/types/cdevhub-ngx-tw-item.d.ts +2 -0
- package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
- package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
- package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
- package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
- package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
- package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
- package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
- package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
- package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
- package/types/cdevhub-ngx-tw-select.d.ts +104 -33
- package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
- package/types/cdevhub-ngx-tw-sheet.d.ts +19 -3
- package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
- package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
- package/types/cdevhub-ngx-tw-split.d.ts +32 -2
- package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
- package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
- package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
- package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
- package/types/cdevhub-ngx-tw-table.d.ts +53 -10
- package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
- package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
- package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
- package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
- package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
- package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
- package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
- package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
- package/types/cdevhub-ngx-tw-toast.d.ts +20 -6
- package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
- package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
- package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
- package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs.map +0 -1
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map +0 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Harness for a single option inside an open `tw-select` panel.
|
|
5
|
+
*
|
|
6
|
+
* Options render into the CDK overlay, not inside `tw-select`, so they are
|
|
7
|
+
* reached through {@link SelectHarness} rather than located directly against a
|
|
8
|
+
* fixture.
|
|
9
|
+
*/
|
|
10
|
+
class SelectOptionHarness extends ComponentHarness {
|
|
11
|
+
static hostSelector = '[role="option"]';
|
|
12
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
13
|
+
static with(options = {}) {
|
|
14
|
+
return new HarnessPredicate(SelectOptionHarness, options)
|
|
15
|
+
.addOption('text', options.text, async (h, text) => HarnessPredicate.stringMatches(await h.getText(), text))
|
|
16
|
+
.addOption('selected', options.selected, async (h, selected) => (await h.isSelected()) === selected)
|
|
17
|
+
.addOption('disabled', options.disabled, async (h, disabled) => (await h.isDisabled()) === disabled);
|
|
18
|
+
}
|
|
19
|
+
/** The option's rendered text, trimmed. */
|
|
20
|
+
async getText() {
|
|
21
|
+
return (await (await this.host()).text()).trim();
|
|
22
|
+
}
|
|
23
|
+
/** Whether the option reports `aria-selected="true"`. */
|
|
24
|
+
async isSelected() {
|
|
25
|
+
return (await (await this.host()).getAttribute('aria-selected')) === 'true';
|
|
26
|
+
}
|
|
27
|
+
/** Whether the option reports `aria-disabled="true"`. */
|
|
28
|
+
async isDisabled() {
|
|
29
|
+
return (await (await this.host()).getAttribute('aria-disabled')) === 'true';
|
|
30
|
+
}
|
|
31
|
+
/** Clicks the option. A disabled option ignores the click, as in the browser. */
|
|
32
|
+
async click() {
|
|
33
|
+
await (await this.host()).click();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Harness for `tw-select`.
|
|
39
|
+
*
|
|
40
|
+
* The options panel renders into the CDK overlay container, outside the
|
|
41
|
+
* `tw-select` host, so this harness resolves it through
|
|
42
|
+
* `documentRootLocatorFactory()`. A consumer can therefore load this harness
|
|
43
|
+
* from the ordinary fixture loader and still reach the options — no
|
|
44
|
+
* `documentRootLoader` ceremony required.
|
|
45
|
+
*
|
|
46
|
+
* The panel is *disposed* on close rather than merely detached, so option
|
|
47
|
+
* harnesses must be re-read after each `open()`. Do not cache them across a
|
|
48
|
+
* close.
|
|
49
|
+
*/
|
|
50
|
+
class SelectHarness extends ComponentHarness {
|
|
51
|
+
static hostSelector = 'tw-select';
|
|
52
|
+
trigger = this.locatorFor('button[role="combobox"]');
|
|
53
|
+
clearButton = this.locatorForOptional('button[aria-label="Clear selection"]');
|
|
54
|
+
/** Resolves the overlay panel, which lives outside this harness's host. */
|
|
55
|
+
panel = this.documentRootLocatorFactory().locatorForOptional('[role="listbox"]');
|
|
56
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
57
|
+
static with(options = {}) {
|
|
58
|
+
return new HarnessPredicate(SelectHarness, options)
|
|
59
|
+
.addOption('label', options.label, async (h, label) => HarnessPredicate.stringMatches(await h.getLabel(), label))
|
|
60
|
+
.addOption('triggerText', options.triggerText, async (h, text) => HarnessPredicate.stringMatches(await h.getTriggerText(), text))
|
|
61
|
+
.addOption('disabled', options.disabled, async (h, disabled) => (await h.isDisabled()) === disabled);
|
|
62
|
+
}
|
|
63
|
+
/** The trigger's accessible name, from `aria-label` when one is set. */
|
|
64
|
+
async getLabel() {
|
|
65
|
+
return (await this.trigger()).getAttribute('aria-label');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The text currently rendered in the trigger, trimmed. This is the
|
|
69
|
+
* placeholder when the select holds no value.
|
|
70
|
+
*/
|
|
71
|
+
async getTriggerText() {
|
|
72
|
+
return (await (await this.trigger()).text()).trim();
|
|
73
|
+
}
|
|
74
|
+
/** Whether the panel is open, read from the trigger's `aria-expanded`. */
|
|
75
|
+
async isOpen() {
|
|
76
|
+
return (await (await this.trigger()).getAttribute('aria-expanded')) === 'true';
|
|
77
|
+
}
|
|
78
|
+
/** Whether the trigger reports `aria-disabled="true"`. */
|
|
79
|
+
async isDisabled() {
|
|
80
|
+
return (await (await this.trigger()).getAttribute('aria-disabled')) === 'true';
|
|
81
|
+
}
|
|
82
|
+
/** Whether the trigger reports `aria-invalid="true"`. */
|
|
83
|
+
async isInvalid() {
|
|
84
|
+
return (await (await this.trigger()).getAttribute('aria-invalid')) === 'true';
|
|
85
|
+
}
|
|
86
|
+
/** Whether the trigger reports `aria-required="true"`. */
|
|
87
|
+
async isRequired() {
|
|
88
|
+
return (await (await this.trigger()).getAttribute('aria-required')) === 'true';
|
|
89
|
+
}
|
|
90
|
+
/** Opens the panel. No-op when already open. */
|
|
91
|
+
async open() {
|
|
92
|
+
if (await this.isOpen())
|
|
93
|
+
return;
|
|
94
|
+
await (await this.trigger()).click();
|
|
95
|
+
await this.waitForTasksOutsideAngular();
|
|
96
|
+
}
|
|
97
|
+
/** Closes the panel with Escape. No-op when already closed. */
|
|
98
|
+
async close() {
|
|
99
|
+
if (!(await this.isOpen()))
|
|
100
|
+
return;
|
|
101
|
+
await (await this.trigger()).sendKeys(TestKey.ESCAPE);
|
|
102
|
+
await this.waitForTasksOutsideAngular();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Every option in the open panel. Returns an empty array when the panel is
|
|
106
|
+
* closed, because the overlay is disposed rather than hidden.
|
|
107
|
+
*/
|
|
108
|
+
async getOptions(filters = {}) {
|
|
109
|
+
if (!(await this.panel()))
|
|
110
|
+
return [];
|
|
111
|
+
return this.documentRootLocatorFactory().locatorForAll(SelectOptionHarness.with(filters))();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Opens the panel if needed and clicks the first option whose text matches.
|
|
115
|
+
* Throws when nothing matches, rather than failing silently.
|
|
116
|
+
*/
|
|
117
|
+
async selectOption(text) {
|
|
118
|
+
await this.open();
|
|
119
|
+
const matches = await this.getOptions({ text });
|
|
120
|
+
if (matches.length === 0) {
|
|
121
|
+
throw new Error(`SelectHarness.selectOption: no option matching ${String(text)}.`);
|
|
122
|
+
}
|
|
123
|
+
await matches[0].click();
|
|
124
|
+
await this.waitForTasksOutsideAngular();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The text of every currently selected option. Opens the panel if needed,
|
|
128
|
+
* because selection state is exposed on the options, which only exist while
|
|
129
|
+
* the panel is attached.
|
|
130
|
+
*/
|
|
131
|
+
async getSelectedOptionTexts() {
|
|
132
|
+
await this.open();
|
|
133
|
+
const selected = await this.getOptions({ selected: true });
|
|
134
|
+
return Promise.all(selected.map((option) => option.getText()));
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Whether a clear control is rendered. `tw-select` has no `clearable` input —
|
|
138
|
+
* the control appears whenever the select is enabled and holds a value.
|
|
139
|
+
*/
|
|
140
|
+
async hasClearButton() {
|
|
141
|
+
return (await this.clearButton()) !== null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Clicks the clear control. Throws when none is rendered.
|
|
145
|
+
*
|
|
146
|
+
* The control is a native `<button>` and a *sibling* of the trigger, not a
|
|
147
|
+
* descendant — HTML's content model forbids interactive content inside a
|
|
148
|
+
* `<button>`.
|
|
149
|
+
*/
|
|
150
|
+
async clear() {
|
|
151
|
+
const button = await this.clearButton();
|
|
152
|
+
if (!button) {
|
|
153
|
+
throw new Error('SelectHarness.clear: no clear control is rendered. It appears only when the select is enabled and holds a value.');
|
|
154
|
+
}
|
|
155
|
+
await button.click();
|
|
156
|
+
await this.waitForTasksOutsideAngular();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Generated bundle index. Do not edit.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
export { SelectHarness, SelectOptionHarness };
|
|
165
|
+
//# sourceMappingURL=cdevhub-ngx-tw-select-testing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdevhub-ngx-tw-select-testing.mjs","sources":["../../../projects/ngx-tw/select/testing/select-option-harness.ts","../../../projects/ngx-tw/select/testing/select-harness.ts","../../../projects/ngx-tw/select/testing/cdevhub-ngx-tw-select-testing.ts"],"sourcesContent":["import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\nimport type { BaseHarnessFilters } from '@angular/cdk/testing';\n\n/** Filters accepted by `SelectOptionHarness.with`. */\nexport interface SelectOptionHarnessFilters extends BaseHarnessFilters {\n /** Match by the option's visible text. */\n text?: string | RegExp;\n /** Match selected / unselected options. */\n selected?: boolean;\n /** Match disabled / enabled options. */\n disabled?: boolean;\n}\n\n/**\n * Harness for a single option inside an open `tw-select` panel.\n *\n * Options render into the CDK overlay, not inside `tw-select`, so they are\n * reached through {@link SelectHarness} rather than located directly against a\n * fixture.\n */\nexport class SelectOptionHarness extends ComponentHarness {\n static hostSelector = '[role=\"option\"]';\n\n /** Predicate for `locatorFor` / `locatorForAll`. */\n static with(\n options: SelectOptionHarnessFilters = {},\n ): HarnessPredicate<SelectOptionHarness> {\n return new HarnessPredicate(SelectOptionHarness, options)\n .addOption('text', options.text, async (h, text) =>\n HarnessPredicate.stringMatches(await h.getText(), text),\n )\n .addOption(\n 'selected',\n options.selected,\n async (h, selected) => (await h.isSelected()) === selected,\n )\n .addOption(\n 'disabled',\n options.disabled,\n async (h, disabled) => (await h.isDisabled()) === disabled,\n );\n }\n\n /** The option's rendered text, trimmed. */\n async getText(): Promise<string> {\n return (await (await this.host()).text()).trim();\n }\n\n /** Whether the option reports `aria-selected=\"true\"`. */\n async isSelected(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-selected')) === 'true';\n }\n\n /** Whether the option reports `aria-disabled=\"true\"`. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** Clicks the option. A disabled option ignores the click, as in the browser. */\n async click(): Promise<void> {\n await (await this.host()).click();\n }\n}\n","import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';\nimport type { BaseHarnessFilters, TestElement } from '@angular/cdk/testing';\nimport {\n SelectOptionHarness,\n type SelectOptionHarnessFilters,\n} from './select-option-harness';\n\n/** Filters accepted by `SelectHarness.with`. */\nexport interface SelectHarnessFilters extends BaseHarnessFilters {\n /** Match by the trigger's accessible name. */\n label?: string | RegExp;\n /** Match by the text currently displayed in the trigger. */\n triggerText?: string | RegExp;\n /** Match disabled / enabled selects. */\n disabled?: boolean;\n}\n\n/**\n * Harness for `tw-select`.\n *\n * The options panel renders into the CDK overlay container, outside the\n * `tw-select` host, so this harness resolves it through\n * `documentRootLocatorFactory()`. A consumer can therefore load this harness\n * from the ordinary fixture loader and still reach the options — no\n * `documentRootLoader` ceremony required.\n *\n * The panel is *disposed* on close rather than merely detached, so option\n * harnesses must be re-read after each `open()`. Do not cache them across a\n * close.\n */\nexport class SelectHarness extends ComponentHarness {\n static hostSelector = 'tw-select';\n\n private readonly trigger = this.locatorFor('button[role=\"combobox\"]');\n private readonly clearButton = this.locatorForOptional(\n 'button[aria-label=\"Clear selection\"]',\n );\n /** Resolves the overlay panel, which lives outside this harness's host. */\n private readonly panel = this.documentRootLocatorFactory().locatorForOptional(\n '[role=\"listbox\"]',\n );\n\n /** Predicate for `locatorFor` / `locatorForAll`. */\n static with(options: SelectHarnessFilters = {}): HarnessPredicate<SelectHarness> {\n return new HarnessPredicate(SelectHarness, options)\n .addOption('label', options.label, async (h, label) =>\n HarnessPredicate.stringMatches(await h.getLabel(), label),\n )\n .addOption('triggerText', options.triggerText, async (h, text) =>\n HarnessPredicate.stringMatches(await h.getTriggerText(), text),\n )\n .addOption(\n 'disabled',\n options.disabled,\n async (h, disabled) => (await h.isDisabled()) === disabled,\n );\n }\n\n /** The trigger's accessible name, from `aria-label` when one is set. */\n async getLabel(): Promise<string | null> {\n return (await this.trigger()).getAttribute('aria-label');\n }\n\n /**\n * The text currently rendered in the trigger, trimmed. This is the\n * placeholder when the select holds no value.\n */\n async getTriggerText(): Promise<string> {\n return (await (await this.trigger()).text()).trim();\n }\n\n /** Whether the panel is open, read from the trigger's `aria-expanded`. */\n async isOpen(): Promise<boolean> {\n return (await (await this.trigger()).getAttribute('aria-expanded')) === 'true';\n }\n\n /** Whether the trigger reports `aria-disabled=\"true\"`. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.trigger()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** Whether the trigger reports `aria-invalid=\"true\"`. */\n async isInvalid(): Promise<boolean> {\n return (await (await this.trigger()).getAttribute('aria-invalid')) === 'true';\n }\n\n /** Whether the trigger reports `aria-required=\"true\"`. */\n async isRequired(): Promise<boolean> {\n return (await (await this.trigger()).getAttribute('aria-required')) === 'true';\n }\n\n /** Opens the panel. No-op when already open. */\n async open(): Promise<void> {\n if (await this.isOpen()) return;\n await (await this.trigger()).click();\n await this.waitForTasksOutsideAngular();\n }\n\n /** Closes the panel with Escape. No-op when already closed. */\n async close(): Promise<void> {\n if (!(await this.isOpen())) return;\n await (await this.trigger()).sendKeys(TestKey.ESCAPE);\n await this.waitForTasksOutsideAngular();\n }\n\n /**\n * Every option in the open panel. Returns an empty array when the panel is\n * closed, because the overlay is disposed rather than hidden.\n */\n async getOptions(\n filters: SelectOptionHarnessFilters = {},\n ): Promise<SelectOptionHarness[]> {\n if (!(await this.panel())) return [];\n return this.documentRootLocatorFactory().locatorForAll(\n SelectOptionHarness.with(filters),\n )();\n }\n\n /**\n * Opens the panel if needed and clicks the first option whose text matches.\n * Throws when nothing matches, rather than failing silently.\n */\n async selectOption(text: string | RegExp): Promise<void> {\n await this.open();\n const matches = await this.getOptions({ text });\n if (matches.length === 0) {\n throw new Error(\n `SelectHarness.selectOption: no option matching ${String(text)}.`,\n );\n }\n await matches[0].click();\n await this.waitForTasksOutsideAngular();\n }\n\n /**\n * The text of every currently selected option. Opens the panel if needed,\n * because selection state is exposed on the options, which only exist while\n * the panel is attached.\n */\n async getSelectedOptionTexts(): Promise<string[]> {\n await this.open();\n const selected = await this.getOptions({ selected: true });\n return Promise.all(selected.map((option) => option.getText()));\n }\n\n /**\n * Whether a clear control is rendered. `tw-select` has no `clearable` input —\n * the control appears whenever the select is enabled and holds a value.\n */\n async hasClearButton(): Promise<boolean> {\n return (await this.clearButton()) !== null;\n }\n\n /**\n * Clicks the clear control. Throws when none is rendered.\n *\n * The control is a native `<button>` and a *sibling* of the trigger, not a\n * descendant — HTML's content model forbids interactive content inside a\n * `<button>`.\n */\n async clear(): Promise<void> {\n const button: TestElement | null = await this.clearButton();\n if (!button) {\n throw new Error(\n 'SelectHarness.clear: no clear control is rendered. It appears only when the select is enabled and holds a value.',\n );\n }\n await button.click();\n await this.waitForTasksOutsideAngular();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|