@sapudex/web-components 2.26.0 → 2.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cypress/specs/TabNavigation.cy.tsx +1024 -0
- package/cypress/support/component-imports.src.ts +4 -0
- package/dist/Tab.d.ts +57 -0
- package/dist/Tab.js +67 -0
- package/dist/Tab.js.map +1 -1
- package/dist/TabNavigation.d.ts +25 -3
- package/dist/TabNavigation.js +96 -18
- package/dist/TabNavigation.js.map +1 -1
- package/dist/assets/{InputSuggestions-CG5owMFQ.js → InputSuggestions-Bm_0fOBQ.js} +1 -1
- package/dist/assets/{ListItemStandardExpandableTextTemplate-DpVr7qdn.js → ListItemStandardExpandableTextTemplate-CHXlUP-E.js} +1 -1
- package/dist/assets/{bundle.esm-CTkLMr6f.js → bundle.esm-D_SXCGNu.js} +218 -218
- package/dist/css/themes/RatingIndicator.css +1 -1
- package/dist/css/themes/Slider.css +1 -1
- package/dist/css/themes/TabNavigation.css +1 -1
- package/dist/custom-elements-internal.json +205 -154
- package/dist/custom-elements.json +186 -139
- package/dist/generated/templates/TabHeaderTemplate.lit.js +30 -11
- package/dist/generated/templates/TabHeaderTemplate.lit.js.map +1 -1
- package/dist/generated/templates/TabNavigationTemplate.lit.js +8 -6
- package/dist/generated/templates/TabNavigationTemplate.lit.js.map +1 -1
- package/dist/generated/themes/RatingIndicator.css.d.ts +1 -1
- package/dist/generated/themes/RatingIndicator.css.js +1 -1
- package/dist/generated/themes/RatingIndicator.css.js.map +1 -1
- package/dist/generated/themes/Slider.css.d.ts +1 -1
- package/dist/generated/themes/Slider.css.js +1 -1
- package/dist/generated/themes/Slider.css.js.map +1 -1
- package/dist/generated/themes/TabNavigation.css.d.ts +1 -1
- package/dist/generated/themes/TabNavigation.css.js +1 -1
- package/dist/generated/themes/TabNavigation.css.js.map +1 -1
- package/dist/vscode.html-custom-data.json +11 -1
- package/dist/web-types.json +29 -2
- package/package.json +1 -1
- package/src/Tab.ts +98 -0
- package/src/TabHeader.hbs +85 -33
- package/src/TabNavigation.hbs +16 -0
- package/src/TabNavigation.ts +109 -21
- package/src/generated/templates/TabHeaderTemplate.lit.ts +29 -10
- package/src/generated/templates/TabNavigationTemplate.lit.ts +8 -6
- package/src/generated/themes/RatingIndicator.css.ts +1 -1
- package/src/generated/themes/Slider.css.ts +1 -1
- package/src/generated/themes/TabNavigation.css.ts +1 -1
- package/src/themes/TabNavigation.css +203 -1
|
@@ -0,0 +1,1024 @@
|
|
|
1
|
+
import UDExTabNavigation from "../../src/TabNavigation.js";
|
|
2
|
+
import UDExTab from "../../src/Tab.js";
|
|
3
|
+
|
|
4
|
+
// Test fixtures
|
|
5
|
+
const verticalTabNavigation = (
|
|
6
|
+
<UDExTabNavigation orientation="Vertical" id="verticalTabNav">
|
|
7
|
+
<UDExTab text="General Settings" selected>
|
|
8
|
+
<div>
|
|
9
|
+
<h3>General Settings</h3>
|
|
10
|
+
<p>Configure your general application preferences and system settings.</p>
|
|
11
|
+
</div>
|
|
12
|
+
</UDExTab>
|
|
13
|
+
<UDExTab text="Account & Privacy">
|
|
14
|
+
<div>
|
|
15
|
+
<h3>Account & Privacy</h3>
|
|
16
|
+
<p>Manage your account information, password, and privacy settings.</p>
|
|
17
|
+
</div>
|
|
18
|
+
</UDExTab>
|
|
19
|
+
<UDExTab text="Notifications">
|
|
20
|
+
<div>
|
|
21
|
+
<h3>Notifications</h3>
|
|
22
|
+
<p>Control how and when you receive notifications from the application.</p>
|
|
23
|
+
</div>
|
|
24
|
+
</UDExTab>
|
|
25
|
+
<UDExTab text="Billing & Plans">
|
|
26
|
+
<div>
|
|
27
|
+
<h3>Billing & Plans</h3>
|
|
28
|
+
<p>View your current plan, billing information, and upgrade options.</p>
|
|
29
|
+
</div>
|
|
30
|
+
</UDExTab>
|
|
31
|
+
<UDExTab text="Help & Support">
|
|
32
|
+
<div>
|
|
33
|
+
<h3>Help & Support</h3>
|
|
34
|
+
<p>Access documentation, FAQs, and contact support team.</p>
|
|
35
|
+
</div>
|
|
36
|
+
</UDExTab>
|
|
37
|
+
</UDExTabNavigation>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const horizontalTabNavigation = (
|
|
41
|
+
<UDExTabNavigation orientation="Horizontal" id="horizontalTabNav">
|
|
42
|
+
<UDExTab text="Tab 1" selected>
|
|
43
|
+
<div><p>Content 1</p></div>
|
|
44
|
+
</UDExTab>
|
|
45
|
+
<UDExTab text="Tab 2">
|
|
46
|
+
<div><p>Content 2</p></div>
|
|
47
|
+
</UDExTab>
|
|
48
|
+
<UDExTab text="Tab 3">
|
|
49
|
+
<div><p>Content 3</p></div>
|
|
50
|
+
</UDExTab>
|
|
51
|
+
</UDExTabNavigation>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// Standard horizontal tabs with 5 tabs and badge (matching WebDriver tests)
|
|
55
|
+
const standardTabNavigation = (
|
|
56
|
+
<UDExTabNavigation orientation="Horizontal" id="standard-tab-navigation">
|
|
57
|
+
<UDExTab text="Tab Text 1" numberBadge="72" selected slot="default-1">
|
|
58
|
+
<div>Tab Content 1</div>
|
|
59
|
+
</UDExTab>
|
|
60
|
+
<UDExTab text="Tab Text 2" slot="default-2">
|
|
61
|
+
<div>Tab Content 2</div>
|
|
62
|
+
</UDExTab>
|
|
63
|
+
<UDExTab text="Tab Text 3" slot="default-3">
|
|
64
|
+
<div>Tab Content 3</div>
|
|
65
|
+
</UDExTab>
|
|
66
|
+
<UDExTab text="Tab Text 4" slot="default-4">
|
|
67
|
+
<div>Tab Content 4</div>
|
|
68
|
+
</UDExTab>
|
|
69
|
+
<UDExTab text="Tab Text 5" slot="default-5">
|
|
70
|
+
<div>Tab Content 5</div>
|
|
71
|
+
</UDExTab>
|
|
72
|
+
</UDExTabNavigation>
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
describe("Tab Navigation component", () => {
|
|
76
|
+
describe("Standard Horizontal Tabs - Rendering", () => {
|
|
77
|
+
beforeEach(() => {
|
|
78
|
+
cy.mount(standardTabNavigation);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should correctly render", () => {
|
|
82
|
+
cy.get("#standard-tab-navigation")
|
|
83
|
+
.shadow()
|
|
84
|
+
.find(".udex-tab-navigation__root")
|
|
85
|
+
.should("exist");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("the component has 5 tabs", () => {
|
|
89
|
+
cy.get("#standard-tab-navigation")
|
|
90
|
+
.shadow()
|
|
91
|
+
.find(".udex-tab-navigation__button-tab")
|
|
92
|
+
.should("have.length", 5);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("the component has contents of tabs", () => {
|
|
96
|
+
cy.get("#standard-tab-navigation")
|
|
97
|
+
.shadow()
|
|
98
|
+
.find("slot")
|
|
99
|
+
.should("have.length", 5);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("the component has badge", () => {
|
|
103
|
+
cy.get("#standard-tab-navigation")
|
|
104
|
+
.shadow()
|
|
105
|
+
.find("udex-badge")
|
|
106
|
+
.should("exist");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("the first tab should be selected", () => {
|
|
110
|
+
cy.get("#standard-tab-navigation")
|
|
111
|
+
.shadow()
|
|
112
|
+
.find(".udex-tab-navigation__button-tab--active")
|
|
113
|
+
.invoke("text")
|
|
114
|
+
.should("match", /Tab Text 1[\s\n]*72/);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("the content of the first tab should be displayed", () => {
|
|
118
|
+
cy.get("#standard-tab-navigation")
|
|
119
|
+
.find("udex-tab[selected][slot='default-1']")
|
|
120
|
+
.should("contain.text", "Tab Content 1");
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe("Standard Horizontal Tabs - Tab Selection", () => {
|
|
125
|
+
beforeEach(() => {
|
|
126
|
+
cy.mount(standardTabNavigation);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("should change the selected tab", () => {
|
|
130
|
+
cy.get("#standard-tab-navigation")
|
|
131
|
+
.shadow()
|
|
132
|
+
.find(".udex-tab-navigation__button-tab--active")
|
|
133
|
+
.invoke("text")
|
|
134
|
+
.should("match", /Tab Text 1[\s\n]*72/);
|
|
135
|
+
|
|
136
|
+
cy.get("#standard-tab-navigation")
|
|
137
|
+
.shadow()
|
|
138
|
+
.find(".udex-tab-navigation__button-tab:nth-child(2)")
|
|
139
|
+
.click();
|
|
140
|
+
|
|
141
|
+
cy.get("#standard-tab-navigation")
|
|
142
|
+
.shadow()
|
|
143
|
+
.find(".udex-tab-navigation__button-tab--active")
|
|
144
|
+
.should("contain.text", "Tab Text 2");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("should display the content of the third tab", () => {
|
|
148
|
+
cy.get("#standard-tab-navigation")
|
|
149
|
+
.shadow()
|
|
150
|
+
.find(".udex-tab-navigation__button-tab:nth-child(3)")
|
|
151
|
+
.click();
|
|
152
|
+
|
|
153
|
+
cy.get("#standard-tab-navigation")
|
|
154
|
+
.shadow()
|
|
155
|
+
.find(".udex-tab-navigation__button-tab--active")
|
|
156
|
+
.should("contain.text", "Tab Text 3");
|
|
157
|
+
|
|
158
|
+
cy.get("#standard-tab-navigation")
|
|
159
|
+
.find("udex-tab[selected][slot='default-3']")
|
|
160
|
+
.should("contain.text", "Tab Content 3");
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* NOTE: Overflow behavior tests are skipped in Cypress component testing
|
|
166
|
+
* because the TabNavigation overflow calculation depends on accurate DOM measurements
|
|
167
|
+
* that don't work reliably in the component test environment. The overflow logic
|
|
168
|
+
* triggers when tab widths exceed the container width, but in isolated component tests
|
|
169
|
+
* the dimensions aren't calculated the same way as in a full page context.
|
|
170
|
+
*
|
|
171
|
+
* The original WebDriver.io tests (TabNavigation.spec.js) that run in full page context
|
|
172
|
+
* successfully test the overflow behavior including:
|
|
173
|
+
* - More button visibility
|
|
174
|
+
* - Dropdown opening/closing
|
|
175
|
+
* - Keyboard navigation in dropdown (Arrow keys, Home, End, Enter, Escape, Tab, Shift+Tab)
|
|
176
|
+
*
|
|
177
|
+
* These tests remain in the WebDriver.io suite and provide coverage for overflow functionality.
|
|
178
|
+
*/
|
|
179
|
+
describe.skip("Horizontal Tabs - Overflow Behavior (tested in WebDriver.io)", () => {
|
|
180
|
+
// Tests skipped - see note above
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe.skip("Overflow Tabs - Accessibility Keyboard Navigation (tested in WebDriver.io)", () => {
|
|
184
|
+
// Tests skipped - see note above
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe("TabNavigation - Vertical Tabs", () => {
|
|
188
|
+
beforeEach(() => {
|
|
189
|
+
cy.mount(verticalTabNavigation);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe("Rendering", () => {
|
|
193
|
+
it("renders with correct orientation and structure", () => {
|
|
194
|
+
cy.get("[udex-tab-navigation]")
|
|
195
|
+
.should("have.attr", "orientation", "Vertical")
|
|
196
|
+
.shadow()
|
|
197
|
+
.find(".udex-tab-navigation__root")
|
|
198
|
+
.should("be.visible");
|
|
199
|
+
|
|
200
|
+
// All tabs should be visible without overflow
|
|
201
|
+
cy.get("[udex-tab-navigation]")
|
|
202
|
+
.find("udex-tab")
|
|
203
|
+
.should("have.length", 5);
|
|
204
|
+
|
|
205
|
+
cy.get("[udex-tab-navigation]")
|
|
206
|
+
.shadow()
|
|
207
|
+
.find("button[role='tab']")
|
|
208
|
+
.should("have.length", 5)
|
|
209
|
+
.each($tab => {
|
|
210
|
+
cy.wrap($tab).should("be.visible");
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("does not show More button in vertical mode", () => {
|
|
215
|
+
cy.get("[udex-tab-navigation]")
|
|
216
|
+
.shadow()
|
|
217
|
+
.find(".udex-tab-navigation__button-more")
|
|
218
|
+
.should("not.be.visible");
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("displays selected tab and content correctly", () => {
|
|
222
|
+
cy.get("[udex-tab-navigation]")
|
|
223
|
+
.shadow()
|
|
224
|
+
.find("button[role='tab'][aria-selected='true']")
|
|
225
|
+
.should("contain.text", "General Settings");
|
|
226
|
+
|
|
227
|
+
cy.get("[udex-tab-navigation]")
|
|
228
|
+
.find("udex-tab[selected]")
|
|
229
|
+
.find("h3")
|
|
230
|
+
.should("contain.text", "General Settings");
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
describe("Tab Selection", () => {
|
|
235
|
+
it("switches tabs and updates content on click", () => {
|
|
236
|
+
cy.get("[udex-tab-navigation]")
|
|
237
|
+
.shadow()
|
|
238
|
+
.find("button[role='tab']")
|
|
239
|
+
.eq(2)
|
|
240
|
+
.click();
|
|
241
|
+
|
|
242
|
+
cy.get("[udex-tab-navigation]")
|
|
243
|
+
.shadow()
|
|
244
|
+
.find("button[role='tab'][aria-selected='true']")
|
|
245
|
+
.should("contain.text", "Notifications");
|
|
246
|
+
|
|
247
|
+
cy.get("[udex-tab-navigation]")
|
|
248
|
+
.find("udex-tab[selected]")
|
|
249
|
+
.find("h3")
|
|
250
|
+
.should("contain.text", "Notifications");
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("emits tab-select event on tab change", () => {
|
|
254
|
+
const tabSelectHandler = cy.stub().as("tabSelect");
|
|
255
|
+
|
|
256
|
+
cy.mount(
|
|
257
|
+
<UDExTabNavigation orientation="Vertical" onTabSelect={tabSelectHandler}>
|
|
258
|
+
<UDExTab text="Tab 1" selected>
|
|
259
|
+
<div>Content 1</div>
|
|
260
|
+
</UDExTab>
|
|
261
|
+
<UDExTab text="Tab 2">
|
|
262
|
+
<div>Content 2</div>
|
|
263
|
+
</UDExTab>
|
|
264
|
+
</UDExTabNavigation>
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
cy.get("[udex-tab-navigation]")
|
|
268
|
+
.shadow()
|
|
269
|
+
.find("button[role='tab']")
|
|
270
|
+
.eq(1)
|
|
271
|
+
.click();
|
|
272
|
+
|
|
273
|
+
cy.get("@tabSelect").should("have.been.called");
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe("Vertical Keyboard Navigation", () => {
|
|
278
|
+
it("navigates to next tab with ArrowDown key", () => {
|
|
279
|
+
cy.get("[udex-tab-navigation]")
|
|
280
|
+
.shadow()
|
|
281
|
+
.find("button[role='tab']")
|
|
282
|
+
.eq(0)
|
|
283
|
+
.focus()
|
|
284
|
+
.realPress("ArrowDown");
|
|
285
|
+
|
|
286
|
+
cy.get("[udex-tab-navigation]")
|
|
287
|
+
.shadow()
|
|
288
|
+
.find("button[role='tab']")
|
|
289
|
+
.eq(1)
|
|
290
|
+
.should("be.focused");
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it("navigates to previous tab with ArrowUp key", () => {
|
|
294
|
+
cy.get("[udex-tab-navigation]")
|
|
295
|
+
.shadow()
|
|
296
|
+
.find("button[role='tab']")
|
|
297
|
+
.eq(2)
|
|
298
|
+
.focus()
|
|
299
|
+
.realPress("ArrowUp");
|
|
300
|
+
|
|
301
|
+
cy.get("[udex-tab-navigation]")
|
|
302
|
+
.shadow()
|
|
303
|
+
.find("button[role='tab']")
|
|
304
|
+
.eq(1)
|
|
305
|
+
.should("be.focused");
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it("wraps to first tab when pressing ArrowDown on last tab", () => {
|
|
309
|
+
cy.get("[udex-tab-navigation]")
|
|
310
|
+
.shadow()
|
|
311
|
+
.find("button[role='tab']")
|
|
312
|
+
.eq(4)
|
|
313
|
+
.focus()
|
|
314
|
+
.realPress("ArrowDown");
|
|
315
|
+
|
|
316
|
+
cy.get("[udex-tab-navigation]")
|
|
317
|
+
.shadow()
|
|
318
|
+
.find("button[role='tab']")
|
|
319
|
+
.eq(0)
|
|
320
|
+
.should("be.focused");
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it("wraps to last tab when pressing ArrowUp on first tab", () => {
|
|
324
|
+
cy.get("[udex-tab-navigation]")
|
|
325
|
+
.shadow()
|
|
326
|
+
.find("button[role='tab']")
|
|
327
|
+
.eq(0)
|
|
328
|
+
.focus()
|
|
329
|
+
.realPress("ArrowUp");
|
|
330
|
+
|
|
331
|
+
cy.get("[udex-tab-navigation]")
|
|
332
|
+
.shadow()
|
|
333
|
+
.find("button[role='tab']")
|
|
334
|
+
.eq(4)
|
|
335
|
+
.should("be.focused");
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it("does not respond to ArrowLeft key in vertical mode", () => {
|
|
339
|
+
cy.get("[udex-tab-navigation]")
|
|
340
|
+
.shadow()
|
|
341
|
+
.find("button[role='tab']")
|
|
342
|
+
.eq(1)
|
|
343
|
+
.focus()
|
|
344
|
+
.realPress("ArrowLeft");
|
|
345
|
+
|
|
346
|
+
// Focus should remain on the same tab
|
|
347
|
+
cy.get("[udex-tab-navigation]")
|
|
348
|
+
.shadow()
|
|
349
|
+
.find("button[role='tab']")
|
|
350
|
+
.eq(1)
|
|
351
|
+
.should("be.focused");
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it("does not respond to ArrowRight key in vertical mode", () => {
|
|
355
|
+
cy.get("[udex-tab-navigation]")
|
|
356
|
+
.shadow()
|
|
357
|
+
.find("button[role='tab']")
|
|
358
|
+
.eq(1)
|
|
359
|
+
.focus()
|
|
360
|
+
.realPress("ArrowRight");
|
|
361
|
+
|
|
362
|
+
// Focus should remain on the same tab
|
|
363
|
+
cy.get("[udex-tab-navigation]")
|
|
364
|
+
.shadow()
|
|
365
|
+
.find("button[role='tab']")
|
|
366
|
+
.eq(1)
|
|
367
|
+
.should("be.focused");
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it("focuses first tab with Home key", () => {
|
|
371
|
+
cy.get("[udex-tab-navigation]")
|
|
372
|
+
.shadow()
|
|
373
|
+
.find("button[role='tab']")
|
|
374
|
+
.eq(3)
|
|
375
|
+
.focus()
|
|
376
|
+
.realPress("Home");
|
|
377
|
+
|
|
378
|
+
cy.get("[udex-tab-navigation]")
|
|
379
|
+
.shadow()
|
|
380
|
+
.find("button[role='tab']")
|
|
381
|
+
.eq(0)
|
|
382
|
+
.should("be.focused");
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it("focuses last tab with End key", () => {
|
|
386
|
+
cy.get("[udex-tab-navigation]")
|
|
387
|
+
.shadow()
|
|
388
|
+
.find("button[role='tab']")
|
|
389
|
+
.eq(0)
|
|
390
|
+
.focus()
|
|
391
|
+
.realPress("End");
|
|
392
|
+
|
|
393
|
+
cy.get("[udex-tab-navigation]")
|
|
394
|
+
.shadow()
|
|
395
|
+
.find("button[role='tab']")
|
|
396
|
+
.eq(4)
|
|
397
|
+
.should("be.focused");
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it("activates tab with Enter key", () => {
|
|
401
|
+
cy.get("[udex-tab-navigation]")
|
|
402
|
+
.shadow()
|
|
403
|
+
.find("button[role='tab']")
|
|
404
|
+
.eq(2)
|
|
405
|
+
.focus()
|
|
406
|
+
.realPress("Enter");
|
|
407
|
+
|
|
408
|
+
cy.get("[udex-tab-navigation]")
|
|
409
|
+
.shadow()
|
|
410
|
+
.find("button[role='tab']")
|
|
411
|
+
.eq(2)
|
|
412
|
+
.should("have.attr", "aria-selected", "true");
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it("activates tab with Space key", () => {
|
|
416
|
+
cy.get("[udex-tab-navigation]")
|
|
417
|
+
.shadow()
|
|
418
|
+
.find("button[role='tab']")
|
|
419
|
+
.eq(3)
|
|
420
|
+
.focus()
|
|
421
|
+
.realPress("Space");
|
|
422
|
+
|
|
423
|
+
cy.get("[udex-tab-navigation]")
|
|
424
|
+
.shadow()
|
|
425
|
+
.find("button[role='tab']")
|
|
426
|
+
.eq(3)
|
|
427
|
+
.should("have.attr", "aria-selected", "true");
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
describe("TabNavigation - Horizontal Tabs", () => {
|
|
433
|
+
beforeEach(() => {
|
|
434
|
+
cy.mount(horizontalTabNavigation);
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
describe("Rendering", () => {
|
|
438
|
+
it("renders with correct orientation and structure", () => {
|
|
439
|
+
cy.get("[udex-tab-navigation]")
|
|
440
|
+
.should("have.attr", "orientation", "Horizontal")
|
|
441
|
+
.shadow()
|
|
442
|
+
.find(".udex-tab-navigation__root")
|
|
443
|
+
.should("be.visible");
|
|
444
|
+
|
|
445
|
+
cy.get("[udex-tab-navigation]")
|
|
446
|
+
.find("udex-tab")
|
|
447
|
+
.should("have.length", 3);
|
|
448
|
+
|
|
449
|
+
cy.get("[udex-tab-navigation]")
|
|
450
|
+
.shadow()
|
|
451
|
+
.find("button[role='tab']")
|
|
452
|
+
.should("have.length", 3);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it("displays selected tab and content correctly", () => {
|
|
456
|
+
cy.get("[udex-tab-navigation]")
|
|
457
|
+
.shadow()
|
|
458
|
+
.find("button[role='tab'][aria-selected='true']")
|
|
459
|
+
.should("contain.text", "Tab 1");
|
|
460
|
+
|
|
461
|
+
cy.get("[udex-tab-navigation]")
|
|
462
|
+
.find("udex-tab[selected]")
|
|
463
|
+
.find("p")
|
|
464
|
+
.should("contain.text", "Content 1");
|
|
465
|
+
});
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
describe("Tab Selection", () => {
|
|
469
|
+
it("switches tabs and updates content on click", () => {
|
|
470
|
+
cy.get("[udex-tab-navigation]")
|
|
471
|
+
.shadow()
|
|
472
|
+
.find("button[role='tab']")
|
|
473
|
+
.eq(2)
|
|
474
|
+
.click();
|
|
475
|
+
|
|
476
|
+
cy.get("[udex-tab-navigation]")
|
|
477
|
+
.shadow()
|
|
478
|
+
.find("button[role='tab'][aria-selected='true']")
|
|
479
|
+
.should("contain.text", "Tab 3");
|
|
480
|
+
|
|
481
|
+
cy.get("[udex-tab-navigation]")
|
|
482
|
+
.find("udex-tab[selected]")
|
|
483
|
+
.find("p")
|
|
484
|
+
.should("contain.text", "Content 3");
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
describe("Horizontal Keyboard Navigation", () => {
|
|
489
|
+
it("navigates to next tab with ArrowRight key", () => {
|
|
490
|
+
cy.get("[udex-tab-navigation]")
|
|
491
|
+
.shadow()
|
|
492
|
+
.find("button[role='tab']")
|
|
493
|
+
.eq(0)
|
|
494
|
+
.focus()
|
|
495
|
+
.realPress("ArrowRight");
|
|
496
|
+
|
|
497
|
+
cy.get("[udex-tab-navigation]")
|
|
498
|
+
.shadow()
|
|
499
|
+
.find("button[role='tab']")
|
|
500
|
+
.eq(1)
|
|
501
|
+
.should("be.focused");
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it("navigates to previous tab with ArrowLeft key", () => {
|
|
505
|
+
cy.get("[udex-tab-navigation]")
|
|
506
|
+
.shadow()
|
|
507
|
+
.find("button[role='tab']")
|
|
508
|
+
.eq(2)
|
|
509
|
+
.focus()
|
|
510
|
+
.realPress("ArrowLeft");
|
|
511
|
+
|
|
512
|
+
cy.get("[udex-tab-navigation]")
|
|
513
|
+
.shadow()
|
|
514
|
+
.find("button[role='tab']")
|
|
515
|
+
.eq(1)
|
|
516
|
+
.should("be.focused");
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it("wraps to first tab when pressing ArrowRight on last tab", () => {
|
|
520
|
+
cy.get("[udex-tab-navigation]")
|
|
521
|
+
.shadow()
|
|
522
|
+
.find("button[role='tab']")
|
|
523
|
+
.eq(2)
|
|
524
|
+
.focus()
|
|
525
|
+
.realPress("ArrowRight");
|
|
526
|
+
|
|
527
|
+
cy.get("[udex-tab-navigation]")
|
|
528
|
+
.shadow()
|
|
529
|
+
.find("button[role='tab']")
|
|
530
|
+
.eq(0)
|
|
531
|
+
.should("be.focused");
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
it("wraps to last tab when pressing ArrowLeft on first tab", () => {
|
|
535
|
+
cy.get("[udex-tab-navigation]")
|
|
536
|
+
.shadow()
|
|
537
|
+
.find("button[role='tab']")
|
|
538
|
+
.eq(0)
|
|
539
|
+
.focus()
|
|
540
|
+
.realPress("ArrowLeft");
|
|
541
|
+
|
|
542
|
+
cy.get("[udex-tab-navigation]")
|
|
543
|
+
.shadow()
|
|
544
|
+
.find("button[role='tab']")
|
|
545
|
+
.eq(2)
|
|
546
|
+
.should("be.focused");
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
it("does not respond to ArrowUp key in horizontal mode", () => {
|
|
550
|
+
cy.get("[udex-tab-navigation]")
|
|
551
|
+
.shadow()
|
|
552
|
+
.find("button[role='tab']")
|
|
553
|
+
.eq(1)
|
|
554
|
+
.focus()
|
|
555
|
+
.realPress("ArrowUp");
|
|
556
|
+
|
|
557
|
+
// Focus should remain on the same tab
|
|
558
|
+
cy.get("[udex-tab-navigation]")
|
|
559
|
+
.shadow()
|
|
560
|
+
.find("button[role='tab']")
|
|
561
|
+
.eq(1)
|
|
562
|
+
.should("be.focused");
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
it("does not respond to ArrowDown key in horizontal mode", () => {
|
|
566
|
+
cy.get("[udex-tab-navigation]")
|
|
567
|
+
.shadow()
|
|
568
|
+
.find("button[role='tab']")
|
|
569
|
+
.eq(1)
|
|
570
|
+
.focus()
|
|
571
|
+
.realPress("ArrowDown");
|
|
572
|
+
|
|
573
|
+
// Focus should remain on the same tab
|
|
574
|
+
cy.get("[udex-tab-navigation]")
|
|
575
|
+
.shadow()
|
|
576
|
+
.find("button[role='tab']")
|
|
577
|
+
.eq(1)
|
|
578
|
+
.should("be.focused");
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
it("focuses first tab with Home key", () => {
|
|
582
|
+
cy.get("[udex-tab-navigation]")
|
|
583
|
+
.shadow()
|
|
584
|
+
.find("button[role='tab']")
|
|
585
|
+
.eq(2)
|
|
586
|
+
.focus()
|
|
587
|
+
.realPress("Home");
|
|
588
|
+
|
|
589
|
+
cy.get("[udex-tab-navigation]")
|
|
590
|
+
.shadow()
|
|
591
|
+
.find("button[role='tab']")
|
|
592
|
+
.eq(0)
|
|
593
|
+
.should("be.focused");
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
it("focuses last tab with End key", () => {
|
|
597
|
+
cy.get("[udex-tab-navigation]")
|
|
598
|
+
.shadow()
|
|
599
|
+
.find("button[role='tab']")
|
|
600
|
+
.eq(0)
|
|
601
|
+
.focus()
|
|
602
|
+
.realPress("End");
|
|
603
|
+
|
|
604
|
+
cy.get("[udex-tab-navigation]")
|
|
605
|
+
.shadow()
|
|
606
|
+
.find("button[role='tab']")
|
|
607
|
+
.eq(2)
|
|
608
|
+
.should("be.focused");
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it("activates tab with Enter key", () => {
|
|
612
|
+
cy.get("[udex-tab-navigation]")
|
|
613
|
+
.shadow()
|
|
614
|
+
.find("button[role='tab']")
|
|
615
|
+
.eq(1)
|
|
616
|
+
.focus()
|
|
617
|
+
.realPress("Enter");
|
|
618
|
+
|
|
619
|
+
cy.get("[udex-tab-navigation]")
|
|
620
|
+
.shadow()
|
|
621
|
+
.find("button[role='tab']")
|
|
622
|
+
.eq(1)
|
|
623
|
+
.should("have.attr", "aria-selected", "true");
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
it("activates tab with Space key", () => {
|
|
627
|
+
cy.get("[udex-tab-navigation]")
|
|
628
|
+
.shadow()
|
|
629
|
+
.find("button[role='tab']")
|
|
630
|
+
.eq(2)
|
|
631
|
+
.focus()
|
|
632
|
+
.realPress("Space");
|
|
633
|
+
|
|
634
|
+
cy.get("[udex-tab-navigation]")
|
|
635
|
+
.shadow()
|
|
636
|
+
.find("button[role='tab']")
|
|
637
|
+
.eq(2)
|
|
638
|
+
.should("have.attr", "aria-selected", "true");
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
describe("Accessibility", () => {
|
|
643
|
+
it("has correct ARIA role on tabs", () => {
|
|
644
|
+
cy.get("[udex-tab-navigation]")
|
|
645
|
+
.shadow()
|
|
646
|
+
.find("button[role='tab']")
|
|
647
|
+
.should("have.length.at.least", 1);
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
it("has correct ARIA role on tab list", () => {
|
|
651
|
+
cy.get("[udex-tab-navigation]")
|
|
652
|
+
.shadow()
|
|
653
|
+
.find("[role='tablist']")
|
|
654
|
+
.should("exist");
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
it("has correct tabindex on selected tab", () => {
|
|
658
|
+
cy.get("[udex-tab-navigation]")
|
|
659
|
+
.shadow()
|
|
660
|
+
.find("button[role='tab'][aria-selected='true']")
|
|
661
|
+
.should("have.attr", "tabindex", "0");
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
it("has correct tabindex on non-selected tabs", () => {
|
|
665
|
+
cy.get("[udex-tab-navigation]")
|
|
666
|
+
.shadow()
|
|
667
|
+
.find("button[role='tab'][aria-selected='false']")
|
|
668
|
+
.should("have.attr", "tabindex", "-1");
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
it("has aria-controls attribute pointing to tab panel", () => {
|
|
672
|
+
cy.get("[udex-tab-navigation]")
|
|
673
|
+
.shadow()
|
|
674
|
+
.find("button[role='tab']")
|
|
675
|
+
.first()
|
|
676
|
+
.should("have.attr", "aria-controls");
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it("updates aria-selected when tabs change", () => {
|
|
680
|
+
cy.get("[udex-tab-navigation]")
|
|
681
|
+
.shadow()
|
|
682
|
+
.find("button[role='tab']")
|
|
683
|
+
.eq(1)
|
|
684
|
+
.click();
|
|
685
|
+
|
|
686
|
+
cy.get("[udex-tab-navigation]")
|
|
687
|
+
.shadow()
|
|
688
|
+
.find("button[role='tab']")
|
|
689
|
+
.eq(1)
|
|
690
|
+
.should("have.attr", "aria-selected", "true");
|
|
691
|
+
|
|
692
|
+
cy.get("[udex-tab-navigation]")
|
|
693
|
+
.shadow()
|
|
694
|
+
.find("button[role='tab']")
|
|
695
|
+
.eq(0)
|
|
696
|
+
.should("have.attr", "aria-selected", "false");
|
|
697
|
+
});
|
|
698
|
+
});
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
describe("TabNavigation - Body Text and Link Slot Features", () => {
|
|
702
|
+
describe("Horizontal tabs with bodyText", () => {
|
|
703
|
+
it("does NOT show body text in header for horizontal tabs", () => {
|
|
704
|
+
cy.mount(
|
|
705
|
+
<UDExTabNavigation orientation="Horizontal">
|
|
706
|
+
<UDExTab text="Settings" bodyText="Configure your preferences" selected>
|
|
707
|
+
<div>Settings content</div>
|
|
708
|
+
</UDExTab>
|
|
709
|
+
<UDExTab text="Account" bodyText="Manage your account">
|
|
710
|
+
<div>Account content</div>
|
|
711
|
+
</UDExTab>
|
|
712
|
+
</UDExTabNavigation>
|
|
713
|
+
);
|
|
714
|
+
|
|
715
|
+
// Body text should NOT be visible in the header for horizontal tabs
|
|
716
|
+
cy.get("[udex-tab-navigation]")
|
|
717
|
+
.shadow()
|
|
718
|
+
.find(".udex-tab-navigation__button-body-text")
|
|
719
|
+
.should("not.exist");
|
|
720
|
+
|
|
721
|
+
// Wrapper should NOT be used for horizontal tabs
|
|
722
|
+
cy.get("[udex-tab-navigation]")
|
|
723
|
+
.shadow()
|
|
724
|
+
.find(".udex-tab-navigation__tab-wrapper")
|
|
725
|
+
.should("not.exist");
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
it("does NOT show link slot in header for horizontal tabs", () => {
|
|
729
|
+
// Note: The Tab component uses a `link` slot for adding links
|
|
730
|
+
// In horizontal mode, even with bodyText, the wrapper and links should not be shown
|
|
731
|
+
cy.mount(
|
|
732
|
+
<UDExTabNavigation orientation="Horizontal">
|
|
733
|
+
<UDExTab text="Settings" bodyText="Configure your preferences" selected>
|
|
734
|
+
<div>Settings content</div>
|
|
735
|
+
</UDExTab>
|
|
736
|
+
<UDExTab text="Account" bodyText="Manage your account">
|
|
737
|
+
<div>Account content</div>
|
|
738
|
+
</UDExTab>
|
|
739
|
+
</UDExTabNavigation>
|
|
740
|
+
);
|
|
741
|
+
|
|
742
|
+
// Link container should NOT be visible in the header for horizontal tabs
|
|
743
|
+
cy.get("[udex-tab-navigation]")
|
|
744
|
+
.shadow()
|
|
745
|
+
.find(".udex-tab-navigation__button-links")
|
|
746
|
+
.should("not.exist");
|
|
747
|
+
|
|
748
|
+
// Wrapper should NOT be used for horizontal tabs
|
|
749
|
+
cy.get("[udex-tab-navigation]")
|
|
750
|
+
.shadow()
|
|
751
|
+
.find(".udex-tab-navigation__tab-wrapper")
|
|
752
|
+
.should("not.exist");
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
it("renders all tabs visible in horizontal mode with bodyText", () => {
|
|
756
|
+
cy.mount(
|
|
757
|
+
<UDExTabNavigation orientation="Horizontal">
|
|
758
|
+
<UDExTab text="Tab 1" bodyText="Description 1" selected>
|
|
759
|
+
<div>Content 1</div>
|
|
760
|
+
</UDExTab>
|
|
761
|
+
<UDExTab text="Tab 2" bodyText="Description 2">
|
|
762
|
+
<div>Content 2</div>
|
|
763
|
+
</UDExTab>
|
|
764
|
+
<UDExTab text="Tab 3" bodyText="Description 3">
|
|
765
|
+
<div>Content 3</div>
|
|
766
|
+
</UDExTab>
|
|
767
|
+
</UDExTabNavigation>
|
|
768
|
+
);
|
|
769
|
+
|
|
770
|
+
// All tabs should be visible
|
|
771
|
+
cy.get("[udex-tab-navigation]")
|
|
772
|
+
.shadow()
|
|
773
|
+
.find("button[role='tab']")
|
|
774
|
+
.should("have.length", 3)
|
|
775
|
+
.each($tab => {
|
|
776
|
+
cy.wrap($tab).should("be.visible");
|
|
777
|
+
});
|
|
778
|
+
});
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
describe("Vertical tabs with bodyText and link slot", () => {
|
|
782
|
+
it("shows body text in header for selected vertical tab", () => {
|
|
783
|
+
cy.mount(
|
|
784
|
+
<UDExTabNavigation orientation="Vertical">
|
|
785
|
+
<UDExTab text="Settings" bodyText="Configure your preferences" selected>
|
|
786
|
+
<div>Settings content</div>
|
|
787
|
+
</UDExTab>
|
|
788
|
+
<UDExTab text="Account" bodyText="Manage your account">
|
|
789
|
+
<div>Account content</div>
|
|
790
|
+
</UDExTab>
|
|
791
|
+
</UDExTabNavigation>
|
|
792
|
+
);
|
|
793
|
+
|
|
794
|
+
// Wrapper should be used for vertical tabs with body text
|
|
795
|
+
cy.get("[udex-tab-navigation]")
|
|
796
|
+
.shadow()
|
|
797
|
+
.find(".udex-tab-navigation__tab-wrapper")
|
|
798
|
+
.should("have.length", 2);
|
|
799
|
+
|
|
800
|
+
// Body text element should exist
|
|
801
|
+
cy.get("[udex-tab-navigation]")
|
|
802
|
+
.shadow()
|
|
803
|
+
.find(".udex-tab-navigation__button-body-text")
|
|
804
|
+
.should("have.length", 2);
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
it("shows link slot in header for vertical tabs with link elements", () => {
|
|
808
|
+
// The Tab component uses a `link` slot for adding links in vertical mode
|
|
809
|
+
// When link slot elements are provided, they should be rendered in the tab header
|
|
810
|
+
cy.mount(
|
|
811
|
+
<UDExTabNavigation orientation="Vertical">
|
|
812
|
+
<UDExTab text="Settings" selected>
|
|
813
|
+
<a slot="link" href="https://example.com">Learn more</a>
|
|
814
|
+
<div>Settings content</div>
|
|
815
|
+
</UDExTab>
|
|
816
|
+
<UDExTab text="Account">
|
|
817
|
+
<a slot="link" href="https://example.com">View details</a>
|
|
818
|
+
<div>Account content</div>
|
|
819
|
+
</UDExTab>
|
|
820
|
+
</UDExTabNavigation>
|
|
821
|
+
);
|
|
822
|
+
|
|
823
|
+
// Wrapper should be used for vertical tabs with link slot
|
|
824
|
+
cy.get("[udex-tab-navigation]")
|
|
825
|
+
.shadow()
|
|
826
|
+
.find(".udex-tab-navigation__tab-wrapper")
|
|
827
|
+
.should("have.length", 2);
|
|
828
|
+
|
|
829
|
+
// Link container should exist for tabs with link slot
|
|
830
|
+
cy.get("[udex-tab-navigation]")
|
|
831
|
+
.shadow()
|
|
832
|
+
.find(".udex-tab-navigation__button-links")
|
|
833
|
+
.should("have.length", 2);
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
it("displays body text content correctly for each vertical tab", () => {
|
|
837
|
+
cy.mount(
|
|
838
|
+
<UDExTabNavigation orientation="Vertical">
|
|
839
|
+
<UDExTab
|
|
840
|
+
text="Settings"
|
|
841
|
+
bodyText="Configure your preferences"
|
|
842
|
+
selected
|
|
843
|
+
>
|
|
844
|
+
<div>Settings content</div>
|
|
845
|
+
</UDExTab>
|
|
846
|
+
<UDExTab
|
|
847
|
+
text="Account"
|
|
848
|
+
bodyText="Manage your account"
|
|
849
|
+
>
|
|
850
|
+
<div>Account content</div>
|
|
851
|
+
</UDExTab>
|
|
852
|
+
</UDExTabNavigation>
|
|
853
|
+
);
|
|
854
|
+
|
|
855
|
+
// Body text elements should exist and contain correct text
|
|
856
|
+
cy.get("[udex-tab-navigation]")
|
|
857
|
+
.shadow()
|
|
858
|
+
.find(".udex-tab-navigation__button-body-text")
|
|
859
|
+
.should("have.length", 2);
|
|
860
|
+
|
|
861
|
+
cy.get("[udex-tab-navigation]")
|
|
862
|
+
.shadow()
|
|
863
|
+
.find(".udex-tab-navigation__button-body-text")
|
|
864
|
+
.eq(0)
|
|
865
|
+
.should("contain.text", "Configure your preferences");
|
|
866
|
+
|
|
867
|
+
cy.get("[udex-tab-navigation]")
|
|
868
|
+
.shadow()
|
|
869
|
+
.find(".udex-tab-navigation__button-body-text")
|
|
870
|
+
.eq(1)
|
|
871
|
+
.should("contain.text", "Manage your account");
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
it("does NOT use wrapper for vertical tabs without bodyText or link", () => {
|
|
875
|
+
cy.mount(
|
|
876
|
+
<UDExTabNavigation orientation="Vertical">
|
|
877
|
+
<UDExTab text="Settings" selected>
|
|
878
|
+
<div>Settings content</div>
|
|
879
|
+
</UDExTab>
|
|
880
|
+
<UDExTab text="Account">
|
|
881
|
+
<div>Account content</div>
|
|
882
|
+
</UDExTab>
|
|
883
|
+
</UDExTabNavigation>
|
|
884
|
+
);
|
|
885
|
+
|
|
886
|
+
// Wrapper should NOT be used when there's no body text or link
|
|
887
|
+
cy.get("[udex-tab-navigation]")
|
|
888
|
+
.shadow()
|
|
889
|
+
.find(".udex-tab-navigation__tab-wrapper")
|
|
890
|
+
.should("not.exist");
|
|
891
|
+
|
|
892
|
+
// Tabs should be rendered directly as buttons
|
|
893
|
+
cy.get("[udex-tab-navigation]")
|
|
894
|
+
.shadow()
|
|
895
|
+
.find("button[role='tab']")
|
|
896
|
+
.should("have.length", 2);
|
|
897
|
+
});
|
|
898
|
+
});
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
describe("TabNavigation - Additional Features", () => {
|
|
902
|
+
it("applies tabWidth property to vertical tabs", () => {
|
|
903
|
+
cy.mount(
|
|
904
|
+
<UDExTabNavigation orientation="Vertical" tabWidth="300px">
|
|
905
|
+
<UDExTab text="Settings" selected>
|
|
906
|
+
<div>Settings content</div>
|
|
907
|
+
</UDExTab>
|
|
908
|
+
<UDExTab text="Account">
|
|
909
|
+
<div>Account content</div>
|
|
910
|
+
</UDExTab>
|
|
911
|
+
</UDExTabNavigation>
|
|
912
|
+
);
|
|
913
|
+
|
|
914
|
+
cy.get("[udex-tab-navigation]")
|
|
915
|
+
.should("have.css", "--udex-tab-header-width", "300px");
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
it("applies tabWidth property with different units to vertical tabs", () => {
|
|
919
|
+
cy.mount(
|
|
920
|
+
<UDExTabNavigation orientation="Vertical" tabWidth="20rem">
|
|
921
|
+
<UDExTab text="Settings" selected>
|
|
922
|
+
<div>Settings content</div>
|
|
923
|
+
</UDExTab>
|
|
924
|
+
<UDExTab text="Account">
|
|
925
|
+
<div>Account content</div>
|
|
926
|
+
</UDExTab>
|
|
927
|
+
</UDExTabNavigation>
|
|
928
|
+
);
|
|
929
|
+
|
|
930
|
+
cy.get("[udex-tab-navigation]")
|
|
931
|
+
.should("have.css", "--udex-tab-header-width", "20rem");
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
it("uses default width when tabWidth is auto for vertical tabs", () => {
|
|
935
|
+
cy.mount(
|
|
936
|
+
<UDExTabNavigation orientation="Vertical" tabWidth="auto">
|
|
937
|
+
<UDExTab text="Settings" selected>
|
|
938
|
+
<div>Settings content</div>
|
|
939
|
+
</UDExTab>
|
|
940
|
+
<UDExTab text="Account">
|
|
941
|
+
<div>Account content</div>
|
|
942
|
+
</UDExTab>
|
|
943
|
+
</UDExTabNavigation>
|
|
944
|
+
);
|
|
945
|
+
|
|
946
|
+
// When tabWidth is "auto", the CSS variable should not be set
|
|
947
|
+
// The style attribute may be undefined or not contain the CSS variable
|
|
948
|
+
cy.get("[udex-tab-navigation]")
|
|
949
|
+
.then($el => {
|
|
950
|
+
const style = $el.attr("style") || "";
|
|
951
|
+
expect(style).to.not.contain("--udex-tab-header-width");
|
|
952
|
+
});
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
it("renders tabs with body text in vertical mode", () => {
|
|
956
|
+
cy.mount(
|
|
957
|
+
<UDExTabNavigation orientation="Vertical">
|
|
958
|
+
<UDExTab text="Settings" bodyText="Configure your preferences" selected>
|
|
959
|
+
<div>Settings content</div>
|
|
960
|
+
</UDExTab>
|
|
961
|
+
<UDExTab text="Account" bodyText="Manage your account">
|
|
962
|
+
<div>Account content</div>
|
|
963
|
+
</UDExTab>
|
|
964
|
+
</UDExTabNavigation>
|
|
965
|
+
);
|
|
966
|
+
|
|
967
|
+
cy.get("[udex-tab-navigation]")
|
|
968
|
+
.shadow()
|
|
969
|
+
.find("button[role='tab']")
|
|
970
|
+
.first()
|
|
971
|
+
.should("be.visible");
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
it("renders tabs with number badges in vertical mode", () => {
|
|
975
|
+
cy.mount(
|
|
976
|
+
<UDExTabNavigation orientation="Vertical">
|
|
977
|
+
<UDExTab text="Messages" numberBadge="5" selected>
|
|
978
|
+
<div>Messages content</div>
|
|
979
|
+
</UDExTab>
|
|
980
|
+
<UDExTab text="Notifications" numberBadge="12">
|
|
981
|
+
<div>Notifications content</div>
|
|
982
|
+
</UDExTab>
|
|
983
|
+
</UDExTabNavigation>
|
|
984
|
+
);
|
|
985
|
+
|
|
986
|
+
cy.get("[udex-tab-navigation]")
|
|
987
|
+
.shadow()
|
|
988
|
+
.find("button[role='tab']")
|
|
989
|
+
.should("have.length", 2);
|
|
990
|
+
});
|
|
991
|
+
|
|
992
|
+
it("handles tab selection in vertical mode with many tabs", () => {
|
|
993
|
+
const manyTabs = Array.from({ length: 10 }, (_, i) => (
|
|
994
|
+
<UDExTab text={`Tab ${i + 1}`} selected={i === 0}>
|
|
995
|
+
<div>Content {i + 1}</div>
|
|
996
|
+
</UDExTab>
|
|
997
|
+
));
|
|
998
|
+
|
|
999
|
+
cy.mount(
|
|
1000
|
+
<UDExTabNavigation orientation="Vertical">
|
|
1001
|
+
{manyTabs}
|
|
1002
|
+
</UDExTabNavigation>
|
|
1003
|
+
);
|
|
1004
|
+
|
|
1005
|
+
// All tabs should be visible (no overflow)
|
|
1006
|
+
cy.get("[udex-tab-navigation]")
|
|
1007
|
+
.shadow()
|
|
1008
|
+
.find("button[role='tab']")
|
|
1009
|
+
.should("have.length", 10);
|
|
1010
|
+
|
|
1011
|
+
// Click on last tab
|
|
1012
|
+
cy.get("[udex-tab-navigation]")
|
|
1013
|
+
.shadow()
|
|
1014
|
+
.find("button[role='tab']")
|
|
1015
|
+
.eq(9)
|
|
1016
|
+
.click();
|
|
1017
|
+
|
|
1018
|
+
cy.get("[udex-tab-navigation]")
|
|
1019
|
+
.shadow()
|
|
1020
|
+
.find("button[role='tab'][aria-selected='true']")
|
|
1021
|
+
.should("contain.text", "Tab 10");
|
|
1022
|
+
});
|
|
1023
|
+
});
|
|
1024
|
+
});
|