ux4g-components-web 1.4.1 → 1.5.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.
Files changed (124) hide show
  1. package/README.md +76 -0
  2. package/dist/__tests__/css-bundle.integration.test.d.ts +11 -0
  3. package/dist/__tests__/css-bundle.integration.test.js +1102 -0
  4. package/dist/__tests__/css-bundle.phase10.property.test.d.ts +9 -0
  5. package/dist/__tests__/css-bundle.phase10.property.test.js +64 -0
  6. package/dist/__tests__/css-bundle.phase5.property.test.d.ts +9 -0
  7. package/dist/__tests__/css-bundle.phase5.property.test.js +126 -0
  8. package/dist/__tests__/css-bundle.phase6.property.test.d.ts +9 -0
  9. package/dist/__tests__/css-bundle.phase6.property.test.js +73 -0
  10. package/dist/__tests__/css-bundle.phase7.property.test.d.ts +9 -0
  11. package/dist/__tests__/css-bundle.phase7.property.test.js +76 -0
  12. package/dist/__tests__/css-bundle.phase8.property.test.d.ts +9 -0
  13. package/dist/__tests__/css-bundle.phase8.property.test.js +67 -0
  14. package/dist/__tests__/css-bundle.phase9.property.test.d.ts +9 -0
  15. package/dist/__tests__/css-bundle.phase9.property.test.js +93 -0
  16. package/dist/__tests__/css-bundle.property.test.d.ts +14 -0
  17. package/dist/__tests__/css-bundle.property.test.js +393 -0
  18. package/dist/__tests__/dom-generators.determinism.property.test.d.ts +1 -0
  19. package/dist/__tests__/dom-generators.determinism.property.test.js +71 -0
  20. package/dist/__tests__/dom-generators.id.property.test.d.ts +1 -0
  21. package/dist/__tests__/dom-generators.id.property.test.js +99 -0
  22. package/dist/__tests__/dom-generators.otp.property.test.d.ts +1 -0
  23. package/dist/__tests__/dom-generators.property.test.d.ts +1 -0
  24. package/dist/__tests__/dom-generators.property.test.js +205 -0
  25. package/dist/__tests__/dom-generators.states.property.test.d.ts +1 -0
  26. package/dist/__tests__/dom-generators.table.property.test.d.ts +1 -0
  27. package/dist/__tests__/dom-generators.tier1.property.test.d.ts +1 -0
  28. package/dist/__tests__/dom-generators.tier1.property.test.js +403 -0
  29. package/dist/__tests__/dom-generators.validation.property.test.d.ts +1 -0
  30. package/dist/__tests__/dom-generators.validation.property.test.js +327 -0
  31. package/dist/__tests__/megamenu.classbuilder.property.test.d.ts +1 -0
  32. package/dist/__tests__/megamenu.classbuilder.property.test.js +88 -0
  33. package/dist/__tests__/smoke.test.d.ts +1 -0
  34. package/dist/__tests__/smoke.test.js +65 -0
  35. package/dist/__tests__/types.phase10.property.test.d.ts +1 -0
  36. package/dist/__tests__/types.phase10.property.test.js +166 -0
  37. package/dist/__tests__/types.phase10.test.d.ts +1 -0
  38. package/dist/__tests__/types.phase10.test.js +76 -0
  39. package/dist/__tests__/types.phase3.property.test.d.ts +1 -0
  40. package/dist/__tests__/types.phase3.property.test.js +83 -0
  41. package/dist/__tests__/types.phase3.test.d.ts +1 -0
  42. package/dist/__tests__/types.phase3.test.js +76 -0
  43. package/dist/__tests__/types.phase4.property.test.d.ts +1 -0
  44. package/dist/__tests__/types.phase4.property.test.js +119 -0
  45. package/dist/__tests__/types.phase4.test.d.ts +1 -0
  46. package/dist/__tests__/types.phase4.test.js +70 -0
  47. package/dist/__tests__/types.phase5.property.test.d.ts +1 -0
  48. package/dist/__tests__/types.phase5.property.test.js +120 -0
  49. package/dist/__tests__/types.phase5.test.d.ts +1 -0
  50. package/dist/__tests__/types.phase5.test.js +64 -0
  51. package/dist/__tests__/types.phase6.property.test.d.ts +1 -0
  52. package/dist/__tests__/types.phase6.property.test.js +189 -0
  53. package/dist/__tests__/types.phase6.test.d.ts +1 -0
  54. package/dist/__tests__/types.phase6.test.js +121 -0
  55. package/dist/__tests__/types.phase7.property.test.d.ts +1 -0
  56. package/dist/__tests__/types.phase7.property.test.js +217 -0
  57. package/dist/__tests__/types.phase7.test.d.ts +1 -0
  58. package/dist/__tests__/types.phase7.test.js +106 -0
  59. package/dist/__tests__/types.phase8.property.test.d.ts +1 -0
  60. package/dist/__tests__/types.phase8.property.test.js +224 -0
  61. package/dist/__tests__/types.phase8.test.d.ts +1 -0
  62. package/dist/__tests__/types.phase8.test.js +114 -0
  63. package/dist/__tests__/types.phase9.property.test.d.ts +1 -0
  64. package/dist/__tests__/types.phase9.property.test.js +347 -0
  65. package/dist/__tests__/types.phase9.test.d.ts +1 -0
  66. package/dist/__tests__/types.phase9.test.js +226 -0
  67. package/dist/__tests__/types.restructure.property.test.d.ts +1 -0
  68. package/dist/__tests__/types.restructure.property.test.js +76 -0
  69. package/dist/__tests__/types.test.d.ts +1 -0
  70. package/dist/__tests__/types.test.js +175 -0
  71. package/dist/dom-generators/accordion.d.ts +23 -0
  72. package/dist/dom-generators/avatar.d.ts +19 -0
  73. package/dist/dom-generators/carousel.d.ts +20 -0
  74. package/dist/dom-generators/chip.d.ts +18 -0
  75. package/dist/dom-generators/combobox.d.ts +28 -0
  76. package/dist/dom-generators/date-picker.d.ts +19 -0
  77. package/dist/dom-generators/dom-generators/accordion.d.ts +21 -0
  78. package/dist/dom-generators/dom-generators/avatar.d.ts +17 -0
  79. package/dist/dom-generators/dom-generators/carousel.d.ts +19 -0
  80. package/dist/dom-generators/dom-generators/chip.d.ts +16 -0
  81. package/dist/dom-generators/dom-generators/combobox.d.ts +26 -0
  82. package/dist/dom-generators/dom-generators/date-picker.d.ts +18 -0
  83. package/dist/dom-generators/dom-generators/drawer.d.ts +17 -0
  84. package/dist/dom-generators/dom-generators/dropdown.d.ts +26 -0
  85. package/dist/dom-generators/dom-generators/file-upload.d.ts +20 -0
  86. package/dist/dom-generators/dom-generators/id-generator.d.ts +9 -0
  87. package/dist/dom-generators/dom-generators/index.d.ts +27 -0
  88. package/dist/dom-generators/dom-generators/modal.d.ts +19 -0
  89. package/dist/dom-generators/dom-generators/otp.d.ts +16 -0
  90. package/dist/dom-generators/dom-generators/popover.d.ts +17 -0
  91. package/dist/dom-generators/dom-generators/progress.d.ts +16 -0
  92. package/dist/dom-generators/dom-generators/search.d.ts +20 -0
  93. package/dist/dom-generators/dom-generators/stepper.d.ts +21 -0
  94. package/dist/dom-generators/dom-generators/table.d.ts +23 -0
  95. package/dist/dom-generators/dom-generators/tabs.d.ts +21 -0
  96. package/dist/dom-generators/dom-generators/time-picker.d.ts +18 -0
  97. package/dist/dom-generators/dom-generators/tooltip.d.ts +17 -0
  98. package/dist/dom-generators/dom-generators/types.d.ts +27 -0
  99. package/dist/dom-generators/dom-generators/validate.d.ts +20 -0
  100. package/dist/dom-generators/drawer.d.ts +19 -0
  101. package/dist/dom-generators/dropdown.d.ts +28 -0
  102. package/dist/dom-generators/file-upload.d.ts +22 -0
  103. package/dist/dom-generators/id-generator.d.ts +9 -0
  104. package/dist/dom-generators/index.bundled.d.ts +654 -0
  105. package/dist/dom-generators/index.cjs +2029 -0
  106. package/dist/dom-generators/index.d.ts +27 -0
  107. package/dist/dom-generators/index.mjs +2001 -0
  108. package/dist/dom-generators/modal.d.ts +21 -0
  109. package/dist/dom-generators/otp.d.ts +18 -0
  110. package/dist/dom-generators/popover.d.ts +19 -0
  111. package/dist/dom-generators/progress.d.ts +18 -0
  112. package/dist/dom-generators/search.d.ts +22 -0
  113. package/dist/dom-generators/stepper.d.ts +23 -0
  114. package/dist/dom-generators/table.d.ts +25 -0
  115. package/dist/dom-generators/tabs.d.ts +23 -0
  116. package/dist/dom-generators/time-picker.d.ts +19 -0
  117. package/dist/dom-generators/tooltip.d.ts +19 -0
  118. package/dist/dom-generators/types.d.ts +155 -0
  119. package/dist/dom-generators/validate.d.ts +20 -0
  120. package/dist/runtime/bootstrap.js +59 -0
  121. package/dist/runtime/index.js +55 -0
  122. package/dist/types.d.ts +155 -0
  123. package/dist/types.js +552 -0
  124. package/package.json +12 -2
@@ -0,0 +1,1102 @@
1
+ /**
2
+ * Integration tests for CSS bundle
3
+ * Validates: Requirements 2.7, 2.9
4
+ *
5
+ * These tests verify that the built styles/ux4g.css contains the expected
6
+ * selectors for dark theme support and button disabled states.
7
+ *
8
+ * NOTE: The CSS bundle is currently built from placeholder files, so these
9
+ * tests will fail until real CSS is in place — that is expected.
10
+ */
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ const CSS_BUNDLE_PATH = path.resolve(__dirname, '../../styles/ux4g.css');
14
+ describe('CSS bundle integration tests', () => {
15
+ let cssContent = null;
16
+ let fileExists;
17
+ beforeAll(() => {
18
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
19
+ if (fileExists) {
20
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
21
+ }
22
+ });
23
+ /**
24
+ * Validates: Requirements 2.7, 2.9
25
+ */
26
+ it('styles/ux4g.css file exists after build', () => {
27
+ expect(fileExists).toBe(true);
28
+ });
29
+ /**
30
+ * Validates: Requirements 2.7
31
+ * Dark theme support via [data-theme="dark"] attribute selector
32
+ * Note: minified CSS may omit quotes: [data-theme=dark]
33
+ */
34
+ it('[data-theme="dark"] selector is present in the CSS bundle', () => {
35
+ if (!fileExists) {
36
+ throw new Error('styles/ux4g.css does not exist — run npm run build:css first');
37
+ }
38
+ if (!cssContent || cssContent.trim().length === 0) {
39
+ throw new Error('styles/ux4g.css is empty — the CSS bundle has not been built with real CSS yet');
40
+ }
41
+ // Minified CSS may use unquoted attribute values: [data-theme=dark]
42
+ const hasQuoted = cssContent.includes('[data-theme="dark"]');
43
+ const hasUnquoted = cssContent.includes('[data-theme=dark]');
44
+ expect(hasQuoted || hasUnquoted).toBe(true);
45
+ });
46
+ /**
47
+ * Validates: Requirements 2.9
48
+ * Disabled state via native :disabled pseudo-class
49
+ */
50
+ it(':disabled selector is present in button rules', () => {
51
+ if (!fileExists) {
52
+ throw new Error('styles/ux4g.css does not exist — run npm run build:css first');
53
+ }
54
+ if (!cssContent || cssContent.trim().length === 0) {
55
+ throw new Error('styles/ux4g.css is empty — the CSS bundle has not been built with real CSS yet');
56
+ }
57
+ expect(cssContent).toContain(':disabled');
58
+ });
59
+ /**
60
+ * Validates: Requirements 2.9
61
+ * Disabled state via [aria-disabled="true"] for accessibility
62
+ * Note: minified CSS may omit quotes: [aria-disabled=true]
63
+ */
64
+ it('[aria-disabled="true"] selector is present in button rules', () => {
65
+ if (!fileExists) {
66
+ throw new Error('styles/ux4g.css does not exist — run npm run build:css first');
67
+ }
68
+ if (!cssContent || cssContent.trim().length === 0) {
69
+ throw new Error('styles/ux4g.css is empty — the CSS bundle has not been built with real CSS yet');
70
+ }
71
+ // Minified CSS may use unquoted attribute values: [aria-disabled=true]
72
+ const hasQuoted = cssContent.includes('[aria-disabled="true"]');
73
+ const hasUnquoted = cssContent.includes('[aria-disabled=true]');
74
+ expect(hasQuoted || hasUnquoted).toBe(true);
75
+ });
76
+ /**
77
+ * Validates: Requirements 2.2
78
+ * Spinner base selector [class^="ux4g-spinner-"] is present in the CSS bundle
79
+ * Note: minified CSS omits quotes: [class^=ux4g-spinner-]
80
+ */
81
+ it('[class^="ux4g-spinner-"] base selector is present in the CSS bundle', () => {
82
+ if (!fileExists) {
83
+ throw new Error('styles/ux4g.css does not exist — run npm run build:css first');
84
+ }
85
+ if (!cssContent || cssContent.trim().length === 0) {
86
+ throw new Error('styles/ux4g.css is empty — the CSS bundle has not been built with real CSS yet');
87
+ }
88
+ const hasQuoted = cssContent.includes('[class^="ux4g-spinner-"]');
89
+ const hasUnquoted = cssContent.includes('[class^=ux4g-spinner-]');
90
+ expect(hasQuoted || hasUnquoted).toBe(true);
91
+ });
92
+ /**
93
+ * Validates: Requirements 2.5
94
+ * Spinner rotation keyframe animation is present in the CSS bundle
95
+ */
96
+ it('@keyframes ux4g-spinner-rotate is present in the CSS bundle', () => {
97
+ if (!fileExists) {
98
+ throw new Error('styles/ux4g.css does not exist — run npm run build:css first');
99
+ }
100
+ if (!cssContent || cssContent.trim().length === 0) {
101
+ throw new Error('styles/ux4g.css is empty — the CSS bundle has not been built with real CSS yet');
102
+ }
103
+ expect(cssContent).toContain('@keyframes ux4g-spinner-rotate');
104
+ });
105
+ /**
106
+ * Validates: Requirements 2.5
107
+ * prefers-reduced-motion media query disables spinner animation
108
+ */
109
+ it('prefers-reduced-motion media query with animation: none is present in the CSS bundle', () => {
110
+ if (!fileExists) {
111
+ throw new Error('styles/ux4g.css does not exist — run npm run build:css first');
112
+ }
113
+ if (!cssContent || cssContent.trim().length === 0) {
114
+ throw new Error('styles/ux4g.css is empty — the CSS bundle has not been built with real CSS yet');
115
+ }
116
+ expect(cssContent).toContain('prefers-reduced-motion');
117
+ expect(cssContent).toContain('animation:none');
118
+ });
119
+ /**
120
+ * Validates: Requirements 2.6
121
+ * Spinner semantic color tokens are present in the CSS bundle
122
+ */
123
+ it('spinner semantic color tokens are present in the CSS bundle', () => {
124
+ if (!fileExists) {
125
+ throw new Error('styles/ux4g.css does not exist — run npm run build:css first');
126
+ }
127
+ if (!cssContent || cssContent.trim().length === 0) {
128
+ throw new Error('styles/ux4g.css is empty — the CSS bundle has not been built with real CSS yet');
129
+ }
130
+ expect(cssContent).toContain('--Spinner-primary-Color-1');
131
+ expect(cssContent).toContain('--Spinner-Light-Color-1');
132
+ expect(cssContent).toContain('--Spinner-danger-Color-1');
133
+ });
134
+ /**
135
+ * Validates: Requirements 6.1
136
+ * Focus ring outline color token is present in the CSS bundle
137
+ */
138
+ it('--ux4g-outline-color-focus token is present in the CSS bundle', () => {
139
+ if (!fileExists) {
140
+ throw new Error('styles/ux4g.css does not exist — run npm run build:css first');
141
+ }
142
+ if (!cssContent || cssContent.trim().length === 0) {
143
+ throw new Error('styles/ux4g.css is empty — the CSS bundle has not been built with real CSS yet');
144
+ }
145
+ expect(cssContent).toContain('--ux4g-outline-color-focus');
146
+ });
147
+ });
148
+ describe('Phase 3 CSS bundle integration tests', () => {
149
+ let cssContent = null;
150
+ let fileExists;
151
+ beforeAll(() => {
152
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
153
+ if (fileExists) {
154
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
155
+ }
156
+ });
157
+ it('styles/ux4g.css contains .ux4g-text-link-sm selector', () => {
158
+ if (!fileExists || !cssContent)
159
+ throw new Error('styles/ux4g.css does not exist or is empty');
160
+ expect(cssContent).toContain('.ux4g-text-link-sm');
161
+ });
162
+ it('styles/ux4g.css contains .ux4g-text-link-neutral-md selector', () => {
163
+ if (!fileExists || !cssContent)
164
+ throw new Error('styles/ux4g.css does not exist or is empty');
165
+ expect(cssContent).toContain('.ux4g-text-link-neutral-md');
166
+ });
167
+ it('styles/ux4g.css contains ux4g-badge-dot- attribute selector', () => {
168
+ if (!fileExists || !cssContent)
169
+ throw new Error('styles/ux4g.css does not exist or is empty');
170
+ const hasQuoted = cssContent.includes('[class*="ux4g-badge-dot-"]');
171
+ const hasUnquoted = cssContent.includes('[class*=ux4g-badge-dot-]');
172
+ const hasClass = cssContent.includes('.ux4g-badge-dot-');
173
+ expect(hasQuoted || hasUnquoted || hasClass).toBe(true);
174
+ });
175
+ it('styles/ux4g.css contains ux4g-badge-icon- selector', () => {
176
+ if (!fileExists || !cssContent)
177
+ throw new Error('styles/ux4g.css does not exist or is empty');
178
+ const hasQuoted = cssContent.includes('[class*="ux4g-badge-icon-"]');
179
+ const hasUnquoted = cssContent.includes('[class*=ux4g-badge-icon-]');
180
+ const hasClass = cssContent.includes('.ux4g-badge-icon-');
181
+ expect(hasQuoted || hasUnquoted || hasClass).toBe(true);
182
+ });
183
+ it('styles/ux4g.css contains .ux4g-avatar selector', () => {
184
+ if (!fileExists || !cssContent)
185
+ throw new Error('styles/ux4g.css does not exist or is empty');
186
+ expect(cssContent).toContain('.ux4g-avatar');
187
+ });
188
+ it('styles/ux4g.css contains .ux4g-avatar-status selector', () => {
189
+ if (!fileExists || !cssContent)
190
+ throw new Error('styles/ux4g.css does not exist or is empty');
191
+ expect(cssContent).toContain('.ux4g-avatar-status');
192
+ });
193
+ it('styles/ux4g.css contains .ux4g-img selector', () => {
194
+ if (!fileExists || !cssContent)
195
+ throw new Error('styles/ux4g.css does not exist or is empty');
196
+ expect(cssContent).toContain('.ux4g-img');
197
+ });
198
+ it('styles/ux4g.css contains .ux4g-img-rounded selector', () => {
199
+ if (!fileExists || !cssContent)
200
+ throw new Error('styles/ux4g.css does not exist or is empty');
201
+ expect(cssContent).toContain('.ux4g-img-rounded');
202
+ });
203
+ it('styles/ux4g.css contains ux4g-img-overlay selector', () => {
204
+ if (!fileExists || !cssContent)
205
+ throw new Error('styles/ux4g.css does not exist or is empty');
206
+ expect(cssContent).toContain('ux4g-img-overlay');
207
+ });
208
+ it('styles/ux4g.css contains ux4g-img-overlay-bottom selector', () => {
209
+ if (!fileExists || !cssContent)
210
+ throw new Error('styles/ux4g.css does not exist or is empty');
211
+ expect(cssContent).toContain('ux4g-img-overlay-bottom');
212
+ });
213
+ });
214
+ describe('Phase 4 CSS bundle integration tests', () => {
215
+ let cssContent = null;
216
+ let fileExists;
217
+ beforeAll(() => {
218
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
219
+ if (fileExists) {
220
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
221
+ }
222
+ });
223
+ it('styles/ux4g.css contains .ux4g-filter-chip-md selector', () => {
224
+ if (!fileExists || !cssContent)
225
+ throw new Error('styles/ux4g.css does not exist or is empty');
226
+ expect(cssContent).toContain('.ux4g-filter-chip-md');
227
+ });
228
+ it('styles/ux4g.css contains .ux4g-filter-chip-sm selector', () => {
229
+ if (!fileExists || !cssContent)
230
+ throw new Error('styles/ux4g.css does not exist or is empty');
231
+ expect(cssContent).toContain('.ux4g-filter-chip-sm');
232
+ });
233
+ it('styles/ux4g.css contains .ux4g-choice-chip-md selector', () => {
234
+ if (!fileExists || !cssContent)
235
+ throw new Error('styles/ux4g.css does not exist or is empty');
236
+ expect(cssContent).toContain('.ux4g-choice-chip-md');
237
+ });
238
+ it('styles/ux4g.css contains .ux4g-choice-chip-sm selector', () => {
239
+ if (!fileExists || !cssContent)
240
+ throw new Error('styles/ux4g.css does not exist or is empty');
241
+ expect(cssContent).toContain('.ux4g-choice-chip-sm');
242
+ });
243
+ it('styles/ux4g.css contains .ux4g-input-chip-md selector', () => {
244
+ if (!fileExists || !cssContent)
245
+ throw new Error('styles/ux4g.css does not exist or is empty');
246
+ expect(cssContent).toContain('.ux4g-input-chip-md');
247
+ });
248
+ it('styles/ux4g.css contains .ux4g-input-chip-sm selector', () => {
249
+ if (!fileExists || !cssContent)
250
+ throw new Error('styles/ux4g.css does not exist or is empty');
251
+ expect(cssContent).toContain('.ux4g-input-chip-sm');
252
+ });
253
+ it('styles/ux4g.css contains .ux4g-input-chip-xs selector', () => {
254
+ if (!fileExists || !cssContent)
255
+ throw new Error('styles/ux4g.css does not exist or is empty');
256
+ expect(cssContent).toContain('.ux4g-input-chip-xs');
257
+ });
258
+ it('styles/ux4g.css contains .ux4g-tag-tonal-neutral selector', () => {
259
+ if (!fileExists || !cssContent)
260
+ throw new Error('styles/ux4g.css does not exist or is empty');
261
+ expect(cssContent).toContain('.ux4g-tag-tonal-neutral');
262
+ });
263
+ it('styles/ux4g.css contains .ux4g-tag-filled-primary selector', () => {
264
+ if (!fileExists || !cssContent)
265
+ throw new Error('styles/ux4g.css does not exist or is empty');
266
+ // Note: vendor CSS uses 'primary' for the brand/primary color in filled variant
267
+ expect(cssContent).toContain('.ux4g-tag-filled-primary');
268
+ });
269
+ it('styles/ux4g.css contains .ux4g-tag-outline-error selector', () => {
270
+ if (!fileExists || !cssContent)
271
+ throw new Error('styles/ux4g.css does not exist or is empty');
272
+ expect(cssContent).toContain('.ux4g-tag-outline-error');
273
+ });
274
+ it('styles/ux4g.css contains .ux4g-tag-text-info selector', () => {
275
+ if (!fileExists || !cssContent)
276
+ throw new Error('styles/ux4g.css does not exist or is empty');
277
+ expect(cssContent).toContain('.ux4g-tag-text-info');
278
+ });
279
+ it('styles/ux4g.css contains .ux4g-tag-s selector', () => {
280
+ if (!fileExists || !cssContent)
281
+ throw new Error('styles/ux4g.css does not exist or is empty');
282
+ expect(cssContent).toContain('.ux4g-tag-s');
283
+ });
284
+ it('styles/ux4g.css contains .ux4g-divider-horizontal selector', () => {
285
+ if (!fileExists || !cssContent)
286
+ throw new Error('styles/ux4g.css does not exist or is empty');
287
+ expect(cssContent).toContain('.ux4g-divider-horizontal');
288
+ });
289
+ it('styles/ux4g.css contains .ux4g-divider-vertical selector', () => {
290
+ if (!fileExists || !cssContent)
291
+ throw new Error('styles/ux4g.css does not exist or is empty');
292
+ expect(cssContent).toContain('.ux4g-divider-vertical');
293
+ });
294
+ it('styles/ux4g.css contains .ux4g-breadcrumb selector', () => {
295
+ if (!fileExists || !cssContent)
296
+ throw new Error('styles/ux4g.css does not exist or is empty');
297
+ expect(cssContent).toContain('.ux4g-breadcrumb');
298
+ });
299
+ it('styles/ux4g.css contains .ux4g-breadcrumb-divider selector', () => {
300
+ if (!fileExists || !cssContent)
301
+ throw new Error('styles/ux4g.css does not exist or is empty');
302
+ expect(cssContent).toContain('.ux4g-breadcrumb-divider');
303
+ });
304
+ it('styles/ux4g.css contains .ux4g-breadcrumb-icon selector', () => {
305
+ if (!fileExists || !cssContent)
306
+ throw new Error('styles/ux4g.css does not exist or is empty');
307
+ expect(cssContent).toContain('.ux4g-breadcrumb-icon');
308
+ });
309
+ });
310
+ describe('Phase 5 CSS bundle integration tests', () => {
311
+ let cssContent = null;
312
+ let fileExists;
313
+ beforeAll(() => {
314
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
315
+ if (fileExists) {
316
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
317
+ }
318
+ });
319
+ // Checkbox selectors
320
+ it('styles/ux4g.css contains .ux4g-checkbox selector', () => {
321
+ if (!fileExists || !cssContent)
322
+ throw new Error('styles/ux4g.css does not exist or is empty');
323
+ expect(cssContent).toContain('.ux4g-checkbox');
324
+ });
325
+ it('styles/ux4g.css contains .ux4g-checkbox-sm selector', () => {
326
+ if (!fileExists || !cssContent)
327
+ throw new Error('styles/ux4g.css does not exist or is empty');
328
+ expect(cssContent).toContain('.ux4g-checkbox-sm');
329
+ });
330
+ it('styles/ux4g.css contains .ux4g-checkbox-md selector', () => {
331
+ if (!fileExists || !cssContent)
332
+ throw new Error('styles/ux4g.css does not exist or is empty');
333
+ expect(cssContent).toContain('.ux4g-checkbox-md');
334
+ });
335
+ it('styles/ux4g.css contains .ux4g-checkbox-lg selector', () => {
336
+ if (!fileExists || !cssContent)
337
+ throw new Error('styles/ux4g.css does not exist or is empty');
338
+ expect(cssContent).toContain('.ux4g-checkbox-lg');
339
+ });
340
+ it('styles/ux4g.css contains .ux4g-checkbox-error selector', () => {
341
+ if (!fileExists || !cssContent)
342
+ throw new Error('styles/ux4g.css does not exist or is empty');
343
+ expect(cssContent).toContain('.ux4g-checkbox-error');
344
+ });
345
+ // Radio selectors
346
+ it('styles/ux4g.css contains .ux4g-radio selector', () => {
347
+ if (!fileExists || !cssContent)
348
+ throw new Error('styles/ux4g.css does not exist or is empty');
349
+ expect(cssContent).toContain('.ux4g-radio');
350
+ });
351
+ it('styles/ux4g.css contains .ux4g-radio-sm selector', () => {
352
+ if (!fileExists || !cssContent)
353
+ throw new Error('styles/ux4g.css does not exist or is empty');
354
+ expect(cssContent).toContain('.ux4g-radio-sm');
355
+ });
356
+ it('styles/ux4g.css contains .ux4g-radio-md selector', () => {
357
+ if (!fileExists || !cssContent)
358
+ throw new Error('styles/ux4g.css does not exist or is empty');
359
+ expect(cssContent).toContain('.ux4g-radio-md');
360
+ });
361
+ it('styles/ux4g.css contains .ux4g-radio-lg selector', () => {
362
+ if (!fileExists || !cssContent)
363
+ throw new Error('styles/ux4g.css does not exist or is empty');
364
+ expect(cssContent).toContain('.ux4g-radio-lg');
365
+ });
366
+ it('styles/ux4g.css contains .ux4g-radio-error selector', () => {
367
+ if (!fileExists || !cssContent)
368
+ throw new Error('styles/ux4g.css does not exist or is empty');
369
+ expect(cssContent).toContain('.ux4g-radio-error');
370
+ });
371
+ // Switch selectors
372
+ it('styles/ux4g.css contains .ux4g-switch selector', () => {
373
+ if (!fileExists || !cssContent)
374
+ throw new Error('styles/ux4g.css does not exist or is empty');
375
+ expect(cssContent).toContain('.ux4g-switch');
376
+ });
377
+ it('styles/ux4g.css contains .ux4g-switch-sm selector', () => {
378
+ if (!fileExists || !cssContent)
379
+ throw new Error('styles/ux4g.css does not exist or is empty');
380
+ expect(cssContent).toContain('.ux4g-switch-sm');
381
+ });
382
+ it('styles/ux4g.css contains .ux4g-switch-md selector', () => {
383
+ if (!fileExists || !cssContent)
384
+ throw new Error('styles/ux4g.css does not exist or is empty');
385
+ expect(cssContent).toContain('.ux4g-switch-md');
386
+ });
387
+ it('styles/ux4g.css contains .ux4g-switch-lg selector', () => {
388
+ if (!fileExists || !cssContent)
389
+ throw new Error('styles/ux4g.css does not exist or is empty');
390
+ expect(cssContent).toContain('.ux4g-switch-lg');
391
+ });
392
+ // Card selectors
393
+ it('styles/ux4g.css contains .ux4g-card selector', () => {
394
+ if (!fileExists || !cssContent)
395
+ throw new Error('styles/ux4g.css does not exist or is empty');
396
+ expect(cssContent).toContain('.ux4g-card');
397
+ });
398
+ it('styles/ux4g.css contains .ux4g-card-solid selector', () => {
399
+ if (!fileExists || !cssContent)
400
+ throw new Error('styles/ux4g.css does not exist or is empty');
401
+ expect(cssContent).toContain('.ux4g-card-solid');
402
+ });
403
+ it('styles/ux4g.css contains .ux4g-card-outline selector', () => {
404
+ if (!fileExists || !cssContent)
405
+ throw new Error('styles/ux4g.css does not exist or is empty');
406
+ expect(cssContent).toContain('.ux4g-card-outline');
407
+ });
408
+ it('styles/ux4g.css contains .ux4g-card-vertical selector', () => {
409
+ if (!fileExists || !cssContent)
410
+ throw new Error('styles/ux4g.css does not exist or is empty');
411
+ expect(cssContent).toContain('.ux4g-card-vertical');
412
+ });
413
+ it('styles/ux4g.css contains .ux4g-card-horizontal selector', () => {
414
+ if (!fileExists || !cssContent)
415
+ throw new Error('styles/ux4g.css does not exist or is empty');
416
+ expect(cssContent).toContain('.ux4g-card-horizontal');
417
+ });
418
+ // Input selectors
419
+ it('styles/ux4g.css contains .ux4g-input-container selector', () => {
420
+ if (!fileExists || !cssContent)
421
+ throw new Error('styles/ux4g.css does not exist or is empty');
422
+ expect(cssContent).toContain('.ux4g-input-container');
423
+ });
424
+ it('styles/ux4g.css contains .ux4g-input-sm selector', () => {
425
+ if (!fileExists || !cssContent)
426
+ throw new Error('styles/ux4g.css does not exist or is empty');
427
+ expect(cssContent).toContain('.ux4g-input-sm');
428
+ });
429
+ it('styles/ux4g.css contains .ux4g-input-md selector', () => {
430
+ if (!fileExists || !cssContent)
431
+ throw new Error('styles/ux4g.css does not exist or is empty');
432
+ expect(cssContent).toContain('.ux4g-input-md');
433
+ });
434
+ it('styles/ux4g.css contains .ux4g-input-lg selector', () => {
435
+ if (!fileExists || !cssContent)
436
+ throw new Error('styles/ux4g.css does not exist or is empty');
437
+ expect(cssContent).toContain('.ux4g-input-lg');
438
+ });
439
+ it('styles/ux4g.css contains .ux4g-input-xl selector', () => {
440
+ if (!fileExists || !cssContent)
441
+ throw new Error('styles/ux4g.css does not exist or is empty');
442
+ expect(cssContent).toContain('.ux4g-input-xl');
443
+ });
444
+ it('styles/ux4g.css contains .ux4g-input-default selector', () => {
445
+ if (!fileExists || !cssContent)
446
+ throw new Error('styles/ux4g.css does not exist or is empty');
447
+ expect(cssContent).toContain('.ux4g-input-default');
448
+ });
449
+ it('styles/ux4g.css contains .ux4g-input-error selector', () => {
450
+ if (!fileExists || !cssContent)
451
+ throw new Error('styles/ux4g.css does not exist or is empty');
452
+ expect(cssContent).toContain('.ux4g-input-error');
453
+ });
454
+ it('styles/ux4g.css contains .ux4g-input-success selector', () => {
455
+ if (!fileExists || !cssContent)
456
+ throw new Error('styles/ux4g.css does not exist or is empty');
457
+ expect(cssContent).toContain('.ux4g-input-success');
458
+ });
459
+ it('styles/ux4g.css contains .ux4g-input-warning selector', () => {
460
+ if (!fileExists || !cssContent)
461
+ throw new Error('styles/ux4g.css does not exist or is empty');
462
+ expect(cssContent).toContain('.ux4g-input-warning');
463
+ });
464
+ });
465
+ describe('Phase 6 CSS bundle integration tests', () => {
466
+ let cssContent = null;
467
+ let fileExists;
468
+ beforeAll(() => {
469
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
470
+ if (fileExists) {
471
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
472
+ }
473
+ });
474
+ // List selectors
475
+ /**
476
+ * Validates: Requirements 2.9
477
+ */
478
+ it('styles/ux4g.css contains .ux4g-list selector', () => {
479
+ if (!fileExists || !cssContent)
480
+ throw new Error('styles/ux4g.css does not exist or is empty');
481
+ expect(cssContent).toContain('.ux4g-list');
482
+ });
483
+ it('styles/ux4g.css contains .ux4g-list-default selector', () => {
484
+ if (!fileExists || !cssContent)
485
+ throw new Error('styles/ux4g.css does not exist or is empty');
486
+ expect(cssContent).toContain('.ux4g-list-default');
487
+ });
488
+ it('styles/ux4g.css contains .ux4g-list-m selector', () => {
489
+ if (!fileExists || !cssContent)
490
+ throw new Error('styles/ux4g.css does not exist or is empty');
491
+ expect(cssContent).toContain('.ux4g-list-m');
492
+ });
493
+ // Dropdown selectors
494
+ /**
495
+ * Validates: Requirements 2.9
496
+ */
497
+ it('styles/ux4g.css contains .ux4g-dropdown selector', () => {
498
+ if (!fileExists || !cssContent)
499
+ throw new Error('styles/ux4g.css does not exist or is empty');
500
+ expect(cssContent).toContain('.ux4g-dropdown');
501
+ });
502
+ it('styles/ux4g.css contains .ux4g-dropdown-button selector (selection type is implicit via :not negation)', () => {
503
+ if (!fileExists || !cssContent)
504
+ throw new Error('styles/ux4g.css does not exist or is empty');
505
+ // The dropdown CSS uses :not(.ux4g-dropdown-button):not(.ux4g-dropdown-overflow) to style the
506
+ // selection type implicitly — there is no standalone .ux4g-dropdown-selection class in the source.
507
+ // We assert .ux4g-dropdown-button as the representative dropdown type selector.
508
+ expect(cssContent).toContain('.ux4g-dropdown-button');
509
+ });
510
+ it('styles/ux4g.css contains .ux4g-dropdown-md selector', () => {
511
+ if (!fileExists || !cssContent)
512
+ throw new Error('styles/ux4g.css does not exist or is empty');
513
+ expect(cssContent).toContain('.ux4g-dropdown-md');
514
+ });
515
+ // Combobox selectors
516
+ /**
517
+ * Validates: Requirements 2.9
518
+ */
519
+ it('styles/ux4g.css contains .ux4g-combobox selector', () => {
520
+ if (!fileExists || !cssContent)
521
+ throw new Error('styles/ux4g.css does not exist or is empty');
522
+ expect(cssContent).toContain('.ux4g-combobox');
523
+ });
524
+ it('styles/ux4g.css contains .ux4g-combobox-single selector', () => {
525
+ if (!fileExists || !cssContent)
526
+ throw new Error('styles/ux4g.css does not exist or is empty');
527
+ expect(cssContent).toContain('.ux4g-combobox-single');
528
+ });
529
+ it('styles/ux4g.css contains .ux4g-combobox-md selector', () => {
530
+ if (!fileExists || !cssContent)
531
+ throw new Error('styles/ux4g.css does not exist or is empty');
532
+ expect(cssContent).toContain('.ux4g-combobox-md');
533
+ });
534
+ // Modal selectors
535
+ /**
536
+ * Validates: Requirements 2.9
537
+ */
538
+ it('styles/ux4g.css contains .ux4g-modal-backdrop selector', () => {
539
+ if (!fileExists || !cssContent)
540
+ throw new Error('styles/ux4g.css does not exist or is empty');
541
+ expect(cssContent).toContain('.ux4g-modal-backdrop');
542
+ });
543
+ it('styles/ux4g.css contains .ux4g-modal-m selector', () => {
544
+ if (!fileExists || !cssContent)
545
+ throw new Error('styles/ux4g.css does not exist or is empty');
546
+ expect(cssContent).toContain('.ux4g-modal-m');
547
+ });
548
+ it('styles/ux4g.css contains .ux4g-modal-backdrop-50 selector', () => {
549
+ if (!fileExists || !cssContent)
550
+ throw new Error('styles/ux4g.css does not exist or is empty');
551
+ expect(cssContent).toContain('.ux4g-modal-backdrop-50');
552
+ });
553
+ // Alert selectors
554
+ /**
555
+ * Validates: Requirements 2.9
556
+ */
557
+ it('styles/ux4g.css contains .ux4g-alert selector', () => {
558
+ if (!fileExists || !cssContent)
559
+ throw new Error('styles/ux4g.css does not exist or is empty');
560
+ expect(cssContent).toContain('.ux4g-alert');
561
+ });
562
+ it('styles/ux4g.css contains .ux4g-alert-info selector', () => {
563
+ if (!fileExists || !cssContent)
564
+ throw new Error('styles/ux4g.css does not exist or is empty');
565
+ expect(cssContent).toContain('.ux4g-alert-info');
566
+ });
567
+ it('styles/ux4g.css contains .ux4g-context-alert selector', () => {
568
+ if (!fileExists || !cssContent)
569
+ throw new Error('styles/ux4g.css does not exist or is empty');
570
+ expect(cssContent).toContain('.ux4g-context-alert');
571
+ });
572
+ it('styles/ux4g.css contains .ux4g-alert-container selector', () => {
573
+ if (!fileExists || !cssContent)
574
+ throw new Error('styles/ux4g.css does not exist or is empty');
575
+ expect(cssContent).toContain('.ux4g-alert-container');
576
+ });
577
+ // Search selectors
578
+ /**
579
+ * Validates: Requirements 2.9
580
+ */
581
+ it('styles/ux4g.css contains .ux4g-search-container selector', () => {
582
+ if (!fileExists || !cssContent)
583
+ throw new Error('styles/ux4g.css does not exist or is empty');
584
+ expect(cssContent).toContain('.ux4g-search-container');
585
+ });
586
+ it('styles/ux4g.css contains .ux4g-search-m selector', () => {
587
+ if (!fileExists || !cssContent)
588
+ throw new Error('styles/ux4g.css does not exist or is empty');
589
+ expect(cssContent).toContain('.ux4g-search-m');
590
+ });
591
+ });
592
+ describe('Phase 7 CSS bundle integration tests', () => {
593
+ let cssContent = null;
594
+ let fileExists;
595
+ beforeAll(() => {
596
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
597
+ if (fileExists) {
598
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
599
+ }
600
+ });
601
+ // Pagination selectors
602
+ /**
603
+ * Validates: Requirements 2.9
604
+ */
605
+ it('styles/ux4g.css contains .ux4g-pagination selector', () => {
606
+ if (!fileExists || !cssContent)
607
+ throw new Error('styles/ux4g.css does not exist or is empty');
608
+ expect(cssContent).toContain('.ux4g-pagination');
609
+ });
610
+ it('styles/ux4g.css contains .ux4g-pagination-dotted selector', () => {
611
+ if (!fileExists || !cssContent)
612
+ throw new Error('styles/ux4g.css does not exist or is empty');
613
+ expect(cssContent).toContain('.ux4g-pagination-dotted');
614
+ });
615
+ it('styles/ux4g.css contains .ux4g-pagination-solid selector', () => {
616
+ if (!fileExists || !cssContent)
617
+ throw new Error('styles/ux4g.css does not exist or is empty');
618
+ expect(cssContent).toContain('.ux4g-pagination-solid');
619
+ });
620
+ // Table selectors
621
+ /**
622
+ * Validates: Requirements 2.9
623
+ */
624
+ it('styles/ux4g.css contains .ux4g-table selector', () => {
625
+ if (!fileExists || !cssContent)
626
+ throw new Error('styles/ux4g.css does not exist or is empty');
627
+ expect(cssContent).toContain('.ux4g-table');
628
+ });
629
+ it('styles/ux4g.css contains .ux4g-table-m selector', () => {
630
+ if (!fileExists || !cssContent)
631
+ throw new Error('styles/ux4g.css does not exist or is empty');
632
+ expect(cssContent).toContain('.ux4g-table-m');
633
+ });
634
+ it('styles/ux4g.css contains .ux4g-table-column-dividers selector', () => {
635
+ if (!fileExists || !cssContent)
636
+ throw new Error('styles/ux4g.css does not exist or is empty');
637
+ expect(cssContent).toContain('.ux4g-table-column-dividers');
638
+ });
639
+ // Popover selectors
640
+ /**
641
+ * Validates: Requirements 2.9
642
+ */
643
+ it('styles/ux4g.css contains .ux4g-popover selector', () => {
644
+ if (!fileExists || !cssContent)
645
+ throw new Error('styles/ux4g.css does not exist or is empty');
646
+ expect(cssContent).toContain('.ux4g-popover');
647
+ });
648
+ it('styles/ux4g.css contains .ux4g-popover-bottom selector', () => {
649
+ if (!fileExists || !cssContent)
650
+ throw new Error('styles/ux4g.css does not exist or is empty');
651
+ expect(cssContent).toContain('.ux4g-popover-bottom');
652
+ });
653
+ it('styles/ux4g.css contains .ux4g-popover-top-start selector', () => {
654
+ if (!fileExists || !cssContent)
655
+ throw new Error('styles/ux4g.css does not exist or is empty');
656
+ expect(cssContent).toContain('.ux4g-popover-top-start');
657
+ });
658
+ // Tooltip selectors
659
+ /**
660
+ * Validates: Requirements 2.9
661
+ */
662
+ it('styles/ux4g.css contains .ux4g-tooltip-wrapper selector', () => {
663
+ if (!fileExists || !cssContent)
664
+ throw new Error('styles/ux4g.css does not exist or is empty');
665
+ expect(cssContent).toContain('.ux4g-tooltip-wrapper');
666
+ });
667
+ it('styles/ux4g.css contains .ux4g-tooltip selector', () => {
668
+ if (!fileExists || !cssContent)
669
+ throw new Error('styles/ux4g.css does not exist or is empty');
670
+ expect(cssContent).toContain('.ux4g-tooltip');
671
+ });
672
+ it('styles/ux4g.css contains .ux4g-tooltip-top-center selector', () => {
673
+ if (!fileExists || !cssContent)
674
+ throw new Error('styles/ux4g.css does not exist or is empty');
675
+ expect(cssContent).toContain('.ux4g-tooltip-top-center');
676
+ });
677
+ // Tab selectors
678
+ /**
679
+ * Validates: Requirements 2.9
680
+ */
681
+ it('styles/ux4g.css contains .ux4g-tab selector', () => {
682
+ if (!fileExists || !cssContent)
683
+ throw new Error('styles/ux4g.css does not exist or is empty');
684
+ expect(cssContent).toContain('.ux4g-tab');
685
+ });
686
+ it('styles/ux4g.css contains .ux4g-tab-underline selector', () => {
687
+ if (!fileExists || !cssContent)
688
+ throw new Error('styles/ux4g.css does not exist or is empty');
689
+ expect(cssContent).toContain('.ux4g-tab-underline');
690
+ });
691
+ it('styles/ux4g.css contains .ux4g-tab-md selector', () => {
692
+ if (!fileExists || !cssContent)
693
+ throw new Error('styles/ux4g.css does not exist or is empty');
694
+ expect(cssContent).toContain('.ux4g-tab-md');
695
+ });
696
+ // Icon Button selectors
697
+ /**
698
+ * Validates: Requirements 2.9
699
+ */
700
+ it('styles/ux4g.css contains .ux4g-icon-btn selector', () => {
701
+ if (!fileExists || !cssContent)
702
+ throw new Error('styles/ux4g.css does not exist or is empty');
703
+ expect(cssContent).toContain('.ux4g-icon-btn');
704
+ });
705
+ it('styles/ux4g.css contains .ux4g-icon-btn-primary selector', () => {
706
+ if (!fileExists || !cssContent)
707
+ throw new Error('styles/ux4g.css does not exist or is empty');
708
+ expect(cssContent).toContain('.ux4g-icon-btn-primary');
709
+ });
710
+ it('styles/ux4g.css contains .ux4g-icon-btn-md selector', () => {
711
+ if (!fileExists || !cssContent)
712
+ throw new Error('styles/ux4g.css does not exist or is empty');
713
+ expect(cssContent).toContain('.ux4g-icon-btn-md');
714
+ });
715
+ });
716
+ describe('Phase 8 CSS bundle integration tests', () => {
717
+ let cssContent = null;
718
+ let fileExists;
719
+ beforeAll(() => {
720
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
721
+ if (fileExists) {
722
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
723
+ }
724
+ });
725
+ // Accessibility Bar selectors
726
+ /**
727
+ * Validates: Requirements 2.8
728
+ */
729
+ it('styles/ux4g.css contains .ux4g-topbar selector', () => {
730
+ if (!fileExists || !cssContent)
731
+ throw new Error('styles/ux4g.css does not exist or is empty');
732
+ expect(cssContent).toContain('.ux4g-topbar');
733
+ });
734
+ it('styles/ux4g.css contains .ux4g-topbar__wrap selector', () => {
735
+ if (!fileExists || !cssContent)
736
+ throw new Error('styles/ux4g.css does not exist or is empty');
737
+ expect(cssContent).toContain('.ux4g-topbar__wrap');
738
+ });
739
+ it('styles/ux4g.css contains .ux4g-topbar__skip selector', () => {
740
+ if (!fileExists || !cssContent)
741
+ throw new Error('styles/ux4g.css does not exist or is empty');
742
+ expect(cssContent).toContain('.ux4g-topbar__skip');
743
+ });
744
+ // Accordion selectors
745
+ /**
746
+ * Validates: Requirements 2.8
747
+ */
748
+ it('styles/ux4g.css contains .ux4g-accordion selector', () => {
749
+ if (!fileExists || !cssContent)
750
+ throw new Error('styles/ux4g.css does not exist or is empty');
751
+ expect(cssContent).toContain('.ux4g-accordion');
752
+ });
753
+ it('styles/ux4g.css contains .ux4g-accordion-arrow-left selector', () => {
754
+ if (!fileExists || !cssContent)
755
+ throw new Error('styles/ux4g.css does not exist or is empty');
756
+ expect(cssContent).toContain('.ux4g-accordion-arrow-left');
757
+ });
758
+ it('styles/ux4g.css contains .ux4g-accordion-bordered selector', () => {
759
+ if (!fileExists || !cssContent)
760
+ throw new Error('styles/ux4g.css does not exist or is empty');
761
+ expect(cssContent).toContain('.ux4g-accordion-bordered');
762
+ });
763
+ // Stepper selectors
764
+ /**
765
+ * Validates: Requirements 2.8
766
+ */
767
+ it('styles/ux4g.css contains .ux4g-stepper selector', () => {
768
+ if (!fileExists || !cssContent)
769
+ throw new Error('styles/ux4g.css does not exist or is empty');
770
+ expect(cssContent).toContain('.ux4g-stepper');
771
+ });
772
+ it('styles/ux4g.css contains .ux4g-stepper-vertical selector', () => {
773
+ if (!fileExists || !cssContent)
774
+ throw new Error('styles/ux4g.css does not exist or is empty');
775
+ expect(cssContent).toContain('.ux4g-stepper-vertical');
776
+ });
777
+ it('styles/ux4g.css contains .ux4g-stepper-horizontal selector', () => {
778
+ if (!fileExists || !cssContent)
779
+ throw new Error('styles/ux4g.css does not exist or is empty');
780
+ expect(cssContent).toContain('.ux4g-stepper-horizontal');
781
+ });
782
+ it('styles/ux4g.css contains .ux4g-stepper-center selector', () => {
783
+ if (!fileExists || !cssContent)
784
+ throw new Error('styles/ux4g.css does not exist or is empty');
785
+ expect(cssContent).toContain('.ux4g-stepper-center');
786
+ });
787
+ it('styles/ux4g.css contains .ux4g-stepper-bottom-line selector', () => {
788
+ if (!fileExists || !cssContent)
789
+ throw new Error('styles/ux4g.css does not exist or is empty');
790
+ expect(cssContent).toContain('.ux4g-stepper-bottom-line');
791
+ });
792
+ // Slider selectors
793
+ /**
794
+ * Validates: Requirements 2.8
795
+ */
796
+ it('styles/ux4g.css contains .ux4g-slider-field selector', () => {
797
+ if (!fileExists || !cssContent)
798
+ throw new Error('styles/ux4g.css does not exist or is empty');
799
+ expect(cssContent).toContain('.ux4g-slider-field');
800
+ });
801
+ it('styles/ux4g.css contains .ux4g-slider-md selector', () => {
802
+ if (!fileExists || !cssContent)
803
+ throw new Error('styles/ux4g.css does not exist or is empty');
804
+ expect(cssContent).toContain('.ux4g-slider-md');
805
+ });
806
+ // Drawer selectors
807
+ /**
808
+ * Validates: Requirements 2.8
809
+ */
810
+ it('styles/ux4g.css contains .ux4g-drawer selector', () => {
811
+ if (!fileExists || !cssContent)
812
+ throw new Error('styles/ux4g.css does not exist or is empty');
813
+ expect(cssContent).toContain('.ux4g-drawer');
814
+ });
815
+ it('styles/ux4g.css contains .ux4g-drawer-right selector', () => {
816
+ if (!fileExists || !cssContent)
817
+ throw new Error('styles/ux4g.css does not exist or is empty');
818
+ expect(cssContent).toContain('.ux4g-drawer-right');
819
+ });
820
+ it('styles/ux4g.css contains .ux4g-drawer-open selector', () => {
821
+ if (!fileExists || !cssContent)
822
+ throw new Error('styles/ux4g.css does not exist or is empty');
823
+ expect(cssContent).toContain('.ux4g-drawer-open');
824
+ });
825
+ });
826
+ describe('Phase 9 CSS bundle integration tests', () => {
827
+ let cssContent = null;
828
+ let fileExists;
829
+ beforeAll(() => {
830
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
831
+ if (fileExists) {
832
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
833
+ }
834
+ });
835
+ // Date-Time Picker selectors
836
+ /**
837
+ * Validates: Requirements 16.5
838
+ */
839
+ it('styles/ux4g.css contains .ux4g-date-picker-container selector', () => {
840
+ if (!fileExists || !cssContent)
841
+ throw new Error('styles/ux4g.css does not exist or is empty');
842
+ expect(cssContent).toContain('.ux4g-date-picker-container');
843
+ });
844
+ it('styles/ux4g.css contains .ux4g-time-picker-container selector', () => {
845
+ if (!fileExists || !cssContent)
846
+ throw new Error('styles/ux4g.css does not exist or is empty');
847
+ expect(cssContent).toContain('.ux4g-time-picker-container');
848
+ });
849
+ // Status Pipeline selectors
850
+ /**
851
+ * Validates: Requirements 16.6
852
+ */
853
+ it('styles/ux4g.css contains .ux4g-status-pipeline-stepper selector', () => {
854
+ if (!fileExists || !cssContent)
855
+ throw new Error('styles/ux4g.css does not exist or is empty');
856
+ expect(cssContent).toContain('.ux4g-status-pipeline-stepper');
857
+ });
858
+ it('styles/ux4g.css contains .ux4g-status-pipeline-vertical selector', () => {
859
+ if (!fileExists || !cssContent)
860
+ throw new Error('styles/ux4g.css does not exist or is empty');
861
+ expect(cssContent).toContain('.ux4g-status-pipeline-vertical');
862
+ });
863
+ it('styles/ux4g.css contains .ux4g-status-pipeline-horizontal selector', () => {
864
+ if (!fileExists || !cssContent)
865
+ throw new Error('styles/ux4g.css does not exist or is empty');
866
+ expect(cssContent).toContain('.ux4g-status-pipeline-horizontal');
867
+ });
868
+ it('styles/ux4g.css contains .ux4g-status-pipeline-bottom-line selector', () => {
869
+ if (!fileExists || !cssContent)
870
+ throw new Error('styles/ux4g.css does not exist or is empty');
871
+ expect(cssContent).toContain('.ux4g-status-pipeline-bottom-line');
872
+ });
873
+ // Journey Timeline selectors
874
+ /**
875
+ * Validates: Requirements 16.7
876
+ */
877
+ it('styles/ux4g.css contains .ux4g-journey-timeline selector', () => {
878
+ if (!fileExists || !cssContent)
879
+ throw new Error('styles/ux4g.css does not exist or is empty');
880
+ expect(cssContent).toContain('.ux4g-journey-timeline');
881
+ });
882
+ it('styles/ux4g.css contains .ux4g-journey-timeline--vertical selector', () => {
883
+ if (!fileExists || !cssContent)
884
+ throw new Error('styles/ux4g.css does not exist or is empty');
885
+ expect(cssContent).toContain('.ux4g-journey-timeline--vertical');
886
+ });
887
+ it('styles/ux4g.css contains .ux4g-journey-timeline--horizontal selector', () => {
888
+ if (!fileExists || !cssContent)
889
+ throw new Error('styles/ux4g.css does not exist or is empty');
890
+ expect(cssContent).toContain('.ux4g-journey-timeline--horizontal');
891
+ });
892
+ // Form Field Group selectors
893
+ /**
894
+ * Validates: Requirements 16.8
895
+ */
896
+ it('styles/ux4g.css contains .ux4g-form-group selector', () => {
897
+ if (!fileExists || !cssContent)
898
+ throw new Error('styles/ux4g.css does not exist or is empty');
899
+ expect(cssContent).toContain('.ux4g-form-group');
900
+ });
901
+ // OTP Input selectors
902
+ /**
903
+ * Validates: Requirements 16.9
904
+ */
905
+ it('styles/ux4g.css contains .ux4g-otp selector', () => {
906
+ if (!fileExists || !cssContent)
907
+ throw new Error('styles/ux4g.css does not exist or is empty');
908
+ expect(cssContent).toContain('.ux4g-otp');
909
+ });
910
+ it('styles/ux4g.css contains .ux4g-otp-success selector', () => {
911
+ if (!fileExists || !cssContent)
912
+ throw new Error('styles/ux4g.css does not exist or is empty');
913
+ expect(cssContent).toContain('.ux4g-otp-success');
914
+ });
915
+ it('styles/ux4g.css contains .ux4g-otp-error selector', () => {
916
+ if (!fileExists || !cssContent)
917
+ throw new Error('styles/ux4g.css does not exist or is empty');
918
+ expect(cssContent).toContain('.ux4g-otp-error');
919
+ });
920
+ it('styles/ux4g.css contains .ux4g-otp-locked selector', () => {
921
+ if (!fileExists || !cssContent)
922
+ throw new Error('styles/ux4g.css does not exist or is empty');
923
+ expect(cssContent).toContain('.ux4g-otp-locked');
924
+ });
925
+ // File Upload selectors
926
+ /**
927
+ * Validates: Requirements 16.10
928
+ */
929
+ it('styles/ux4g.css contains .ux4g-upload selector', () => {
930
+ if (!fileExists || !cssContent)
931
+ throw new Error('styles/ux4g.css does not exist or is empty');
932
+ expect(cssContent).toContain('.ux4g-upload');
933
+ });
934
+ it('styles/ux4g.css contains .ux4g-upload-state-error selector', () => {
935
+ if (!fileExists || !cssContent)
936
+ throw new Error('styles/ux4g.css does not exist or is empty');
937
+ expect(cssContent).toContain('.ux4g-upload-state-error');
938
+ });
939
+ // Progress Indicator selectors
940
+ /**
941
+ * Validates: Requirements 16.11
942
+ */
943
+ it('styles/ux4g.css contains .ux4g-progress-bar selector', () => {
944
+ if (!fileExists || !cssContent)
945
+ throw new Error('styles/ux4g.css does not exist or is empty');
946
+ expect(cssContent).toContain('.ux4g-progress-bar');
947
+ });
948
+ it('styles/ux4g.css contains .ux4g-progress-circle selector', () => {
949
+ if (!fileExists || !cssContent)
950
+ throw new Error('styles/ux4g.css does not exist or is empty');
951
+ expect(cssContent).toContain('.ux4g-progress-circle');
952
+ });
953
+ // Feedback selectors
954
+ /**
955
+ * Validates: Requirements 16.12
956
+ */
957
+ it('styles/ux4g.css contains .ux4g-feedback selector', () => {
958
+ if (!fileExists || !cssContent)
959
+ throw new Error('styles/ux4g.css does not exist or is empty');
960
+ expect(cssContent).toContain('.ux4g-feedback');
961
+ });
962
+ // Draft Status Banner selectors
963
+ /**
964
+ * Validates: Requirements 16.13
965
+ */
966
+ it('styles/ux4g.css contains .ux4g-draft-status-bar selector', () => {
967
+ if (!fileExists || !cssContent)
968
+ throw new Error('styles/ux4g.css does not exist or is empty');
969
+ expect(cssContent).toContain('.ux4g-draft-status-bar');
970
+ });
971
+ it('styles/ux4g.css contains .ux4g-auto-draft-status-bar selector', () => {
972
+ if (!fileExists || !cssContent)
973
+ throw new Error('styles/ux4g.css does not exist or is empty');
974
+ expect(cssContent).toContain('.ux4g-auto-draft-status-bar');
975
+ });
976
+ it('styles/ux4g.css contains .ux4g-success-draft-status-bar selector', () => {
977
+ if (!fileExists || !cssContent)
978
+ throw new Error('styles/ux4g.css does not exist or is empty');
979
+ expect(cssContent).toContain('.ux4g-success-draft-status-bar');
980
+ });
981
+ // SLA Progress Indicator selectors
982
+ /**
983
+ * Validates: Requirements 16.14
984
+ */
985
+ it('styles/ux4g.css contains .ux4g-sla-circle selector', () => {
986
+ if (!fileExists || !cssContent)
987
+ throw new Error('styles/ux4g.css does not exist or is empty');
988
+ expect(cssContent).toContain('.ux4g-sla-circle');
989
+ });
990
+ it('styles/ux4g.css contains .ux4g-sla-linear selector', () => {
991
+ if (!fileExists || !cssContent)
992
+ throw new Error('styles/ux4g.css does not exist or is empty');
993
+ expect(cssContent).toContain('.ux4g-sla-linear');
994
+ });
995
+ it('styles/ux4g.css contains .ux4g-sla-badge selector', () => {
996
+ if (!fileExists || !cssContent)
997
+ throw new Error('styles/ux4g.css does not exist or is empty');
998
+ expect(cssContent).toContain('.ux4g-sla-badge');
999
+ });
1000
+ // Carousel selectors
1001
+ /**
1002
+ * Validates: Requirements 16.15
1003
+ */
1004
+ it('styles/ux4g.css contains .ux4g-carousel selector', () => {
1005
+ if (!fileExists || !cssContent)
1006
+ throw new Error('styles/ux4g.css does not exist or is empty');
1007
+ expect(cssContent).toContain('.ux4g-carousel');
1008
+ });
1009
+ // Empty State selectors
1010
+ /**
1011
+ * Validates: Requirements 16.16
1012
+ */
1013
+ it('styles/ux4g.css contains .ux4g-empty-state selector', () => {
1014
+ if (!fileExists || !cssContent)
1015
+ throw new Error('styles/ux4g.css does not exist or is empty');
1016
+ expect(cssContent).toContain('.ux4g-empty-state');
1017
+ });
1018
+ // Chip Group selectors
1019
+ /**
1020
+ * Validates: Requirements 16.17
1021
+ */
1022
+ it('styles/ux4g.css contains .ux4g-filter-chip-group selector', () => {
1023
+ if (!fileExists || !cssContent)
1024
+ throw new Error('styles/ux4g.css does not exist or is empty');
1025
+ expect(cssContent).toContain('.ux4g-filter-chip-group');
1026
+ });
1027
+ it('styles/ux4g.css contains .ux4g-choice-chip-group selector', () => {
1028
+ if (!fileExists || !cssContent)
1029
+ throw new Error('styles/ux4g.css does not exist or is empty');
1030
+ expect(cssContent).toContain('.ux4g-choice-chip-group');
1031
+ });
1032
+ // Navbar selectors
1033
+ /**
1034
+ * Validates: Requirements 16.18
1035
+ */
1036
+ it('styles/ux4g.css contains .ux4g-navbar selector', () => {
1037
+ if (!fileExists || !cssContent)
1038
+ throw new Error('styles/ux4g.css does not exist or is empty');
1039
+ expect(cssContent).toContain('.ux4g-navbar');
1040
+ });
1041
+ });
1042
+ describe('Phase 10 CSS bundle integration tests', () => {
1043
+ let cssContent = null;
1044
+ let fileExists;
1045
+ beforeAll(() => {
1046
+ fileExists = fs.existsSync(CSS_BUNDLE_PATH);
1047
+ if (fileExists) {
1048
+ cssContent = fs.readFileSync(CSS_BUNDLE_PATH, 'utf8');
1049
+ }
1050
+ });
1051
+ // Slot Grid selectors
1052
+ /**
1053
+ * Validates: Requirements 6.1
1054
+ */
1055
+ it('styles/ux4g.css contains .ux4g-time-slot-weekly-container selector', () => {
1056
+ if (!fileExists || !cssContent)
1057
+ throw new Error('styles/ux4g.css does not exist or is empty');
1058
+ expect(cssContent).toContain('.ux4g-time-slot-weekly-container');
1059
+ });
1060
+ /**
1061
+ * Validates: Requirements 6.2
1062
+ */
1063
+ it('styles/ux4g.css contains .ux4g-time-slot-compact-container selector', () => {
1064
+ if (!fileExists || !cssContent)
1065
+ throw new Error('styles/ux4g.css does not exist or is empty');
1066
+ expect(cssContent).toContain('.ux4g-time-slot-compact-container');
1067
+ });
1068
+ // Footer selectors
1069
+ /**
1070
+ * Validates: Requirements 6.3
1071
+ */
1072
+ it('styles/ux4g.css contains .ux4g-footer-primary selector', () => {
1073
+ if (!fileExists || !cssContent)
1074
+ throw new Error('styles/ux4g.css does not exist or is empty');
1075
+ expect(cssContent).toContain('.ux4g-footer-primary');
1076
+ });
1077
+ /**
1078
+ * Validates: Requirements 6.4
1079
+ */
1080
+ it('styles/ux4g.css contains .ux4g-footer-dark selector', () => {
1081
+ if (!fileExists || !cssContent)
1082
+ throw new Error('styles/ux4g.css does not exist or is empty');
1083
+ expect(cssContent).toContain('.ux4g-footer-dark');
1084
+ });
1085
+ // Result List Row selectors
1086
+ /**
1087
+ * Validates: Requirements 6.5
1088
+ */
1089
+ it('styles/ux4g.css contains .ux4g-result-list selector', () => {
1090
+ if (!fileExists || !cssContent)
1091
+ throw new Error('styles/ux4g.css does not exist or is empty');
1092
+ expect(cssContent).toContain('.ux4g-result-list');
1093
+ });
1094
+ /**
1095
+ * Validates: Requirements 6.6
1096
+ */
1097
+ it('styles/ux4g.css contains .ux4g-result-list-v1 selector', () => {
1098
+ if (!fileExists || !cssContent)
1099
+ throw new Error('styles/ux4g.css does not exist or is empty');
1100
+ expect(cssContent).toContain('.ux4g-result-list-v1');
1101
+ });
1102
+ });