@kaizen/components 0.0.0-canary-04-titleblock-logic-20251211225600 → 0.0.0-canary-guidance-block-codemod-20251212045145
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/codemods/migrateGuidanceBlockActionsToActionsSlot/migrateGuidanceBlockActionsToActionsSlot.spec.ts +209 -26
- package/codemods/migrateGuidanceBlockActionsToActionsSlot/migrateGuidanceBlockActionsToActionsSlot.ts +24 -1
- package/codemods/migrateGuidanceBlockActionsToActionsSlot/transformActionsToActionsSlot.spec.ts +2 -1
- package/codemods/migrateGuidanceBlockActionsToActionsSlot/transformActionsToActionsSlot.ts +20 -0
- package/codemods/runV1Codemods/__snapshots__/runV1Codemods.spec.ts.snap +2 -3
- package/codemods/runV1Codemods/runV1Codemods.spec.ts +2 -3
- package/codemods/utils/transformV1ButtonPropsToButtonOrLinkButton.ts +40 -0
- package/dist/cjs/src/MenuV1/index.cjs +3 -4
- package/dist/cjs/src/MenuV1/subcomponents/MenuHeading/MenuHeading.cjs +27 -0
- package/dist/cjs/src/MenuV1/subcomponents/MenuHeading/MenuHeading.module.scss.cjs +6 -0
- package/dist/cjs/src/TitleBlock/TitleBlock.cjs +36 -32
- package/dist/cjs/src/TitleBlock/TitleBlock.module.scss.cjs +1 -5
- package/dist/cjs/src/TitleBlock/subcomponents/MainActions.cjs +45 -90
- package/dist/cjs/src/TitleBlock/subcomponents/MainActions.module.scss.cjs +1 -3
- package/dist/cjs/src/TitleBlock/subcomponents/MobileActions.cjs +306 -0
- package/dist/cjs/src/TitleBlock/subcomponents/MobileActions.module.scss.cjs +16 -0
- package/dist/cjs/src/TitleBlock/subcomponents/SecondaryActions.cjs +14 -60
- package/dist/esm/src/MenuV1/index.mjs +3 -5
- package/dist/esm/src/MenuV1/subcomponents/MenuHeading/MenuHeading.mjs +21 -0
- package/dist/esm/src/MenuV1/subcomponents/MenuHeading/MenuHeading.module.scss.mjs +4 -0
- package/dist/esm/src/TitleBlock/TitleBlock.mjs +37 -33
- package/dist/esm/src/TitleBlock/TitleBlock.module.scss.mjs +1 -5
- package/dist/esm/src/TitleBlock/subcomponents/MainActions.mjs +47 -92
- package/dist/esm/src/TitleBlock/subcomponents/MainActions.module.scss.mjs +1 -3
- package/dist/esm/src/TitleBlock/subcomponents/MobileActions.mjs +300 -0
- package/dist/esm/src/TitleBlock/subcomponents/MobileActions.module.scss.mjs +14 -0
- package/dist/esm/src/TitleBlock/subcomponents/SecondaryActions.mjs +14 -60
- package/dist/styles.css +206 -82
- package/dist/types/TitleBlock/TitleBlock.d.ts +1 -1
- package/dist/types/TitleBlock/subcomponents/MainActions.d.ts +3 -4
- package/dist/types/TitleBlock/subcomponents/MobileActions.d.ts +14 -0
- package/package.json +1 -1
- package/src/TitleBlock/TitleBlock.module.scss +14 -55
- package/src/TitleBlock/TitleBlock.spec.tsx +461 -33
- package/src/TitleBlock/TitleBlock.tsx +24 -7
- package/src/TitleBlock/_docs/TitleBlock.stories.tsx +5 -25
- package/src/TitleBlock/_mixins.scss +0 -6
- package/src/TitleBlock/subcomponents/MainActions.module.scss +2 -28
- package/src/TitleBlock/subcomponents/MainActions.tsx +70 -127
- package/src/TitleBlock/subcomponents/MobileActions.module.scss +208 -0
- package/src/TitleBlock/subcomponents/MobileActions.spec.tsx +210 -0
- package/src/TitleBlock/subcomponents/MobileActions.tsx +472 -0
- package/src/TitleBlock/subcomponents/SecondaryActions.tsx +45 -114
- package/src/TitleBlock/subcomponents/Toolbar.tsx +0 -1
|
@@ -35,15 +35,25 @@ describe('<TitleBlock />', () => {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
it('renders the primary action button label and href', () => {
|
|
38
|
-
const {
|
|
38
|
+
const { getByTestId } = render(
|
|
39
39
|
<TitleBlock title="Test Title" primaryAction={primaryActionAsLink}>
|
|
40
40
|
Example
|
|
41
41
|
</TitleBlock>,
|
|
42
42
|
)
|
|
43
|
-
const btn =
|
|
43
|
+
const btn = getByTestId('title-block-primary-action-button')
|
|
44
44
|
expect(btn.textContent).toEqual(primaryActionAsLink.label)
|
|
45
45
|
expect(btn.getAttribute('href')).toEqual(primaryActionAsLink.href)
|
|
46
46
|
})
|
|
47
|
+
|
|
48
|
+
it('passes the href to the mobile action drawer button', () => {
|
|
49
|
+
const { getByTestId } = render(
|
|
50
|
+
<TitleBlock title="Test Title" primaryAction={primaryActionAsLink}>
|
|
51
|
+
Example
|
|
52
|
+
</TitleBlock>,
|
|
53
|
+
)
|
|
54
|
+
const btn = getByTestId('title-block-mobile-actions-primary-button')
|
|
55
|
+
expect(btn.getAttribute('href')).toEqual(primaryActionAsLink.href)
|
|
56
|
+
})
|
|
47
57
|
})
|
|
48
58
|
|
|
49
59
|
describe('when the primary action is a button with only an onClick', () => {
|
|
@@ -59,12 +69,12 @@ describe('<TitleBlock />', () => {
|
|
|
59
69
|
})
|
|
60
70
|
|
|
61
71
|
it('renders the primary action button label and onClick', async () => {
|
|
62
|
-
const {
|
|
72
|
+
const { getByTestId } = render(
|
|
63
73
|
<TitleBlock title="Test Title" primaryAction={primaryActionAsButton}>
|
|
64
74
|
Example
|
|
65
75
|
</TitleBlock>,
|
|
66
76
|
)
|
|
67
|
-
const btn =
|
|
77
|
+
const btn = getByTestId('title-block-primary-action-button')
|
|
68
78
|
expect(btn.textContent).toEqual(primaryActionAsButton.label)
|
|
69
79
|
await user.click(btn)
|
|
70
80
|
|
|
@@ -72,6 +82,21 @@ describe('<TitleBlock />', () => {
|
|
|
72
82
|
expect(testOnClickFn).toHaveBeenCalled()
|
|
73
83
|
})
|
|
74
84
|
})
|
|
85
|
+
|
|
86
|
+
it('creates a mobile actions primary button', async () => {
|
|
87
|
+
const { getByTestId } = render(
|
|
88
|
+
<TitleBlock title="Test Title" primaryAction={primaryActionAsButton}>
|
|
89
|
+
Example
|
|
90
|
+
</TitleBlock>,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
const btn = getByTestId('title-block-mobile-actions-primary-button')
|
|
94
|
+
expect(btn.textContent).toEqual(primaryActionAsButton.label)
|
|
95
|
+
await user.click(btn)
|
|
96
|
+
await waitFor(() => {
|
|
97
|
+
expect(testOnClickFn).toHaveBeenCalled()
|
|
98
|
+
})
|
|
99
|
+
})
|
|
75
100
|
})
|
|
76
101
|
|
|
77
102
|
describe('when the primary action is disabled', () => {
|
|
@@ -93,12 +118,12 @@ describe('<TitleBlock />', () => {
|
|
|
93
118
|
})
|
|
94
119
|
|
|
95
120
|
it('renders a disabled primary action button', async () => {
|
|
96
|
-
const {
|
|
121
|
+
const { getByTestId } = render(
|
|
97
122
|
<TitleBlock title="Test Title" primaryAction={primaryActionAsButton}>
|
|
98
123
|
Example
|
|
99
124
|
</TitleBlock>,
|
|
100
125
|
)
|
|
101
|
-
const btn =
|
|
126
|
+
const btn = getByTestId('title-block-primary-action-button') as HTMLButtonElement
|
|
102
127
|
expect(btn.textContent).toEqual(primaryActionAsButton.label)
|
|
103
128
|
expect(btn.disabled).toBeTruthy()
|
|
104
129
|
await user.click(btn)
|
|
@@ -109,12 +134,40 @@ describe('<TitleBlock />', () => {
|
|
|
109
134
|
})
|
|
110
135
|
|
|
111
136
|
it('renders a disabled primary action link button', () => {
|
|
112
|
-
const {
|
|
137
|
+
const { getByTestId } = render(
|
|
113
138
|
<TitleBlock title="Test Title" primaryAction={primaryActionAsLink}>
|
|
114
139
|
Example
|
|
115
140
|
</TitleBlock>,
|
|
116
141
|
)
|
|
117
|
-
const btn =
|
|
142
|
+
const btn = getByTestId('title-block-primary-action-button') as HTMLButtonElement
|
|
143
|
+
expect(btn.textContent).toEqual(primaryActionAsLink.label)
|
|
144
|
+
expect(btn.getAttribute('href')).not.toEqual(primaryActionAsLink.href)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('creates a mobile actions primary button with disabled styles and no onClick', async () => {
|
|
148
|
+
const { getByTestId } = render(
|
|
149
|
+
<TitleBlock title="Test Title" primaryAction={primaryActionAsButton}>
|
|
150
|
+
Example
|
|
151
|
+
</TitleBlock>,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
const btn = getByTestId('title-block-mobile-actions-primary-button') as HTMLButtonElement
|
|
155
|
+
expect(btn.textContent).toEqual(primaryActionAsButton.label)
|
|
156
|
+
await user.click(btn)
|
|
157
|
+
|
|
158
|
+
await waitFor(() => {
|
|
159
|
+
expect(testOnClickFn).not.toHaveBeenCalled()
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('creates a mobile actions primary button with disabled styles and no href', () => {
|
|
164
|
+
const { getByTestId } = render(
|
|
165
|
+
<TitleBlock title="Test Title" primaryAction={primaryActionAsLink}>
|
|
166
|
+
Example
|
|
167
|
+
</TitleBlock>,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
const btn = getByTestId('title-block-mobile-actions-primary-button') as HTMLButtonElement
|
|
118
171
|
expect(btn.textContent).toEqual(primaryActionAsLink.label)
|
|
119
172
|
expect(btn.getAttribute('href')).not.toEqual(primaryActionAsLink.href)
|
|
120
173
|
})
|
|
@@ -134,12 +187,12 @@ describe('<TitleBlock />', () => {
|
|
|
134
187
|
})
|
|
135
188
|
|
|
136
189
|
it('renders the primary action button label, href and onClick', async () => {
|
|
137
|
-
const {
|
|
190
|
+
const { getByTestId } = render(
|
|
138
191
|
<TitleBlock title="Test Title" primaryAction={primaryActionAsLinkAndOnClick}>
|
|
139
192
|
Example
|
|
140
193
|
</TitleBlock>,
|
|
141
194
|
)
|
|
142
|
-
const btn =
|
|
195
|
+
const btn = getByTestId('title-block-primary-action-button')
|
|
143
196
|
expect(btn.textContent).toEqual(primaryActionAsLinkAndOnClick.label)
|
|
144
197
|
expect(btn.getAttribute('href')).toEqual(primaryActionAsLinkAndOnClick.href)
|
|
145
198
|
await user.click(btn)
|
|
@@ -148,6 +201,21 @@ describe('<TitleBlock />', () => {
|
|
|
148
201
|
expect(testOnClickFn).toHaveBeenCalled()
|
|
149
202
|
})
|
|
150
203
|
})
|
|
204
|
+
|
|
205
|
+
it('passes both the href and onClick to the mobile action drawer button', async () => {
|
|
206
|
+
const { getByTestId } = render(
|
|
207
|
+
<TitleBlock title="Test Title" primaryAction={primaryActionAsLinkAndOnClick}>
|
|
208
|
+
Example
|
|
209
|
+
</TitleBlock>,
|
|
210
|
+
)
|
|
211
|
+
const btn = getByTestId('title-block-mobile-actions-primary-button')
|
|
212
|
+
expect(btn.getAttribute('href')).toEqual(primaryActionAsLinkAndOnClick.href)
|
|
213
|
+
await user.click(btn)
|
|
214
|
+
|
|
215
|
+
await waitFor(() => {
|
|
216
|
+
expect(testOnClickFn).toHaveBeenCalled()
|
|
217
|
+
})
|
|
218
|
+
})
|
|
151
219
|
})
|
|
152
220
|
|
|
153
221
|
describe('when the primary action is a menu', () => {
|
|
@@ -166,20 +234,30 @@ describe('<TitleBlock />', () => {
|
|
|
166
234
|
}
|
|
167
235
|
|
|
168
236
|
it('renders the primary action menu button with label and menu items', async () => {
|
|
169
|
-
const {
|
|
237
|
+
const { getByTestId, getAllByTestId } = render(
|
|
170
238
|
<TitleBlock title="Test Title" primaryAction={primaryActionAsMenu}>
|
|
171
239
|
Example
|
|
172
240
|
</TitleBlock>,
|
|
173
241
|
)
|
|
174
|
-
const btn =
|
|
242
|
+
const btn = getByTestId('title-block-primary-action-button')
|
|
175
243
|
expect(btn).toHaveAccessibleName(primaryActionAsMenu.label)
|
|
176
244
|
await user.click(btn)
|
|
177
245
|
|
|
178
246
|
await waitFor(() => {
|
|
179
|
-
const menuItems =
|
|
247
|
+
const menuItems = getAllByTestId(/^main-action-primary-menu-item-/)
|
|
180
248
|
expect(menuItems.length).toEqual(2)
|
|
181
249
|
})
|
|
182
250
|
})
|
|
251
|
+
|
|
252
|
+
it('passes the primary menu items to the mobile actions drawer', () => {
|
|
253
|
+
const { getAllByTestId } = render(
|
|
254
|
+
<TitleBlock title="Test Title" primaryAction={primaryActionAsMenu}>
|
|
255
|
+
Example
|
|
256
|
+
</TitleBlock>,
|
|
257
|
+
)
|
|
258
|
+
const menuItems = getAllByTestId(/^title-block-mobile-actions-primary-link-/)
|
|
259
|
+
expect(menuItems.length).toEqual(2)
|
|
260
|
+
})
|
|
183
261
|
})
|
|
184
262
|
|
|
185
263
|
describe('when the default action is a button with only an href', () => {
|
|
@@ -189,22 +267,45 @@ describe('<TitleBlock />', () => {
|
|
|
189
267
|
}
|
|
190
268
|
|
|
191
269
|
it('renders the default action button label and href', () => {
|
|
192
|
-
const {
|
|
270
|
+
const { getByTestId } = render(
|
|
193
271
|
<TitleBlock title="Test Title" defaultAction={defaultActionAsLink}>
|
|
194
272
|
Example
|
|
195
273
|
</TitleBlock>,
|
|
196
274
|
)
|
|
197
|
-
const btn =
|
|
275
|
+
const btn = getByTestId('title-block-default-action-button')
|
|
198
276
|
expect(btn.textContent).toEqual(defaultActionAsLink.label)
|
|
199
277
|
expect(btn.getAttribute('href')).toEqual(defaultActionAsLink.href)
|
|
200
278
|
})
|
|
279
|
+
|
|
280
|
+
it('creates a mobile actions default action menu item', () => {
|
|
281
|
+
const { getByTestId } = render(
|
|
282
|
+
<TitleBlock title="Test Title" defaultAction={defaultActionAsLink}>
|
|
283
|
+
Example
|
|
284
|
+
</TitleBlock>,
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
const menuItem = getByTestId('title-block-mobile-actions-default-link')
|
|
288
|
+
expect(menuItem.getAttribute('href')).toEqual(defaultActionAsLink.href)
|
|
289
|
+
expect(menuItem.textContent).toEqual(defaultActionAsLink.label)
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
it('renders the mobile actions menu drawer handle even with no primary action', () => {
|
|
293
|
+
const { getByTestId } = render(
|
|
294
|
+
<TitleBlock title="Test Title" defaultAction={defaultActionAsLink}>
|
|
295
|
+
Example
|
|
296
|
+
</TitleBlock>,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
expect(getByTestId('title-block-mobile-actions-drawer-handle')).toBeTruthy()
|
|
300
|
+
})
|
|
201
301
|
})
|
|
202
302
|
|
|
203
303
|
describe('when the default action is a button with only an onClick', () => {
|
|
204
304
|
const testOnClickFn = vi.fn()
|
|
205
305
|
const defaultActionAsButton = {
|
|
206
|
-
label: 'defaultActionLabel',
|
|
207
|
-
onClick: testOnClickFn,
|
|
306
|
+
'label': 'defaultActionLabel',
|
|
307
|
+
'onClick': testOnClickFn,
|
|
308
|
+
'data-testid': 'title-block-mobile-actions-default-action',
|
|
208
309
|
}
|
|
209
310
|
|
|
210
311
|
beforeEach(() => {
|
|
@@ -212,12 +313,12 @@ describe('<TitleBlock />', () => {
|
|
|
212
313
|
})
|
|
213
314
|
|
|
214
315
|
it('renders the default action button label and onClick', async () => {
|
|
215
|
-
const {
|
|
316
|
+
const { getByTestId } = render(
|
|
216
317
|
<TitleBlock title="Test Title" defaultAction={defaultActionAsButton}>
|
|
217
318
|
Example
|
|
218
319
|
</TitleBlock>,
|
|
219
320
|
)
|
|
220
|
-
const btn =
|
|
321
|
+
const btn = getByTestId('title-block-default-action-button')
|
|
221
322
|
expect(btn.textContent).toEqual(defaultActionAsButton.label)
|
|
222
323
|
await user.click(btn)
|
|
223
324
|
|
|
@@ -225,6 +326,32 @@ describe('<TitleBlock />', () => {
|
|
|
225
326
|
expect(testOnClickFn).toHaveBeenCalled()
|
|
226
327
|
})
|
|
227
328
|
})
|
|
329
|
+
|
|
330
|
+
it('creates a mobile actions default action menu item', async () => {
|
|
331
|
+
const { getByTestId } = render(
|
|
332
|
+
<TitleBlock title="Test Title" defaultAction={defaultActionAsButton}>
|
|
333
|
+
Example
|
|
334
|
+
</TitleBlock>,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
const menuItem = getByTestId('title-block-mobile-actions-default-action')
|
|
338
|
+
expect(menuItem.textContent).toEqual(defaultActionAsButton.label)
|
|
339
|
+
await user.click(menuItem)
|
|
340
|
+
|
|
341
|
+
await waitFor(() => {
|
|
342
|
+
expect(testOnClickFn).toHaveBeenCalled()
|
|
343
|
+
})
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
it('renders the mobile actions menu drawer handle even with no primary action', () => {
|
|
347
|
+
const { getByTestId } = render(
|
|
348
|
+
<TitleBlock title="Test Title" defaultAction={defaultActionAsButton}>
|
|
349
|
+
Example
|
|
350
|
+
</TitleBlock>,
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
expect(getByTestId('title-block-mobile-actions-drawer-handle')).toBeTruthy()
|
|
354
|
+
})
|
|
228
355
|
})
|
|
229
356
|
|
|
230
357
|
describe('when the default action is a button with both an href and an onClick', () => {
|
|
@@ -240,12 +367,12 @@ describe('<TitleBlock />', () => {
|
|
|
240
367
|
})
|
|
241
368
|
|
|
242
369
|
it('renders the default action button label, href and onClick', async () => {
|
|
243
|
-
const {
|
|
370
|
+
const { getByTestId } = render(
|
|
244
371
|
<TitleBlock title="Test Title" defaultAction={defaultActionAsLinkAndOnClick}>
|
|
245
372
|
Example
|
|
246
373
|
</TitleBlock>,
|
|
247
374
|
)
|
|
248
|
-
const btn =
|
|
375
|
+
const btn = getByTestId('title-block-default-action-button')
|
|
249
376
|
expect(btn.textContent).toEqual(defaultActionAsLinkAndOnClick.label)
|
|
250
377
|
expect(btn.getAttribute('href')).toEqual(defaultActionAsLinkAndOnClick.href)
|
|
251
378
|
await user.click(btn)
|
|
@@ -254,6 +381,25 @@ describe('<TitleBlock />', () => {
|
|
|
254
381
|
expect(testOnClickFn).toHaveBeenCalled()
|
|
255
382
|
})
|
|
256
383
|
})
|
|
384
|
+
|
|
385
|
+
it('creates a single mobile actions default link menu item with both href and onClick', async () => {
|
|
386
|
+
const { getByTestId, queryByTestId } = render(
|
|
387
|
+
<TitleBlock title="Test Title" defaultAction={defaultActionAsLinkAndOnClick}>
|
|
388
|
+
Example
|
|
389
|
+
</TitleBlock>,
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
const menuItem = getByTestId('title-block-mobile-actions-default-link')
|
|
393
|
+
const defaultAction = queryByTestId('title-block-mobile-actions-default-action')
|
|
394
|
+
expect(defaultAction).toBeFalsy()
|
|
395
|
+
expect(menuItem.getAttribute('href')).toEqual(defaultActionAsLinkAndOnClick.href)
|
|
396
|
+
expect(menuItem.textContent).toEqual(defaultActionAsLinkAndOnClick.label)
|
|
397
|
+
await user.click(menuItem)
|
|
398
|
+
|
|
399
|
+
await waitFor(() => {
|
|
400
|
+
expect(testOnClickFn).not.toHaveBeenCalled()
|
|
401
|
+
})
|
|
402
|
+
})
|
|
257
403
|
})
|
|
258
404
|
|
|
259
405
|
describe('when the default action is disabled', () => {
|
|
@@ -274,12 +420,12 @@ describe('<TitleBlock />', () => {
|
|
|
274
420
|
})
|
|
275
421
|
|
|
276
422
|
it('renders a disabled default action button', async () => {
|
|
277
|
-
const {
|
|
423
|
+
const { getByTestId } = render(
|
|
278
424
|
<TitleBlock title="Test Title" defaultAction={defaultActionAsButton}>
|
|
279
425
|
Example
|
|
280
426
|
</TitleBlock>,
|
|
281
427
|
)
|
|
282
|
-
const btn =
|
|
428
|
+
const btn = getByTestId('title-block-default-action-button') as HTMLButtonElement
|
|
283
429
|
expect(btn.textContent).toEqual(defaultActionAsButton.label)
|
|
284
430
|
expect(btn.disabled).toBeTruthy()
|
|
285
431
|
await user.click(btn)
|
|
@@ -290,12 +436,40 @@ describe('<TitleBlock />', () => {
|
|
|
290
436
|
})
|
|
291
437
|
|
|
292
438
|
it('renders a disabled default action link button', () => {
|
|
293
|
-
const {
|
|
439
|
+
const { getByTestId } = render(
|
|
294
440
|
<TitleBlock title="Test Title" defaultAction={defaultActionAsLink}>
|
|
295
441
|
Example
|
|
296
442
|
</TitleBlock>,
|
|
297
443
|
)
|
|
298
|
-
const btn =
|
|
444
|
+
const btn = getByTestId('title-block-default-action-button') as HTMLButtonElement
|
|
445
|
+
expect(btn.textContent).toEqual(defaultActionAsLink.label)
|
|
446
|
+
expect(btn.getAttribute('href')).not.toEqual(defaultActionAsLink.href)
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
it('creates a mobile actions default action menu item with disabled styles and no onClick', async () => {
|
|
450
|
+
const { getByTestId } = render(
|
|
451
|
+
<TitleBlock title="Test Title" defaultAction={defaultActionAsButton}>
|
|
452
|
+
Example
|
|
453
|
+
</TitleBlock>,
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
const btn = getByTestId('title-block-mobile-actions-default-action') as HTMLButtonElement
|
|
457
|
+
expect(btn.textContent).toEqual(defaultActionAsButton.label)
|
|
458
|
+
await user.click(btn)
|
|
459
|
+
|
|
460
|
+
await waitFor(() => {
|
|
461
|
+
expect(testOnClickFn).not.toHaveBeenCalled()
|
|
462
|
+
})
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
it('creates a mobile actions default link menu item with disabled styles and no href', () => {
|
|
466
|
+
const { getByTestId } = render(
|
|
467
|
+
<TitleBlock title="Test Title" defaultAction={defaultActionAsLink}>
|
|
468
|
+
Example
|
|
469
|
+
</TitleBlock>,
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
const btn = getByTestId('title-block-mobile-actions-default-link') as HTMLButtonElement
|
|
299
473
|
expect(btn.textContent).toEqual(defaultActionAsLink.label)
|
|
300
474
|
expect(btn.getAttribute('href')).not.toEqual(defaultActionAsLink.href)
|
|
301
475
|
})
|
|
@@ -316,14 +490,12 @@ describe('<TitleBlock />', () => {
|
|
|
316
490
|
it('renders the secondary action with both the href and onClick', async () => {
|
|
317
491
|
const mockWarnFn = vi.fn()
|
|
318
492
|
const spy = vi.spyOn(global.console, 'warn').mockImplementation(mockWarnFn)
|
|
319
|
-
const {
|
|
493
|
+
const { getByTestId } = render(
|
|
320
494
|
<TitleBlock title="Test Title" secondaryActions={[secondaryActionWithLinkAndOnClick]}>
|
|
321
495
|
Example
|
|
322
496
|
</TitleBlock>,
|
|
323
497
|
)
|
|
324
|
-
const btn =
|
|
325
|
-
name: secondaryActionWithLinkAndOnClick.label,
|
|
326
|
-
})
|
|
498
|
+
const btn = getByTestId('title-block-secondary-actions-button')
|
|
327
499
|
expect(btn).toBeTruthy()
|
|
328
500
|
expect(mockWarnFn).toBeCalled()
|
|
329
501
|
expect(btn.textContent).toEqual(secondaryActionWithLinkAndOnClick.label)
|
|
@@ -334,9 +506,28 @@ describe('<TitleBlock />', () => {
|
|
|
334
506
|
})
|
|
335
507
|
spy.mockRestore()
|
|
336
508
|
})
|
|
509
|
+
|
|
510
|
+
it('renders the action as a single mobile actions drawer item with an onClick', async () => {
|
|
511
|
+
const mockWarnFn = vi.fn()
|
|
512
|
+
const spy = vi.spyOn(global.console, 'warn').mockImplementation(mockWarnFn)
|
|
513
|
+
const { getAllByTestId } = render(
|
|
514
|
+
<TitleBlock title="Test Title" secondaryActions={[secondaryActionWithLinkAndOnClick]}>
|
|
515
|
+
Example
|
|
516
|
+
</TitleBlock>,
|
|
517
|
+
)
|
|
518
|
+
const btn = getAllByTestId('title-block-mobile-actions-secondary-action')
|
|
519
|
+
expect(btn.length).toEqual(1)
|
|
520
|
+
expect(btn[0].getAttribute('href')).not.toEqual(secondaryActionWithLinkAndOnClick.href)
|
|
521
|
+
await user.click(btn[0])
|
|
522
|
+
|
|
523
|
+
await waitFor(() => {
|
|
524
|
+
expect(testOnClickFn).toHaveBeenCalled()
|
|
525
|
+
})
|
|
526
|
+
spy.mockRestore()
|
|
527
|
+
})
|
|
337
528
|
})
|
|
338
529
|
|
|
339
|
-
describe('when a custom
|
|
530
|
+
describe('when a custom compent is provided for section title', () => {
|
|
340
531
|
it('renders a custom element in section title', async () => {
|
|
341
532
|
const expectedText = 'This is a button'
|
|
342
533
|
const CustomComponent = (props: SectionTitleRenderProps): JSX.Element => (
|
|
@@ -361,6 +552,132 @@ describe('<TitleBlock />', () => {
|
|
|
361
552
|
})
|
|
362
553
|
})
|
|
363
554
|
|
|
555
|
+
describe('when a secondary action is passed with only an href', () => {
|
|
556
|
+
const secondaryActionWithLink = {
|
|
557
|
+
label: 'secondaryActionLabel',
|
|
558
|
+
href: '#secondaryActionHref',
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
it('renders the action as a single mobile actions drawer item with the correct href', () => {
|
|
562
|
+
const { getAllByTestId } = render(
|
|
563
|
+
<TitleBlock title="Test Title" secondaryActions={[secondaryActionWithLink]}>
|
|
564
|
+
Example
|
|
565
|
+
</TitleBlock>,
|
|
566
|
+
)
|
|
567
|
+
const btn = getAllByTestId('title-block-mobile-actions-secondary-action')
|
|
568
|
+
expect(btn.length).toEqual(1)
|
|
569
|
+
expect(btn[0].getAttribute('href')).toEqual(secondaryActionWithLink.href)
|
|
570
|
+
})
|
|
571
|
+
})
|
|
572
|
+
|
|
573
|
+
describe('when autoHideMobileActionsMenu is true', () => {
|
|
574
|
+
const secondaryActionWithLink = {
|
|
575
|
+
label: 'secondaryActionLabel',
|
|
576
|
+
href: '#secondaryActionHref',
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
it('hides the other actions menu when user clicks a menu item', async () => {
|
|
580
|
+
const { getAllByTestId } = render(
|
|
581
|
+
<TitleBlock
|
|
582
|
+
title="Test Title"
|
|
583
|
+
secondaryActions={[secondaryActionWithLink]}
|
|
584
|
+
autoHideMobileActionsMenu
|
|
585
|
+
>
|
|
586
|
+
Example
|
|
587
|
+
</TitleBlock>,
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
const mobileActionsButton = screen.getByRole('button', {
|
|
591
|
+
name: 'Other actions',
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
expect(mobileActionsButton.getAttribute('aria-expanded')).toEqual('false')
|
|
595
|
+
await user.click(mobileActionsButton)
|
|
596
|
+
await waitFor(() => {
|
|
597
|
+
expect(mobileActionsButton.getAttribute('aria-expanded')).toEqual('true')
|
|
598
|
+
})
|
|
599
|
+
|
|
600
|
+
const btn = getAllByTestId('title-block-mobile-actions-secondary-action')
|
|
601
|
+
expect(btn.length).toEqual(1)
|
|
602
|
+
await user.click(btn[0])
|
|
603
|
+
|
|
604
|
+
await waitFor(() => {
|
|
605
|
+
expect(mobileActionsButton.getAttribute('aria-expanded')).toEqual('false')
|
|
606
|
+
})
|
|
607
|
+
})
|
|
608
|
+
})
|
|
609
|
+
|
|
610
|
+
describe('when a disabled secondary action is passed with only an href', () => {
|
|
611
|
+
const secondaryActionWithLink = {
|
|
612
|
+
label: 'secondaryActionLabel',
|
|
613
|
+
href: '#secondaryActionHref',
|
|
614
|
+
disabled: true,
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
it('renders the action as a single disabled mobile actions drawer item with no href', () => {
|
|
618
|
+
const { getAllByTestId } = render(
|
|
619
|
+
<TitleBlock title="Test Title" secondaryActions={[secondaryActionWithLink]}>
|
|
620
|
+
Example
|
|
621
|
+
</TitleBlock>,
|
|
622
|
+
)
|
|
623
|
+
const btn = getAllByTestId('title-block-mobile-actions-secondary-action')
|
|
624
|
+
expect(btn.length).toEqual(1)
|
|
625
|
+
expect(btn[0].getAttribute('href')).not.toEqual(secondaryActionWithLink.href)
|
|
626
|
+
})
|
|
627
|
+
})
|
|
628
|
+
|
|
629
|
+
describe('when a disabled secondary action is passed with only an onClick', () => {
|
|
630
|
+
const testOnClickFn = vi.fn()
|
|
631
|
+
const secondaryActionWithOnClick = {
|
|
632
|
+
label: 'secondaryActionLabel',
|
|
633
|
+
onClick: testOnClickFn,
|
|
634
|
+
disabled: true,
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
it('renders the action as a single disabled mobile actions drawer item with no onClick', async () => {
|
|
638
|
+
const { getAllByTestId } = render(
|
|
639
|
+
<TitleBlock title="Test Title" secondaryActions={[secondaryActionWithOnClick]}>
|
|
640
|
+
Example
|
|
641
|
+
</TitleBlock>,
|
|
642
|
+
)
|
|
643
|
+
const btn = getAllByTestId('title-block-mobile-actions-secondary-action')
|
|
644
|
+
expect(btn.length).toEqual(1)
|
|
645
|
+
await user.click(btn[0])
|
|
646
|
+
|
|
647
|
+
await waitFor(() => {
|
|
648
|
+
expect(testOnClickFn).not.toHaveBeenCalled()
|
|
649
|
+
})
|
|
650
|
+
})
|
|
651
|
+
})
|
|
652
|
+
|
|
653
|
+
describe('when a disabled secondary overflow menu item is passed with only an onClick for the action', () => {
|
|
654
|
+
const testOnClickFn = vi.fn()
|
|
655
|
+
const secondaryOverflowMenuItemWithOnClick = {
|
|
656
|
+
label: 'secondaryActionOverflowMenuItemLabel',
|
|
657
|
+
action: testOnClickFn,
|
|
658
|
+
disabled: true,
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
it('renders the action as a single disabled mobile actions drawer item with no onClick', async () => {
|
|
662
|
+
const { getAllByTestId } = render(
|
|
663
|
+
<TitleBlock
|
|
664
|
+
title="Test Title"
|
|
665
|
+
secondaryActions={[]}
|
|
666
|
+
secondaryOverflowMenuItems={[secondaryOverflowMenuItemWithOnClick]}
|
|
667
|
+
>
|
|
668
|
+
Example
|
|
669
|
+
</TitleBlock>,
|
|
670
|
+
)
|
|
671
|
+
const btn = getAllByTestId('title-block-mobile-actions-overflow-menu-item')
|
|
672
|
+
expect(btn.length).toEqual(1)
|
|
673
|
+
await user.click(btn[0])
|
|
674
|
+
|
|
675
|
+
await waitFor(() => {
|
|
676
|
+
expect(testOnClickFn).not.toHaveBeenCalled()
|
|
677
|
+
})
|
|
678
|
+
})
|
|
679
|
+
})
|
|
680
|
+
|
|
364
681
|
describe('automation ID behaviour', () => {
|
|
365
682
|
describe('when default automation IDs are not provided alongside required conditional renders', () => {
|
|
366
683
|
it('renders the default automation IDs', () => {
|
|
@@ -553,6 +870,55 @@ describe('<TitleBlock />', () => {
|
|
|
553
870
|
).toHaveAttribute('href', '#test-primary')
|
|
554
871
|
})
|
|
555
872
|
|
|
873
|
+
it('will render a custom anchor component in the mobile drawer', () => {
|
|
874
|
+
render(
|
|
875
|
+
<TitleBlock
|
|
876
|
+
title="Test Title"
|
|
877
|
+
primaryAction={{
|
|
878
|
+
label: 'Primary action',
|
|
879
|
+
href: '#test-primary',
|
|
880
|
+
component: MockLinkComponent,
|
|
881
|
+
}}
|
|
882
|
+
>
|
|
883
|
+
Example
|
|
884
|
+
</TitleBlock>,
|
|
885
|
+
)
|
|
886
|
+
const drawer = screen.getByTestId('title-block-mobile-actions-drawer-handle')
|
|
887
|
+
within(drawer).getByRole('link', {
|
|
888
|
+
name: 'Primary action',
|
|
889
|
+
})
|
|
890
|
+
expect(
|
|
891
|
+
within(drawer).getByRole('link', {
|
|
892
|
+
name: 'Primary action',
|
|
893
|
+
}),
|
|
894
|
+
).toHaveAttribute('href', '#test-primary')
|
|
895
|
+
})
|
|
896
|
+
|
|
897
|
+
it('will render custom button with functional onClick', async () => {
|
|
898
|
+
const testClickFunc = vi.fn()
|
|
899
|
+
render(
|
|
900
|
+
<TitleBlock
|
|
901
|
+
title="Test Title"
|
|
902
|
+
primaryAction={{
|
|
903
|
+
label: 'Primary action',
|
|
904
|
+
onClick: testClickFunc,
|
|
905
|
+
component: MockButtonComponent,
|
|
906
|
+
}}
|
|
907
|
+
>
|
|
908
|
+
Example
|
|
909
|
+
</TitleBlock>,
|
|
910
|
+
)
|
|
911
|
+
const drawer = screen.getByTestId('title-block-mobile-actions-drawer-handle')
|
|
912
|
+
const drawerBtn = within(drawer).getByRole('button', {
|
|
913
|
+
name: 'Primary action',
|
|
914
|
+
})
|
|
915
|
+
await user.click(drawerBtn)
|
|
916
|
+
|
|
917
|
+
await waitFor(() => {
|
|
918
|
+
expect(testClickFunc).toBeCalledTimes(1)
|
|
919
|
+
})
|
|
920
|
+
})
|
|
921
|
+
|
|
556
922
|
it('will render custom button with children and not label', () => {
|
|
557
923
|
const testClickFunc = vi.fn()
|
|
558
924
|
render(
|
|
@@ -569,12 +935,12 @@ describe('<TitleBlock />', () => {
|
|
|
569
935
|
Example
|
|
570
936
|
</TitleBlock>,
|
|
571
937
|
)
|
|
572
|
-
const
|
|
573
|
-
within(
|
|
938
|
+
const drawer = screen.getByTestId('title-block-mobile-actions-drawer-handle')
|
|
939
|
+
within(drawer).getByRole('button', {
|
|
574
940
|
name: 'This will replace label',
|
|
575
941
|
})
|
|
576
942
|
expect(
|
|
577
|
-
within(
|
|
943
|
+
within(drawer).queryByRole('button', {
|
|
578
944
|
name: 'Primary action',
|
|
579
945
|
}),
|
|
580
946
|
).toBeFalsy()
|
|
@@ -608,6 +974,32 @@ describe('<TitleBlock />', () => {
|
|
|
608
974
|
expect(links[0]).toHaveAttribute('href', '#test-secondary')
|
|
609
975
|
expect(links[1]).toHaveAttribute('href', '#test-secondary-2')
|
|
610
976
|
})
|
|
977
|
+
|
|
978
|
+
it('will render multiple custom anchor components in the secondary actions mobile Drawer', () => {
|
|
979
|
+
render(
|
|
980
|
+
<TitleBlock
|
|
981
|
+
title="Test Title"
|
|
982
|
+
secondaryActions={[
|
|
983
|
+
{
|
|
984
|
+
label: 'Secondary action 1',
|
|
985
|
+
href: '#test-secondary',
|
|
986
|
+
component: MockLinkComponent,
|
|
987
|
+
},
|
|
988
|
+
{
|
|
989
|
+
label: 'Secondary action 2',
|
|
990
|
+
href: '#test-secondary-2',
|
|
991
|
+
component: MockLinkComponent,
|
|
992
|
+
},
|
|
993
|
+
]}
|
|
994
|
+
>
|
|
995
|
+
Example
|
|
996
|
+
</TitleBlock>,
|
|
997
|
+
)
|
|
998
|
+
const links = screen.getAllByTestId('title-block-mobile-actions-secondary-action')
|
|
999
|
+
expect(links.length).toBe(2)
|
|
1000
|
+
expect(links[0]).toHaveAttribute('href', '#test-secondary')
|
|
1001
|
+
expect(links[1]).toHaveAttribute('href', '#test-secondary-2')
|
|
1002
|
+
})
|
|
611
1003
|
})
|
|
612
1004
|
|
|
613
1005
|
describe('defaultAction', () => {
|
|
@@ -630,6 +1022,42 @@ describe('<TitleBlock />', () => {
|
|
|
630
1022
|
})
|
|
631
1023
|
expect(defaultActionAnchor).toHaveAttribute('href', '#test-default')
|
|
632
1024
|
})
|
|
1025
|
+
|
|
1026
|
+
it('will render the component above primary action in the Drawer content if it is a link', () => {
|
|
1027
|
+
render(
|
|
1028
|
+
<TitleBlock
|
|
1029
|
+
title="Test Title"
|
|
1030
|
+
defaultAction={{
|
|
1031
|
+
label: 'Default action',
|
|
1032
|
+
href: '#test-default',
|
|
1033
|
+
component: MockLinkComponent,
|
|
1034
|
+
}}
|
|
1035
|
+
>
|
|
1036
|
+
Example
|
|
1037
|
+
</TitleBlock>,
|
|
1038
|
+
)
|
|
1039
|
+
const mobileActionLink = screen.getByTestId('title-block-mobile-actions-default-link')
|
|
1040
|
+
|
|
1041
|
+
expect(mobileActionLink).toBeInTheDocument()
|
|
1042
|
+
})
|
|
1043
|
+
|
|
1044
|
+
it('will render the component in the top list of the Drawer content if it is a clickable button', () => {
|
|
1045
|
+
const testClickFunc = vi.fn()
|
|
1046
|
+
render(
|
|
1047
|
+
<TitleBlock
|
|
1048
|
+
title="Test Title"
|
|
1049
|
+
defaultAction={{
|
|
1050
|
+
label: 'Default action',
|
|
1051
|
+
onClick: testClickFunc,
|
|
1052
|
+
component: MockButtonComponent,
|
|
1053
|
+
}}
|
|
1054
|
+
>
|
|
1055
|
+
Example
|
|
1056
|
+
</TitleBlock>,
|
|
1057
|
+
)
|
|
1058
|
+
expect(screen.queryByTestId('title-block-mobile-actions-default-link')).toBeFalsy()
|
|
1059
|
+
expect(screen.getByTestId('title-block-mobile-actions-default-action')).toBeInTheDocument()
|
|
1060
|
+
})
|
|
633
1061
|
})
|
|
634
1062
|
})
|
|
635
1063
|
})
|