ngx-com 0.1.16 → 0.1.18

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.
Files changed (82) hide show
  1. package/fesm2022/ngx-com-components-alert-testing.mjs +80 -0
  2. package/fesm2022/ngx-com-components-alert-testing.mjs.map +1 -0
  3. package/fesm2022/ngx-com-components-calendar-testing.mjs +157 -0
  4. package/fesm2022/ngx-com-components-calendar-testing.mjs.map +1 -0
  5. package/fesm2022/ngx-com-components-carousel-testing.mjs +121 -0
  6. package/fesm2022/ngx-com-components-carousel-testing.mjs.map +1 -0
  7. package/fesm2022/ngx-com-components-checkbox-testing.mjs +113 -0
  8. package/fesm2022/ngx-com-components-checkbox-testing.mjs.map +1 -0
  9. package/fesm2022/ngx-com-components-checkbox.mjs +2 -2
  10. package/fesm2022/ngx-com-components-checkbox.mjs.map +1 -1
  11. package/fesm2022/ngx-com-components-code-block-testing.mjs +88 -0
  12. package/fesm2022/ngx-com-components-code-block-testing.mjs.map +1 -0
  13. package/fesm2022/ngx-com-components-collapsible-testing.mjs +104 -0
  14. package/fesm2022/ngx-com-components-collapsible-testing.mjs.map +1 -0
  15. package/fesm2022/ngx-com-components-confirm-testing.mjs +150 -0
  16. package/fesm2022/ngx-com-components-confirm-testing.mjs.map +1 -0
  17. package/fesm2022/ngx-com-components-datepicker-testing.mjs +137 -0
  18. package/fesm2022/ngx-com-components-datepicker-testing.mjs.map +1 -0
  19. package/fesm2022/ngx-com-components-dialog-testing.mjs +109 -0
  20. package/fesm2022/ngx-com-components-dialog-testing.mjs.map +1 -0
  21. package/fesm2022/ngx-com-components-dialog.mjs +18 -18
  22. package/fesm2022/ngx-com-components-dialog.mjs.map +1 -1
  23. package/fesm2022/ngx-com-components-dropdown.mjs +39 -0
  24. package/fesm2022/ngx-com-components-dropdown.mjs.map +1 -1
  25. package/fesm2022/ngx-com-components-form-field-testing.mjs +140 -0
  26. package/fesm2022/ngx-com-components-form-field-testing.mjs.map +1 -0
  27. package/fesm2022/ngx-com-components-form-field.mjs +5 -1
  28. package/fesm2022/ngx-com-components-form-field.mjs.map +1 -1
  29. package/fesm2022/ngx-com-components-menu-testing.mjs +298 -0
  30. package/fesm2022/ngx-com-components-menu-testing.mjs.map +1 -0
  31. package/fesm2022/ngx-com-components-paginator-testing.mjs +128 -0
  32. package/fesm2022/ngx-com-components-paginator-testing.mjs.map +1 -0
  33. package/fesm2022/ngx-com-components-popover-testing.mjs +115 -0
  34. package/fesm2022/ngx-com-components-popover-testing.mjs.map +1 -0
  35. package/fesm2022/ngx-com-components-radio-testing.mjs +157 -0
  36. package/fesm2022/ngx-com-components-radio-testing.mjs.map +1 -0
  37. package/fesm2022/ngx-com-components-radio.mjs +2 -2
  38. package/fesm2022/ngx-com-components-radio.mjs.map +1 -1
  39. package/fesm2022/ngx-com-components-segmented-control-testing.mjs +122 -0
  40. package/fesm2022/ngx-com-components-segmented-control-testing.mjs.map +1 -0
  41. package/fesm2022/ngx-com-components-sort-testing.mjs +108 -0
  42. package/fesm2022/ngx-com-components-sort-testing.mjs.map +1 -0
  43. package/fesm2022/ngx-com-components-switch-testing.mjs +103 -0
  44. package/fesm2022/ngx-com-components-switch-testing.mjs.map +1 -0
  45. package/fesm2022/ngx-com-components-switch.mjs +2 -2
  46. package/fesm2022/ngx-com-components-switch.mjs.map +1 -1
  47. package/fesm2022/ngx-com-components-table-testing.mjs +198 -0
  48. package/fesm2022/ngx-com-components-table-testing.mjs.map +1 -0
  49. package/fesm2022/ngx-com-components-tabs-testing.mjs +126 -0
  50. package/fesm2022/ngx-com-components-tabs-testing.mjs.map +1 -0
  51. package/fesm2022/ngx-com-components-timepicker-testing.mjs +117 -0
  52. package/fesm2022/ngx-com-components-timepicker-testing.mjs.map +1 -0
  53. package/fesm2022/ngx-com-components-toast-testing.mjs +172 -0
  54. package/fesm2022/ngx-com-components-toast-testing.mjs.map +1 -0
  55. package/fesm2022/ngx-com-components-toast.mjs +4 -4
  56. package/fesm2022/ngx-com-components-toast.mjs.map +1 -1
  57. package/fesm2022/ngx-com-components-tooltip-testing.mjs +117 -0
  58. package/fesm2022/ngx-com-components-tooltip-testing.mjs.map +1 -0
  59. package/package.json +89 -1
  60. package/types/ngx-com-components-alert-testing.d.ts +41 -0
  61. package/types/ngx-com-components-calendar-testing.d.ts +80 -0
  62. package/types/ngx-com-components-carousel-testing.d.ts +51 -0
  63. package/types/ngx-com-components-checkbox-testing.d.ts +56 -0
  64. package/types/ngx-com-components-code-block-testing.d.ts +45 -0
  65. package/types/ngx-com-components-collapsible-testing.d.ts +53 -0
  66. package/types/ngx-com-components-confirm-testing.d.ts +78 -0
  67. package/types/ngx-com-components-datepicker-testing.d.ts +61 -0
  68. package/types/ngx-com-components-dialog-testing.d.ts +57 -0
  69. package/types/ngx-com-components-dropdown.d.ts +12 -0
  70. package/types/ngx-com-components-form-field-testing.d.ts +61 -0
  71. package/types/ngx-com-components-menu-testing.d.ts +167 -0
  72. package/types/ngx-com-components-paginator-testing.d.ts +58 -0
  73. package/types/ngx-com-components-popover-testing.d.ts +63 -0
  74. package/types/ngx-com-components-radio-testing.d.ts +86 -0
  75. package/types/ngx-com-components-segmented-control-testing.d.ts +66 -0
  76. package/types/ngx-com-components-sort-testing.d.ts +62 -0
  77. package/types/ngx-com-components-switch-testing.d.ts +52 -0
  78. package/types/ngx-com-components-table-testing.d.ts +124 -0
  79. package/types/ngx-com-components-tabs-testing.d.ts +67 -0
  80. package/types/ngx-com-components-timepicker-testing.d.ts +53 -0
  81. package/types/ngx-com-components-toast-testing.d.ts +93 -0
  82. package/types/ngx-com-components-tooltip-testing.d.ts +57 -0
@@ -0,0 +1,137 @@
1
+ import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';
2
+
3
+ /**
4
+ * Harness for interacting with a ComDatepicker in tests.
5
+ */
6
+ class ComDatepickerHarness extends ComponentHarness {
7
+ static hostSelector = 'com-datepicker';
8
+ triggerGroup = this.locatorFor('div[role="group"]');
9
+ input = this.locatorFor('input[type="text"]');
10
+ clearButton = this.locatorForOptional('button[aria-label="Clear date"]');
11
+ calendarButton = this.locatorFor('button[aria-label$="calendar"]');
12
+ /**
13
+ * Gets a HarnessPredicate for matching datepickers.
14
+ * @param options Filter options.
15
+ */
16
+ static with(options = {}) {
17
+ return new HarnessPredicate(ComDatepickerHarness, options)
18
+ .addOption('placeholder', options.placeholder, async (harness, placeholder) => {
19
+ const text = await harness.getPlaceholder();
20
+ return HarnessPredicate.stringMatches(text, placeholder);
21
+ })
22
+ .addOption('disabled', options.disabled, async (harness, disabled) => {
23
+ return (await harness.isDisabled()) === disabled;
24
+ })
25
+ .addOption('open', options.open, async (harness, open) => {
26
+ return (await harness.isOpen()) === open;
27
+ });
28
+ }
29
+ /** Whether the datepicker panel is currently open. */
30
+ async isOpen() {
31
+ const trigger = await this.triggerGroup();
32
+ return (await trigger.getAttribute('aria-expanded')) === 'true';
33
+ }
34
+ /** Opens the datepicker panel if it is closed. */
35
+ async open() {
36
+ if (!(await this.isOpen())) {
37
+ const btn = await this.calendarButton();
38
+ await btn.click();
39
+ }
40
+ }
41
+ /** Closes the datepicker panel if it is open. */
42
+ async close() {
43
+ if (await this.isOpen()) {
44
+ const host = await this.host();
45
+ await host.sendKeys(TestKey.ESCAPE);
46
+ }
47
+ }
48
+ /** Whether the datepicker is disabled. */
49
+ async isDisabled() {
50
+ const trigger = await this.triggerGroup();
51
+ return (await trigger.getAttribute('aria-disabled')) === 'true';
52
+ }
53
+ /** Whether the datepicker input has the required attribute. */
54
+ async isRequired() {
55
+ const inputEl = await this.input();
56
+ return (await inputEl.getAttribute('aria-required')) === 'true';
57
+ }
58
+ /** Whether the datepicker input is in an invalid state. */
59
+ async isInvalid() {
60
+ const inputEl = await this.input();
61
+ return (await inputEl.getAttribute('aria-invalid')) === 'true';
62
+ }
63
+ /** Gets the current value displayed in the input. */
64
+ async getInputValue() {
65
+ const inputEl = await this.input();
66
+ return inputEl.getProperty('value');
67
+ }
68
+ /** Sets the input value by clearing and typing the given text. */
69
+ async setInputValue(text) {
70
+ const inputEl = await this.input();
71
+ await inputEl.clear();
72
+ await inputEl.sendKeys(text);
73
+ }
74
+ /** Gets the placeholder text of the input. */
75
+ async getPlaceholder() {
76
+ const inputEl = await this.input();
77
+ return (await inputEl.getAttribute('placeholder')) ?? '';
78
+ }
79
+ /** Whether the datepicker currently has a value (clear button is visible). */
80
+ async hasValue() {
81
+ const clearBtn = await this.clearButton();
82
+ return clearBtn !== null;
83
+ }
84
+ /** Clears the current value by clicking the clear button. Throws if no value is set. */
85
+ async clear() {
86
+ const clearBtn = await this.clearButton();
87
+ if (!clearBtn) {
88
+ throw new Error('Datepicker does not have a clearable value');
89
+ }
90
+ return clearBtn.click();
91
+ }
92
+ /** Gets the calendar panel element from the overlay. The datepicker must be open. */
93
+ async getCalendarPanel() {
94
+ if (!(await this.isOpen())) {
95
+ throw new Error('Datepicker panel is not open');
96
+ }
97
+ return this.documentRootLocatorFactory().locatorFor('com-calendar')();
98
+ }
99
+ /** Selects a day by its visible number. Opens the panel if closed. */
100
+ async selectDate(day) {
101
+ await this.open();
102
+ const rootLocator = this.documentRootLocatorFactory();
103
+ const dayButtons = await rootLocator.locatorForAll('div[role="dialog"] com-calendar-cell button')();
104
+ for (const btn of dayButtons) {
105
+ const text = (await btn.text()).trim();
106
+ if (text === String(day)) {
107
+ await btn.click();
108
+ return;
109
+ }
110
+ }
111
+ throw new Error(`Could not find day cell with number: ${day}`);
112
+ }
113
+ /** Focuses the datepicker input. */
114
+ async focus() {
115
+ const inputEl = await this.input();
116
+ return inputEl.focus();
117
+ }
118
+ /** Blurs the datepicker input. */
119
+ async blur() {
120
+ const inputEl = await this.input();
121
+ return inputEl.blur();
122
+ }
123
+ /** Whether the datepicker input is currently focused. */
124
+ async isFocused() {
125
+ const inputEl = await this.input();
126
+ return inputEl.isFocused();
127
+ }
128
+ }
129
+
130
+ // Testing utilities for the datepicker component
131
+
132
+ /**
133
+ * Generated bundle index. Do not edit.
134
+ */
135
+
136
+ export { ComDatepickerHarness };
137
+ //# sourceMappingURL=ngx-com-components-datepicker-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-com-components-datepicker-testing.mjs","sources":["../../../projects/com/components/datepicker/testing/datepicker.harness.ts","../../../projects/com/components/datepicker/testing/index.ts","../../../projects/com/components/datepicker/testing/ngx-com-components-datepicker-testing.ts"],"sourcesContent":["import {\n ComponentHarness,\n HarnessPredicate,\n TestKey,\n} from '@angular/cdk/testing';\nimport type { BaseHarnessFilters, TestElement } from '@angular/cdk/testing';\n\n/** Harness filters for ComDatepickerHarness. */\nexport interface ComDatepickerHarnessFilters extends BaseHarnessFilters {\n /** Filter by the datepicker's placeholder text. */\n placeholder?: string | RegExp;\n /** Filter by whether the datepicker is disabled. */\n disabled?: boolean;\n /** Filter by whether the datepicker panel is open. */\n open?: boolean;\n}\n\n/**\n * Harness for interacting with a ComDatepicker in tests.\n */\nexport class ComDatepickerHarness extends ComponentHarness {\n static hostSelector = 'com-datepicker';\n\n private readonly triggerGroup = this.locatorFor('div[role=\"group\"]');\n private readonly input = this.locatorFor('input[type=\"text\"]');\n private readonly clearButton = this.locatorForOptional('button[aria-label=\"Clear date\"]');\n private readonly calendarButton = this.locatorFor('button[aria-label$=\"calendar\"]');\n\n /**\n * Gets a HarnessPredicate for matching datepickers.\n * @param options Filter options.\n */\n static with(options: ComDatepickerHarnessFilters = {}): HarnessPredicate<ComDatepickerHarness> {\n return new HarnessPredicate(ComDatepickerHarness, options)\n .addOption('placeholder', options.placeholder, async (harness, placeholder) => {\n const text = await harness.getPlaceholder();\n return HarnessPredicate.stringMatches(text, placeholder);\n })\n .addOption('disabled', options.disabled, async (harness, disabled) => {\n return (await harness.isDisabled()) === disabled;\n })\n .addOption('open', options.open, async (harness, open) => {\n return (await harness.isOpen()) === open;\n });\n }\n\n /** Whether the datepicker panel is currently open. */\n async isOpen(): Promise<boolean> {\n const trigger = await this.triggerGroup();\n return (await trigger.getAttribute('aria-expanded')) === 'true';\n }\n\n /** Opens the datepicker panel if it is closed. */\n async open(): Promise<void> {\n if (!(await this.isOpen())) {\n const btn = await this.calendarButton();\n await btn.click();\n }\n }\n\n /** Closes the datepicker panel if it is open. */\n async close(): Promise<void> {\n if (await this.isOpen()) {\n const host = await this.host();\n await host.sendKeys(TestKey.ESCAPE);\n }\n }\n\n /** Whether the datepicker is disabled. */\n async isDisabled(): Promise<boolean> {\n const trigger = await this.triggerGroup();\n return (await trigger.getAttribute('aria-disabled')) === 'true';\n }\n\n /** Whether the datepicker input has the required attribute. */\n async isRequired(): Promise<boolean> {\n const inputEl = await this.input();\n return (await inputEl.getAttribute('aria-required')) === 'true';\n }\n\n /** Whether the datepicker input is in an invalid state. */\n async isInvalid(): Promise<boolean> {\n const inputEl = await this.input();\n return (await inputEl.getAttribute('aria-invalid')) === 'true';\n }\n\n /** Gets the current value displayed in the input. */\n async getInputValue(): Promise<string> {\n const inputEl = await this.input();\n return inputEl.getProperty<string>('value');\n }\n\n /** Sets the input value by clearing and typing the given text. */\n async setInputValue(text: string): Promise<void> {\n const inputEl = await this.input();\n await inputEl.clear();\n await inputEl.sendKeys(text);\n }\n\n /** Gets the placeholder text of the input. */\n async getPlaceholder(): Promise<string> {\n const inputEl = await this.input();\n return (await inputEl.getAttribute('placeholder')) ?? '';\n }\n\n /** Whether the datepicker currently has a value (clear button is visible). */\n async hasValue(): Promise<boolean> {\n const clearBtn = await this.clearButton();\n return clearBtn !== null;\n }\n\n /** Clears the current value by clicking the clear button. Throws if no value is set. */\n async clear(): Promise<void> {\n const clearBtn = await this.clearButton();\n if (!clearBtn) {\n throw new Error('Datepicker does not have a clearable value');\n }\n return clearBtn.click();\n }\n\n /** Gets the calendar panel element from the overlay. The datepicker must be open. */\n async getCalendarPanel(): Promise<TestElement> {\n if (!(await this.isOpen())) {\n throw new Error('Datepicker panel is not open');\n }\n return this.documentRootLocatorFactory().locatorFor('com-calendar')();\n }\n\n /** Selects a day by its visible number. Opens the panel if closed. */\n async selectDate(day: number): Promise<void> {\n await this.open();\n const rootLocator = this.documentRootLocatorFactory();\n const dayButtons = await rootLocator.locatorForAll('div[role=\"dialog\"] com-calendar-cell button')();\n for (const btn of dayButtons) {\n const text = (await btn.text()).trim();\n if (text === String(day)) {\n await btn.click();\n return;\n }\n }\n throw new Error(`Could not find day cell with number: ${day}`);\n }\n\n /** Focuses the datepicker input. */\n async focus(): Promise<void> {\n const inputEl = await this.input();\n return inputEl.focus();\n }\n\n /** Blurs the datepicker input. */\n async blur(): Promise<void> {\n const inputEl = await this.input();\n return inputEl.blur();\n }\n\n /** Whether the datepicker input is currently focused. */\n async isFocused(): Promise<boolean> {\n const inputEl = await this.input();\n return inputEl.isFocused();\n }\n}\n","// Testing utilities for the datepicker component\n\nexport { ComDatepickerHarness } from './datepicker.harness';\n\nexport type { ComDatepickerHarnessFilters } from './datepicker.harness';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAiBA;;AAEG;AACG,MAAO,oBAAqB,SAAQ,gBAAgB,CAAA;AACxD,IAAA,OAAO,YAAY,GAAG,gBAAgB;AAErB,IAAA,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC;AACnD,IAAA,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC;AAC7C,IAAA,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,iCAAiC,CAAC;AACxE,IAAA,cAAc,GAAG,IAAI,CAAC,UAAU,CAAC,gCAAgC,CAAC;AAEnF;;;AAGG;AACH,IAAA,OAAO,IAAI,CAAC,OAAA,GAAuC,EAAE,EAAA;AACnD,QAAA,OAAO,IAAI,gBAAgB,CAAC,oBAAoB,EAAE,OAAO;AACtD,aAAA,SAAS,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,OAAO,EAAE,WAAW,KAAI;AAC5E,YAAA,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE;YAC3C,OAAO,gBAAgB,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC;AAC1D,QAAA,CAAC;AACA,aAAA,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAI;YACnE,OAAO,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,MAAM,QAAQ;AAClD,QAAA,CAAC;AACA,aAAA,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,OAAO,EAAE,IAAI,KAAI;YACvD,OAAO,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI;AAC1C,QAAA,CAAC,CAAC;IACN;;AAGA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE;QACzC,OAAO,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,MAAM,MAAM;IACjE;;AAGA,IAAA,MAAM,IAAI,GAAA;QACR,IAAI,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;AAC1B,YAAA,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE;AACvC,YAAA,MAAM,GAAG,CAAC,KAAK,EAAE;QACnB;IACF;;AAGA,IAAA,MAAM,KAAK,GAAA;AACT,QAAA,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE;AACvB,YAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;YAC9B,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QACrC;IACF;;AAGA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE;QACzC,OAAO,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,MAAM,MAAM;IACjE;;AAGA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE;QAClC,OAAO,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,MAAM,MAAM;IACjE;;AAGA,IAAA,MAAM,SAAS,GAAA;AACb,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE;QAClC,OAAO,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,MAAM;IAChE;;AAGA,IAAA,MAAM,aAAa,GAAA;AACjB,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE;AAClC,QAAA,OAAO,OAAO,CAAC,WAAW,CAAS,OAAO,CAAC;IAC7C;;IAGA,MAAM,aAAa,CAAC,IAAY,EAAA;AAC9B,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE;AAClC,QAAA,MAAM,OAAO,CAAC,KAAK,EAAE;AACrB,QAAA,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC9B;;AAGA,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE;QAClC,OAAO,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,KAAK,EAAE;IAC1D;;AAGA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;QACzC,OAAO,QAAQ,KAAK,IAAI;IAC1B;;AAGA,IAAA,MAAM,KAAK,GAAA;AACT,QAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;QACzC,IAAI,CAAC,QAAQ,EAAE;AACb,YAAA,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC;QAC/D;AACA,QAAA,OAAO,QAAQ,CAAC,KAAK,EAAE;IACzB;;AAGA,IAAA,MAAM,gBAAgB,GAAA;QACpB,IAAI,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;AAC1B,YAAA,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC;QACjD;QACA,OAAO,IAAI,CAAC,0BAA0B,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE;IACvE;;IAGA,MAAM,UAAU,CAAC,GAAW,EAAA;AAC1B,QAAA,MAAM,IAAI,CAAC,IAAI,EAAE;AACjB,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,0BAA0B,EAAE;QACrD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,6CAA6C,CAAC,EAAE;AACnG,QAAA,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;AAC5B,YAAA,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE;AACtC,YAAA,IAAI,IAAI,KAAK,MAAM,CAAC,GAAG,CAAC,EAAE;AACxB,gBAAA,MAAM,GAAG,CAAC,KAAK,EAAE;gBACjB;YACF;QACF;AACA,QAAA,MAAM,IAAI,KAAK,CAAC,wCAAwC,GAAG,CAAA,CAAE,CAAC;IAChE;;AAGA,IAAA,MAAM,KAAK,GAAA;AACT,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE;AAClC,QAAA,OAAO,OAAO,CAAC,KAAK,EAAE;IACxB;;AAGA,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE;AAClC,QAAA,OAAO,OAAO,CAAC,IAAI,EAAE;IACvB;;AAGA,IAAA,MAAM,SAAS,GAAA;AACb,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE;AAClC,QAAA,OAAO,OAAO,CAAC,SAAS,EAAE;IAC5B;;;AC/JF;;ACAA;;AAEG;;;;"}
@@ -0,0 +1,109 @@
1
+ import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';
2
+
3
+ /**
4
+ * Harness for interacting with a dialog container in tests.
5
+ *
6
+ * Because dialogs render inside a CDK overlay (outside the component tree),
7
+ * obtain this harness via `TestbedHarnessEnvironment.documentRootLoader(fixture)`.
8
+ */
9
+ class ComDialogContainerHarness extends ComponentHarness {
10
+ static hostSelector = 'com-dialog-container';
11
+ panel = this.locatorFor('[role="dialog"], [role="alertdialog"]');
12
+ titleEl = this.locatorForOptional('[comDialogTitle]');
13
+ contentEl = this.locatorForOptional('[comDialogContent]');
14
+ actionsEl = this.locatorForOptional('[comDialogActions]');
15
+ closeButton = this.locatorForOptional('[comDialogClose]');
16
+ /**
17
+ * Gets a HarnessPredicate for matching dialog containers.
18
+ * @param options Filter options.
19
+ */
20
+ static with(options = {}) {
21
+ return new HarnessPredicate(ComDialogContainerHarness, options);
22
+ }
23
+ /** Gets the dialog panel's `aria-label` attribute. */
24
+ async getAriaLabel() {
25
+ const el = await this.panel();
26
+ return el.getAttribute('aria-label');
27
+ }
28
+ /** Gets the dialog panel's `aria-labelledby` attribute. */
29
+ async getAriaLabelledby() {
30
+ const el = await this.panel();
31
+ return el.getAttribute('aria-labelledby');
32
+ }
33
+ /** Gets the dialog panel's `aria-describedby` attribute. */
34
+ async getAriaDescribedby() {
35
+ const el = await this.panel();
36
+ return el.getAttribute('aria-describedby');
37
+ }
38
+ /** Gets the role attribute on the dialog panel. */
39
+ async getRole() {
40
+ const el = await this.panel();
41
+ return el.getAttribute('role');
42
+ }
43
+ /** Gets the text content of the `[comDialogTitle]` element, or null if none exists. */
44
+ async getTitleText() {
45
+ const el = await this.titleEl();
46
+ return el ? el.text() : null;
47
+ }
48
+ /** Gets the text content of the `[comDialogContent]` element, or null if none exists. */
49
+ async getContentText() {
50
+ const el = await this.contentEl();
51
+ return el ? el.text() : null;
52
+ }
53
+ /** Gets the text content of the `[comDialogActions]` element, or null if none exists. */
54
+ async getActionsText() {
55
+ const el = await this.actionsEl();
56
+ return el ? el.text() : null;
57
+ }
58
+ /** Gets the `data-state` attribute on the dialog panel. */
59
+ async getState() {
60
+ const el = await this.panel();
61
+ return el.getAttribute('data-state');
62
+ }
63
+ /**
64
+ * Closes the dialog by clicking the `[comDialogClose]` button.
65
+ * Throws if no close button is found.
66
+ */
67
+ async close() {
68
+ const btn = await this.closeButton();
69
+ if (!btn) {
70
+ throw new Error('Could not find a [comDialogClose] element. ' +
71
+ 'Make sure the dialog template includes a button with the comDialogClose directive.');
72
+ }
73
+ await btn.click();
74
+ }
75
+ /** Sends an Escape key press to the dialog panel to close it. */
76
+ async sendEscapeKey() {
77
+ const el = await this.panel();
78
+ await el.sendKeys(TestKey.ESCAPE);
79
+ }
80
+ /** Whether the dialog container is disabled. */
81
+ async isDisabled() {
82
+ const host = await this.host();
83
+ return (await host.getAttribute('aria-disabled')) === 'true';
84
+ }
85
+ /** Whether the dialog panel is focused. */
86
+ async isFocused() {
87
+ const el = await this.panel();
88
+ return el.isFocused();
89
+ }
90
+ /** Focuses the dialog panel. */
91
+ async focus() {
92
+ const el = await this.panel();
93
+ return el.focus();
94
+ }
95
+ /** Blurs the dialog panel. */
96
+ async blur() {
97
+ const el = await this.panel();
98
+ return el.blur();
99
+ }
100
+ }
101
+
102
+ // Testing utilities for the dialog component
103
+
104
+ /**
105
+ * Generated bundle index. Do not edit.
106
+ */
107
+
108
+ export { ComDialogContainerHarness };
109
+ //# sourceMappingURL=ngx-com-components-dialog-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-com-components-dialog-testing.mjs","sources":["../../../projects/com/components/dialog/testing/dialog.harness.ts","../../../projects/com/components/dialog/testing/index.ts","../../../projects/com/components/dialog/testing/ngx-com-components-dialog-testing.ts"],"sourcesContent":["import {\n ComponentHarness,\n HarnessPredicate,\n TestKey,\n} from '@angular/cdk/testing';\nimport type { BaseHarnessFilters } from '@angular/cdk/testing';\n\n/** Harness filters for ComDialogContainerHarness. */\nexport type ComDialogContainerHarnessFilters = BaseHarnessFilters;\n\n/**\n * Harness for interacting with a dialog container in tests.\n *\n * Because dialogs render inside a CDK overlay (outside the component tree),\n * obtain this harness via `TestbedHarnessEnvironment.documentRootLoader(fixture)`.\n */\nexport class ComDialogContainerHarness extends ComponentHarness {\n static hostSelector = 'com-dialog-container';\n\n private readonly panel = this.locatorFor('[role=\"dialog\"], [role=\"alertdialog\"]');\n private readonly titleEl = this.locatorForOptional('[comDialogTitle]');\n private readonly contentEl = this.locatorForOptional('[comDialogContent]');\n private readonly actionsEl = this.locatorForOptional('[comDialogActions]');\n private readonly closeButton = this.locatorForOptional('[comDialogClose]');\n\n /**\n * Gets a HarnessPredicate for matching dialog containers.\n * @param options Filter options.\n */\n static with(\n options: ComDialogContainerHarnessFilters = {},\n ): HarnessPredicate<ComDialogContainerHarness> {\n return new HarnessPredicate(ComDialogContainerHarness, options);\n }\n\n /** Gets the dialog panel's `aria-label` attribute. */\n async getAriaLabel(): Promise<string | null> {\n const el = await this.panel();\n return el.getAttribute('aria-label');\n }\n\n /** Gets the dialog panel's `aria-labelledby` attribute. */\n async getAriaLabelledby(): Promise<string | null> {\n const el = await this.panel();\n return el.getAttribute('aria-labelledby');\n }\n\n /** Gets the dialog panel's `aria-describedby` attribute. */\n async getAriaDescribedby(): Promise<string | null> {\n const el = await this.panel();\n return el.getAttribute('aria-describedby');\n }\n\n /** Gets the role attribute on the dialog panel. */\n async getRole(): Promise<string | null> {\n const el = await this.panel();\n return el.getAttribute('role');\n }\n\n /** Gets the text content of the `[comDialogTitle]` element, or null if none exists. */\n async getTitleText(): Promise<string | null> {\n const el = await this.titleEl();\n return el ? el.text() : null;\n }\n\n /** Gets the text content of the `[comDialogContent]` element, or null if none exists. */\n async getContentText(): Promise<string | null> {\n const el = await this.contentEl();\n return el ? el.text() : null;\n }\n\n /** Gets the text content of the `[comDialogActions]` element, or null if none exists. */\n async getActionsText(): Promise<string | null> {\n const el = await this.actionsEl();\n return el ? el.text() : null;\n }\n\n /** Gets the `data-state` attribute on the dialog panel. */\n async getState(): Promise<string | null> {\n const el = await this.panel();\n return el.getAttribute('data-state');\n }\n\n /**\n * Closes the dialog by clicking the `[comDialogClose]` button.\n * Throws if no close button is found.\n */\n async close(): Promise<void> {\n const btn = await this.closeButton();\n if (!btn) {\n throw new Error(\n 'Could not find a [comDialogClose] element. ' +\n 'Make sure the dialog template includes a button with the comDialogClose directive.',\n );\n }\n await btn.click();\n }\n\n /** Sends an Escape key press to the dialog panel to close it. */\n async sendEscapeKey(): Promise<void> {\n const el = await this.panel();\n await el.sendKeys(TestKey.ESCAPE);\n }\n\n /** Whether the dialog container is disabled. */\n async isDisabled(): Promise<boolean> {\n const host = await this.host();\n return (await host.getAttribute('aria-disabled')) === 'true';\n }\n\n /** Whether the dialog panel is focused. */\n async isFocused(): Promise<boolean> {\n const el = await this.panel();\n return el.isFocused();\n }\n\n /** Focuses the dialog panel. */\n async focus(): Promise<void> {\n const el = await this.panel();\n return el.focus();\n }\n\n /** Blurs the dialog panel. */\n async blur(): Promise<void> {\n const el = await this.panel();\n return el.blur();\n }\n}\n","// Testing utilities for the dialog component\n\nexport { ComDialogContainerHarness } from './dialog.harness';\n\nexport type { ComDialogContainerHarnessFilters } from './dialog.harness';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, viewChild, signal, computed, ChangeDetectionStrategy, Component, InjectionToken, Injector, PLATFORM_ID, TemplateRef, Injectable, Directive, input } from '@angular/core';
2
+ import { InjectionToken, inject, Injector, viewChild, signal, computed, forwardRef, ChangeDetectionStrategy, Component, PLATFORM_ID, TemplateRef, Injectable, Directive, input } from '@angular/core';
3
3
  import { NgTemplateOutlet, NgComponentOutlet, NgStyle, DOCUMENT, isPlatformBrowser } from '@angular/common';
4
4
  import { Overlay } from '@angular/cdk/overlay';
5
5
  import { ComponentPortal } from '@angular/cdk/portal';
@@ -62,6 +62,13 @@ class ComDialogRef {
62
62
  }
63
63
  }
64
64
 
65
+ /**
66
+ * Injection token allowing dialog directives to register their element IDs
67
+ * with the container for ARIA binding.
68
+ * @internal
69
+ */
70
+ const COM_DIALOG_CONTAINER_REF = new InjectionToken('COM_DIALOG_CONTAINER_REF');
71
+
65
72
  /**
66
73
  * CVA variants for the dialog backdrop.
67
74
  *
@@ -189,6 +196,8 @@ function toCssValue(value) {
189
196
  * `--shadow-dialog`, `--radius-overlay`, `--font-heading`
190
197
  */
191
198
  class ComDialogContainerComponent {
199
+ /** @internal Injector for template outlet so directives can resolve container tokens. */
200
+ hostInjector = inject(Injector);
192
201
  focusTrapFactory = inject(FocusTrapFactory);
193
202
  focusTrap = null;
194
203
  animationFallback = null;
@@ -315,7 +324,9 @@ class ComDialogContainerComponent {
315
324
  // autoFocus === false: don't move focus
316
325
  }
317
326
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDialogContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
318
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDialogContainerComponent, isStandalone: true, selector: "com-dialog-container", viewQueries: [{ propertyName: "panelElement", first: true, predicate: ["panelElement"], descendants: true, isSignal: true }], ngImport: i0, template: `
327
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDialogContainerComponent, isStandalone: true, selector: "com-dialog-container", providers: [
328
+ { provide: COM_DIALOG_CONTAINER_REF, useExisting: forwardRef(() => ComDialogContainerComponent) },
329
+ ], viewQueries: [{ propertyName: "panelElement", first: true, predicate: ["panelElement"], descendants: true, isSignal: true }], ngImport: i0, template: `
319
330
  @if (config()?.hasBackdrop) {
320
331
  <div
321
332
  [class]="backdropClasses()"
@@ -341,6 +352,7 @@ class ComDialogContainerComponent {
341
352
  <ng-container
342
353
  [ngTemplateOutlet]="templateContent()!"
343
354
  [ngTemplateOutletContext]="templateContext()"
355
+ [ngTemplateOutletInjector]="hostInjector"
344
356
  />
345
357
  } @else if (componentContent(); as comp) {
346
358
  @if (contentInjector(); as inj) {
@@ -380,6 +392,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
380
392
  <ng-container
381
393
  [ngTemplateOutlet]="templateContent()!"
382
394
  [ngTemplateOutletContext]="templateContext()"
395
+ [ngTemplateOutletInjector]="hostInjector"
383
396
  />
384
397
  } @else if (componentContent(); as comp) {
385
398
  @if (contentInjector(); as inj) {
@@ -389,16 +402,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
389
402
  }
390
403
  }
391
404
  </div>
392
- `, imports: [NgTemplateOutlet, NgComponentOutlet, NgStyle], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:contents}[data-state=open]{--tw-enter-opacity: 0;--tw-enter-scale: .95}[data-state=closed]{--tw-exit-opacity: 0;--tw-exit-scale: .95}@media(prefers-reduced-motion:reduce){[data-state=open],[data-state=closed]{animation:none}}\n"] }]
405
+ `, imports: [NgTemplateOutlet, NgComponentOutlet, NgStyle], providers: [
406
+ { provide: COM_DIALOG_CONTAINER_REF, useExisting: forwardRef(() => ComDialogContainerComponent) },
407
+ ], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:contents}[data-state=open]{--tw-enter-opacity: 0;--tw-enter-scale: .95}[data-state=closed]{--tw-exit-opacity: 0;--tw-exit-scale: .95}@media(prefers-reduced-motion:reduce){[data-state=open],[data-state=closed]{animation:none}}\n"] }]
393
408
  }], propDecorators: { panelElement: [{ type: i0.ViewChild, args: ['panelElement', { isSignal: true }] }] } });
394
409
 
395
- /**
396
- * Injection token allowing dialog directives to register their element IDs
397
- * with the container for ARIA binding.
398
- * @internal
399
- */
400
- const COM_DIALOG_CONTAINER_REF = new InjectionToken('COM_DIALOG_CONTAINER_REF');
401
-
402
410
  /**
403
411
  * Injection token for data passed to a dialog component.
404
412
  *
@@ -485,10 +493,6 @@ class ComDialog {
485
493
  const dialogRef = new ComDialogRef();
486
494
  // Create a child injector with dialog-specific providers
487
495
  const isTemplate = content instanceof TemplateRef;
488
- const containerRef = {
489
- registerTitleId: () => { },
490
- registerContentId: () => { },
491
- };
492
496
  // Resolve parent injector: config.injector > config.viewContainerRef.injector > service injector
493
497
  const parentInjector = resolvedConfig.injector ??
494
498
  resolvedConfig.viewContainerRef?.injector ??
@@ -498,7 +502,6 @@ class ComDialog {
498
502
  ...(resolvedConfig.providers ?? []),
499
503
  { provide: ComDialogRef, useValue: dialogRef },
500
504
  { provide: COM_DIALOG_DATA, useValue: resolvedConfig.data },
501
- { provide: COM_DIALOG_CONTAINER_REF, useValue: containerRef },
502
505
  ],
503
506
  parent: parentInjector,
504
507
  });
@@ -521,9 +524,6 @@ class ComDialog {
521
524
  const portal = new ComponentPortal(ComDialogContainerComponent, null, contentInjector);
522
525
  const containerComponentRef = overlayRef.attach(portal);
523
526
  const container = containerComponentRef.instance;
524
- // Wire up the container ref for ARIA registration
525
- containerRef.registerTitleId = (id) => container.registerTitleId(id);
526
- containerRef.registerContentId = (id) => container.registerContentId(id);
527
527
  // Configure the container
528
528
  container.config.set(resolvedConfig);
529
529
  container.dialogRef.set(dialogRef);