@fiscozen/card 0.1.6 → 1.0.0-beta.1
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/dist/card.js +116 -71
- package/dist/card.umd.cjs +1 -1
- package/dist/src/FzCard.vue.d.ts +20 -4
- package/dist/src/types.d.ts +46 -6
- package/package.json +5 -5
- package/src/FzCard.vue +164 -79
- package/src/__test__/FzCard.test.ts +518 -135
- package/src/__test__/__snapshots__/FzCard.test.ts.snap +9 -6
- package/src/types.ts +38 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -3,191 +3,574 @@ import { describe, it, expect, vi } from "vitest";
|
|
|
3
3
|
import FzCard from "../FzCard.vue";
|
|
4
4
|
|
|
5
5
|
describe("FzCard", () => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
describe("Rendering", () => {
|
|
7
|
+
it("renders correctly and matches snapshot", async () => {
|
|
8
|
+
const wrapper = mount(FzCard, {
|
|
9
|
+
props: {
|
|
10
|
+
title: "Test Card",
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
await wrapper.vm.$nextTick();
|
|
14
|
+
expect(wrapper.html()).toContain("Test Card");
|
|
15
|
+
expect(wrapper.html()).toMatchSnapshot();
|
|
16
|
+
});
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
18
|
+
it("renders title when provided", async () => {
|
|
19
|
+
const wrapper = mount(FzCard, {
|
|
20
|
+
props: {
|
|
21
|
+
title: "Test Card Title",
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
await wrapper.vm.$nextTick();
|
|
25
|
+
expect(wrapper.find("h2").text()).toBe("Test Card Title");
|
|
23
26
|
});
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
it("renders default slot content", async () => {
|
|
29
|
+
const wrapper = mount(FzCard, {
|
|
30
|
+
props: {
|
|
31
|
+
title: "Test Card",
|
|
32
|
+
},
|
|
33
|
+
slots: {
|
|
34
|
+
default: "<p>Test content</p>",
|
|
35
|
+
} as any,
|
|
36
|
+
});
|
|
37
|
+
await wrapper.vm.$nextTick();
|
|
38
|
+
expect(wrapper.html()).toContain("Test content");
|
|
39
|
+
});
|
|
29
40
|
});
|
|
30
41
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
primaryAction: {
|
|
37
|
-
label: "Action 1",
|
|
42
|
+
describe("Props: color", () => {
|
|
43
|
+
it("applies default background color when no color prop", async () => {
|
|
44
|
+
const wrapper = mount(FzCard, {
|
|
45
|
+
props: {
|
|
46
|
+
title: "Test Card",
|
|
38
47
|
},
|
|
39
|
-
}
|
|
48
|
+
});
|
|
49
|
+
await wrapper.vm.$nextTick();
|
|
50
|
+
expect(wrapper.find("section").classes()).toContain("bg-core-white");
|
|
40
51
|
});
|
|
41
52
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
it("applies default background color when color='default'", async () => {
|
|
54
|
+
const wrapper = mount(FzCard, {
|
|
55
|
+
props: {
|
|
56
|
+
title: "Test Card",
|
|
57
|
+
color: "default",
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
await wrapper.vm.$nextTick();
|
|
61
|
+
expect(wrapper.find("section").classes()).toContain("bg-core-white");
|
|
62
|
+
});
|
|
47
63
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
label: "Action 1",
|
|
64
|
+
it("applies blue background color (alice-blue)", async () => {
|
|
65
|
+
const wrapper = mount(FzCard, {
|
|
66
|
+
props: {
|
|
67
|
+
title: "Test Card",
|
|
68
|
+
color: "blue",
|
|
54
69
|
},
|
|
55
|
-
}
|
|
70
|
+
});
|
|
71
|
+
await wrapper.vm.$nextTick();
|
|
72
|
+
expect(wrapper.find("section").classes()).toContain(
|
|
73
|
+
"bg-background-alice-blue",
|
|
74
|
+
);
|
|
56
75
|
});
|
|
57
76
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
77
|
+
it("applies orange background color (seashell)", async () => {
|
|
78
|
+
const wrapper = mount(FzCard, {
|
|
79
|
+
props: {
|
|
80
|
+
title: "Test Card",
|
|
81
|
+
color: "orange",
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
await wrapper.vm.$nextTick();
|
|
85
|
+
expect(wrapper.find("section").classes()).toContain(
|
|
86
|
+
"bg-background-seashell",
|
|
87
|
+
);
|
|
88
|
+
});
|
|
62
89
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
it("applies purple background color (pale-purple)", async () => {
|
|
91
|
+
const wrapper = mount(FzCard, {
|
|
92
|
+
props: {
|
|
93
|
+
title: "Test Card",
|
|
94
|
+
color: "purple",
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
await wrapper.vm.$nextTick();
|
|
98
|
+
expect(wrapper.find("section").classes()).toContain(
|
|
99
|
+
"bg-background-pale-purple",
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("applies grey background color (white-smoke)", async () => {
|
|
104
|
+
const wrapper = mount(FzCard, {
|
|
105
|
+
props: {
|
|
106
|
+
title: "Test Card",
|
|
107
|
+
color: "grey",
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
await wrapper.vm.$nextTick();
|
|
111
|
+
expect(wrapper.find("section").classes()).toContain(
|
|
112
|
+
"bg-background-white-smoke",
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("applies correct border color for blue", async () => {
|
|
117
|
+
const wrapper = mount(FzCard, {
|
|
118
|
+
props: {
|
|
119
|
+
title: "Test Card",
|
|
120
|
+
color: "blue",
|
|
121
|
+
primaryAction: {
|
|
122
|
+
label: "Action 1",
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
await wrapper.vm.$nextTick();
|
|
127
|
+
expect(wrapper.find("section").classes()).toContain(
|
|
128
|
+
"border-background-alice-blue",
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("applies correct border color for orange", async () => {
|
|
133
|
+
const wrapper = mount(FzCard, {
|
|
134
|
+
props: {
|
|
135
|
+
title: "Test Card",
|
|
136
|
+
color: "orange",
|
|
137
|
+
primaryAction: {
|
|
138
|
+
label: "Action 1",
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
await wrapper.vm.$nextTick();
|
|
143
|
+
expect(wrapper.find("section").classes()).toContain("border-orange-200");
|
|
144
|
+
});
|
|
79
145
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
146
|
+
it("applies correct border color for purple", async () => {
|
|
147
|
+
const wrapper = mount(FzCard, {
|
|
148
|
+
props: {
|
|
149
|
+
title: "Test Card",
|
|
150
|
+
color: "purple",
|
|
151
|
+
primaryAction: {
|
|
152
|
+
label: "Action 1",
|
|
153
|
+
},
|
|
88
154
|
},
|
|
89
|
-
}
|
|
155
|
+
});
|
|
156
|
+
await wrapper.vm.$nextTick();
|
|
157
|
+
expect(wrapper.find("section").classes()).toContain("border-purple-200");
|
|
90
158
|
});
|
|
91
159
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
160
|
+
it("applies correct border color for grey", async () => {
|
|
161
|
+
const wrapper = mount(FzCard, {
|
|
162
|
+
props: {
|
|
163
|
+
title: "Test Card",
|
|
164
|
+
color: "grey",
|
|
165
|
+
primaryAction: {
|
|
166
|
+
label: "Action 1",
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
await wrapper.vm.$nextTick();
|
|
171
|
+
expect(wrapper.find("section").classes()).toContain("border-grey-200");
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("applies default border color when no color prop", async () => {
|
|
175
|
+
const wrapper = mount(FzCard, {
|
|
176
|
+
props: {
|
|
177
|
+
title: "Test Card",
|
|
178
|
+
primaryAction: {
|
|
179
|
+
label: "Action 1",
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
await wrapper.vm.$nextTick();
|
|
184
|
+
expect(wrapper.find("section").classes()).toContain("border-grey-100");
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("maps deprecated aliceblue to blue and shows warning", async () => {
|
|
188
|
+
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
189
|
+
|
|
190
|
+
const wrapper = mount(FzCard, {
|
|
191
|
+
props: {
|
|
192
|
+
title: "Test Card",
|
|
193
|
+
color: "aliceblue",
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
await wrapper.vm.$nextTick();
|
|
198
|
+
|
|
199
|
+
// Verify aliceblue is mapped to blue (alice-blue background)
|
|
200
|
+
expect(wrapper.find("section").classes()).toContain(
|
|
201
|
+
"bg-background-alice-blue",
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
// Verify warning was shown
|
|
205
|
+
expect(consoleSpy).toHaveBeenCalledTimes(1);
|
|
206
|
+
const warningMessage = consoleSpy.mock.calls[0][0] as string;
|
|
207
|
+
expect(warningMessage).toContain(
|
|
208
|
+
"[FzCard] The color prop value 'aliceblue' is deprecated",
|
|
209
|
+
);
|
|
210
|
+
expect(warningMessage).toContain("Please use 'blue' instead");
|
|
211
|
+
|
|
212
|
+
consoleSpy.mockRestore();
|
|
213
|
+
});
|
|
96
214
|
});
|
|
97
215
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
216
|
+
describe("Props: collapsible", () => {
|
|
217
|
+
it("should expand and collapse when collapsible is true", async () => {
|
|
218
|
+
const wrapper = mount(FzCard, {
|
|
219
|
+
props: {
|
|
220
|
+
title: "Test Card",
|
|
221
|
+
collapsible: true,
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
await wrapper.vm.$nextTick();
|
|
225
|
+
|
|
226
|
+
expect(wrapper.find("article").exists()).toBeFalsy();
|
|
227
|
+
await wrapper.find("header").find("button").trigger("click");
|
|
228
|
+
expect(wrapper.find("article").exists()).toBeTruthy();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it("should show content by default when not collapsible", async () => {
|
|
232
|
+
const wrapper = mount(FzCard, {
|
|
233
|
+
props: {
|
|
234
|
+
title: "Test Card",
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
await wrapper.vm.$nextTick();
|
|
238
|
+
expect(wrapper.find("article").exists()).toBeTruthy();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("should respect defaultExpanded prop", async () => {
|
|
242
|
+
const wrapper = mount(FzCard, {
|
|
243
|
+
props: {
|
|
244
|
+
title: "Test Card",
|
|
245
|
+
collapsible: true,
|
|
246
|
+
defaultExpanded: true,
|
|
104
247
|
},
|
|
105
|
-
}
|
|
248
|
+
});
|
|
249
|
+
await wrapper.vm.$nextTick();
|
|
250
|
+
expect(wrapper.find("article").exists()).toBeTruthy();
|
|
106
251
|
});
|
|
107
252
|
|
|
108
|
-
|
|
109
|
-
|
|
253
|
+
it("should keep content alive when alwaysAlive is true", async () => {
|
|
254
|
+
const wrapper = mount(FzCard, {
|
|
255
|
+
props: {
|
|
256
|
+
title: "Test Card",
|
|
257
|
+
collapsible: true,
|
|
258
|
+
alwaysAlive: true,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
await wrapper.vm.$nextTick();
|
|
262
|
+
// Content should exist even when collapsed
|
|
263
|
+
expect(wrapper.find("article").exists()).toBeTruthy();
|
|
264
|
+
});
|
|
110
265
|
});
|
|
111
266
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
267
|
+
describe("Props: actions", () => {
|
|
268
|
+
it("renders footer with primaryAction", async () => {
|
|
269
|
+
const wrapper = mount(FzCard, {
|
|
270
|
+
props: {
|
|
271
|
+
title: "Test Card",
|
|
272
|
+
primaryAction: {
|
|
273
|
+
label: "Action 1",
|
|
274
|
+
},
|
|
118
275
|
},
|
|
119
|
-
|
|
120
|
-
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
await wrapper.vm.$nextTick();
|
|
279
|
+
expect(wrapper.find("footer").exists()).toBeTruthy();
|
|
280
|
+
expect(wrapper.html()).toContain("Action 1");
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("renders footer with primaryAction and secondaryAction", async () => {
|
|
284
|
+
const wrapper = mount(FzCard, {
|
|
285
|
+
props: {
|
|
286
|
+
title: "Test Card",
|
|
287
|
+
primaryAction: {
|
|
288
|
+
label: "Primary",
|
|
289
|
+
},
|
|
290
|
+
secondaryAction: {
|
|
291
|
+
label: "Secondary",
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
await wrapper.vm.$nextTick();
|
|
297
|
+
expect(wrapper.find("footer").exists()).toBeTruthy();
|
|
298
|
+
expect(wrapper.html()).toContain("Primary");
|
|
299
|
+
expect(wrapper.html()).toContain("Secondary");
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it("renders footer with all three actions", async () => {
|
|
303
|
+
const wrapper = mount(FzCard, {
|
|
304
|
+
props: {
|
|
305
|
+
title: "Test Card",
|
|
306
|
+
primaryAction: {
|
|
307
|
+
label: "Primary",
|
|
308
|
+
},
|
|
309
|
+
secondaryAction: {
|
|
310
|
+
label: "Secondary",
|
|
311
|
+
},
|
|
312
|
+
tertiaryAction: {
|
|
313
|
+
icon: "bell",
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
await wrapper.vm.$nextTick();
|
|
319
|
+
expect(wrapper.find("footer").exists()).toBeTruthy();
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("warns if tertiaryAction is set without primaryAction and secondaryAction", () => {
|
|
323
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
324
|
+
mount(FzCard, {
|
|
325
|
+
props: {
|
|
326
|
+
title: "Test Card",
|
|
327
|
+
tertiaryAction: {
|
|
328
|
+
icon: "bell",
|
|
329
|
+
},
|
|
121
330
|
},
|
|
122
|
-
}
|
|
331
|
+
});
|
|
332
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
333
|
+
"[Fiscozen Design System]: You should set primaryAction and secondaryAction if you want to set tertiaryAction",
|
|
334
|
+
);
|
|
335
|
+
warnSpy.mockRestore();
|
|
123
336
|
});
|
|
124
337
|
|
|
125
|
-
|
|
126
|
-
|
|
338
|
+
it("warns if secondaryAction is set without primaryAction", () => {
|
|
339
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
340
|
+
mount(FzCard, {
|
|
341
|
+
props: {
|
|
342
|
+
title: "Test Card",
|
|
343
|
+
secondaryAction: {
|
|
344
|
+
label: "Action 2",
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
350
|
+
"[Fiscozen Design System]: You should set primaryAction if you want to set secondaryAction",
|
|
351
|
+
);
|
|
352
|
+
warnSpy.mockRestore();
|
|
353
|
+
});
|
|
127
354
|
});
|
|
128
355
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
356
|
+
describe("Events", () => {
|
|
357
|
+
it("should emit fzprimary:click when primaryAction is clicked", async () => {
|
|
358
|
+
const wrapper = mount(FzCard, {
|
|
359
|
+
props: {
|
|
360
|
+
title: "Test Card",
|
|
361
|
+
primaryAction: {
|
|
362
|
+
label: "Action 1",
|
|
363
|
+
},
|
|
135
364
|
},
|
|
136
|
-
|
|
137
|
-
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
await wrapper.findAll("button")[0].trigger("click");
|
|
368
|
+
expect(wrapper.emitted("fzprimary:click")).toBeTruthy();
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it("should emit fzsecondary:click when secondaryAction is clicked", async () => {
|
|
372
|
+
const wrapper = mount(FzCard, {
|
|
373
|
+
props: {
|
|
374
|
+
title: "Test Card",
|
|
375
|
+
primaryAction: {
|
|
376
|
+
label: "Action 1",
|
|
377
|
+
},
|
|
378
|
+
secondaryAction: {
|
|
379
|
+
label: "Action 2",
|
|
380
|
+
},
|
|
138
381
|
},
|
|
139
|
-
|
|
140
|
-
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
await wrapper.findAll("button")[0].trigger("click");
|
|
385
|
+
expect(wrapper.emitted("fzsecondary:click")).toBeTruthy();
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it("should emit fztertiary:click when tertiaryAction is clicked", async () => {
|
|
389
|
+
const wrapper = mount(FzCard, {
|
|
390
|
+
props: {
|
|
391
|
+
title: "Test Card",
|
|
392
|
+
primaryAction: {
|
|
393
|
+
label: "Action 1",
|
|
394
|
+
},
|
|
395
|
+
secondaryAction: {
|
|
396
|
+
label: "Action 2",
|
|
397
|
+
},
|
|
398
|
+
tertiaryAction: {
|
|
399
|
+
icon: "bell",
|
|
400
|
+
},
|
|
141
401
|
},
|
|
142
|
-
}
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
await wrapper.findAll("button")[0].trigger("click");
|
|
405
|
+
expect(wrapper.emitted("fztertiary:click")).toBeTruthy();
|
|
143
406
|
});
|
|
144
407
|
|
|
145
|
-
|
|
146
|
-
|
|
408
|
+
it("should emit fzcard:click-info when info icon is clicked", async () => {
|
|
409
|
+
const wrapper = mount(FzCard, {
|
|
410
|
+
props: {
|
|
411
|
+
title: "Test Card",
|
|
412
|
+
hasInfoIcon: true,
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
await wrapper.vm.$nextTick();
|
|
417
|
+
const buttons = wrapper.findAll("button");
|
|
418
|
+
// Find the info icon button (it should be the first one when only hasInfoIcon is true)
|
|
419
|
+
await buttons[0].trigger("click");
|
|
420
|
+
expect(wrapper.emitted("fzcard:click-info")).toBeTruthy();
|
|
421
|
+
});
|
|
147
422
|
});
|
|
148
423
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
424
|
+
describe("Slots", () => {
|
|
425
|
+
it("should hide the header when no title and no slots are defined", async () => {
|
|
426
|
+
const wrapper = mount(FzCard, {
|
|
427
|
+
props: {},
|
|
428
|
+
});
|
|
429
|
+
await wrapper.vm.$nextTick();
|
|
430
|
+
|
|
431
|
+
expect(wrapper.find("header").exists()).toBeFalsy();
|
|
155
432
|
});
|
|
156
|
-
await wrapper.vm.$nextTick();
|
|
157
433
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
434
|
+
it("should show the header when no title is defined but header slot is", async () => {
|
|
435
|
+
const wrapper = mount(FzCard, {
|
|
436
|
+
slots: {
|
|
437
|
+
header: "<div>Header</div>",
|
|
438
|
+
} as any,
|
|
439
|
+
});
|
|
440
|
+
await wrapper.vm.$nextTick();
|
|
441
|
+
|
|
442
|
+
expect(wrapper.find("header").exists()).toBeTruthy();
|
|
443
|
+
expect(wrapper.html()).toContain("Header");
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it("should show the header when no title is defined but header-content slot is", async () => {
|
|
447
|
+
const wrapper = mount(FzCard, {
|
|
448
|
+
slots: {
|
|
449
|
+
"header-content": "<div>Header Content</div>",
|
|
450
|
+
} as any,
|
|
451
|
+
});
|
|
452
|
+
await wrapper.vm.$nextTick();
|
|
453
|
+
|
|
454
|
+
expect(wrapper.find("header").exists()).toBeTruthy();
|
|
455
|
+
expect(wrapper.html()).toContain("Header Content");
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
it("should render footer slot content when provided", async () => {
|
|
459
|
+
const wrapper = mount(FzCard, {
|
|
460
|
+
props: {
|
|
461
|
+
title: "Test Card",
|
|
462
|
+
},
|
|
463
|
+
slots: {
|
|
464
|
+
footer: "<div>Custom Footer</div>",
|
|
465
|
+
} as any,
|
|
466
|
+
});
|
|
467
|
+
await wrapper.vm.$nextTick();
|
|
468
|
+
|
|
469
|
+
expect(wrapper.find("footer").exists()).toBeTruthy();
|
|
470
|
+
expect(wrapper.html()).toContain("Custom Footer");
|
|
471
|
+
});
|
|
161
472
|
});
|
|
162
473
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
474
|
+
describe("Accessibility", () => {
|
|
475
|
+
it("should have proper title attribute on h2", async () => {
|
|
476
|
+
const wrapper = mount(FzCard, {
|
|
477
|
+
props: {
|
|
478
|
+
title: "Test Card Title",
|
|
479
|
+
},
|
|
480
|
+
});
|
|
481
|
+
await wrapper.vm.$nextTick();
|
|
482
|
+
expect(wrapper.find("h2").attributes("title")).toBe("Test Card Title");
|
|
166
483
|
});
|
|
167
|
-
await wrapper.vm.$nextTick();
|
|
168
484
|
|
|
169
|
-
|
|
485
|
+
it("should have proper role on collapsible header", async () => {
|
|
486
|
+
const wrapper = mount(FzCard, {
|
|
487
|
+
props: {
|
|
488
|
+
title: "Test Card",
|
|
489
|
+
collapsible: true,
|
|
490
|
+
},
|
|
491
|
+
});
|
|
492
|
+
await wrapper.vm.$nextTick();
|
|
493
|
+
expect(wrapper.find("header").classes()).toContain("cursor-pointer");
|
|
494
|
+
});
|
|
170
495
|
});
|
|
171
496
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
497
|
+
describe("Props: hasInfoIcon", () => {
|
|
498
|
+
it("should not show info icon when hasInfoIcon is false", async () => {
|
|
499
|
+
const wrapper = mount(FzCard, {
|
|
500
|
+
props: {
|
|
501
|
+
title: "Test Card",
|
|
502
|
+
hasInfoIcon: false,
|
|
503
|
+
},
|
|
504
|
+
});
|
|
505
|
+
await wrapper.vm.$nextTick();
|
|
506
|
+
// No info icon button should be present
|
|
507
|
+
const buttons = wrapper.findAll("button");
|
|
508
|
+
expect(buttons.length).toBe(0);
|
|
177
509
|
});
|
|
178
|
-
await wrapper.vm.$nextTick();
|
|
179
510
|
|
|
180
|
-
|
|
511
|
+
it("should show info icon when hasInfoIcon is true", async () => {
|
|
512
|
+
const wrapper = mount(FzCard, {
|
|
513
|
+
props: {
|
|
514
|
+
title: "Test Card",
|
|
515
|
+
hasInfoIcon: true,
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
await wrapper.vm.$nextTick();
|
|
519
|
+
// Info icon button should be present
|
|
520
|
+
const buttons = wrapper.findAll("button");
|
|
521
|
+
expect(buttons.length).toBe(1);
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
it("should show info icon alongside collapse icon", async () => {
|
|
525
|
+
const wrapper = mount(FzCard, {
|
|
526
|
+
props: {
|
|
527
|
+
title: "Test Card",
|
|
528
|
+
hasInfoIcon: true,
|
|
529
|
+
collapsible: true,
|
|
530
|
+
},
|
|
531
|
+
});
|
|
532
|
+
await wrapper.vm.$nextTick();
|
|
533
|
+
// Both info and collapse icons should be present
|
|
534
|
+
const buttons = wrapper.findAll("button");
|
|
535
|
+
expect(buttons.length).toBe(2);
|
|
536
|
+
});
|
|
181
537
|
});
|
|
182
538
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
539
|
+
describe("Edge cases", () => {
|
|
540
|
+
it("should handle card without any props", async () => {
|
|
541
|
+
const wrapper = mount(FzCard);
|
|
542
|
+
await wrapper.vm.$nextTick();
|
|
543
|
+
expect(wrapper.find("section").exists()).toBeTruthy();
|
|
544
|
+
expect(wrapper.find("article").exists()).toBeTruthy();
|
|
188
545
|
});
|
|
189
|
-
await wrapper.vm.$nextTick();
|
|
190
546
|
|
|
191
|
-
|
|
547
|
+
it("should handle contentClass prop", async () => {
|
|
548
|
+
const wrapper = mount(FzCard, {
|
|
549
|
+
props: {
|
|
550
|
+
title: "Test Card",
|
|
551
|
+
contentClass: "custom-class",
|
|
552
|
+
},
|
|
553
|
+
});
|
|
554
|
+
await wrapper.vm.$nextTick();
|
|
555
|
+
expect(wrapper.find("article").classes()).toContain("custom-class");
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
it("exposes toggleOpen method", async () => {
|
|
559
|
+
const wrapper = mount(FzCard, {
|
|
560
|
+
props: {
|
|
561
|
+
title: "Test Card",
|
|
562
|
+
collapsible: true,
|
|
563
|
+
},
|
|
564
|
+
});
|
|
565
|
+
await wrapper.vm.$nextTick();
|
|
566
|
+
|
|
567
|
+
expect(wrapper.find("article").exists()).toBeFalsy();
|
|
568
|
+
|
|
569
|
+
// Call exposed method
|
|
570
|
+
(wrapper.vm as any).toggleOpen();
|
|
571
|
+
await wrapper.vm.$nextTick();
|
|
572
|
+
|
|
573
|
+
expect(wrapper.find("article").exists()).toBeTruthy();
|
|
574
|
+
});
|
|
192
575
|
});
|
|
193
576
|
});
|