@fiscozen/checkbox 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/checkbox.js +2376 -0
  2. package/dist/checkbox.umd.cjs +13 -0
  3. package/dist/index.d.ts +1 -0
  4. package/dist/src/FzCheckbox.vue.d.ts +102 -0
  5. package/dist/src/FzCheckboxGroup.vue.d.ts +72 -0
  6. package/dist/src/__tests__/FzCheckbox.spec.d.ts +1 -0
  7. package/dist/src/__tests__/FzCheckboxGroup.spec.d.ts +1 -0
  8. package/dist/src/common.d.ts +23 -0
  9. package/dist/src/components/ErrorAlert.vue.d.ts +34 -0
  10. package/dist/src/components/FzCheckboxGroupOption.vue.d.ts +86 -0
  11. package/dist/src/index.d.ts +4 -0
  12. package/dist/src/types.d.ts +192 -0
  13. package/dist/src/utils.d.ts +24 -0
  14. package/dist/style.css +1 -0
  15. package/package.json +9 -13
  16. package/src/__tests__/FzCheckbox.spec.ts +748 -0
  17. package/src/__tests__/FzCheckboxGroup.spec.ts +764 -0
  18. package/src/__tests__/__snapshots__/FzCheckbox.spec.ts.snap +427 -0
  19. package/src/__tests__/__snapshots__/FzCheckboxGroup.spec.ts.snap +805 -0
  20. package/src/components/ErrorAlert.vue +1 -1
  21. package/tsconfig.tsbuildinfo +1 -0
  22. package/vitest.config.ts +9 -1
  23. package/coverage/base.css +0 -224
  24. package/coverage/block-navigation.js +0 -87
  25. package/coverage/clover.xml +0 -1031
  26. package/coverage/coverage-final.json +0 -7
  27. package/coverage/favicon.png +0 -0
  28. package/coverage/index.html +0 -131
  29. package/coverage/prettify.css +0 -1
  30. package/coverage/prettify.js +0 -2
  31. package/coverage/sort-arrow-sprite.png +0 -0
  32. package/coverage/sorter.js +0 -196
  33. package/coverage/src/FzCheckbox.vue.html +0 -1489
  34. package/coverage/src/FzCheckboxGroup.vue.html +0 -682
  35. package/coverage/src/common.ts.html +0 -157
  36. package/coverage/src/components/ErrorAlert.vue.html +0 -268
  37. package/coverage/src/components/FzCheckboxGroupOption.vue.html +0 -652
  38. package/coverage/src/components/index.html +0 -131
  39. package/coverage/src/index.html +0 -161
  40. package/coverage/src/utils.ts.html +0 -265
  41. package/src/__test__/FzCheckbox.test.ts +0 -206
  42. package/src/__test__/FzCheckboxGroup.test.ts +0 -263
@@ -1,206 +0,0 @@
1
- // FzCheckbox.test.ts
2
- import { mount } from "@vue/test-utils";
3
- import { describe, it, expect } from "vitest";
4
- import FzCheckbox from "../FzCheckbox.vue";
5
-
6
- const MAX_CHECKBOX = 200;
7
-
8
- describe("FzCheckbox", () => {
9
- it("renders correctly", async () => {
10
- const wrapper = mount(FzCheckbox, {
11
- props: {
12
- label: "Test Checkbox",
13
- value: "test",
14
- modelValue: false,
15
- },
16
- });
17
-
18
- await wrapper.vm.$nextTick();
19
- expect(wrapper.html()).toContain("Test Checkbox");
20
- });
21
-
22
- it("is checked when v-model is true", async () => {
23
- const wrapper = mount(FzCheckbox, {
24
- props: {
25
- label: "Test Checkbox",
26
- value: "test",
27
- modelValue: true,
28
- },
29
- });
30
- await wrapper.vm.$nextTick();
31
- expect(wrapper.find("input").element.checked).toBe(true);
32
- });
33
-
34
- it("is unchecked when v-model is false", async () => {
35
- const wrapper = mount(FzCheckbox, {
36
- props: {
37
- label: "Test Checkbox",
38
- value: "test",
39
- modelValue: false,
40
- },
41
- });
42
-
43
- await wrapper.vm.$nextTick();
44
- expect(wrapper.find("input").element.checked).toBe(false);
45
- });
46
-
47
- it("should be emphasized", async () => {
48
- const wrapper = mount(FzCheckbox, {
49
- props: {
50
- label: "Test Checkbox",
51
- value: "test",
52
- modelValue: false,
53
- emphasis: true,
54
- },
55
- });
56
- await wrapper.vm.$nextTick();
57
- expect(wrapper.find("label").classes()).toContain(
58
- "peer-checked:[&_div]:text-blue-500",
59
- );
60
- });
61
-
62
- it("should be disabled", async () => {
63
- const wrapper = mount(FzCheckbox, {
64
- props: {
65
- label: "Test Checkbox",
66
- value: "test",
67
- modelValue: false,
68
- disabled: true,
69
- },
70
- });
71
- await wrapper.vm.$nextTick();
72
- expect(wrapper.find("input").element.disabled).toBe(true);
73
- });
74
-
75
- it(`should render ${MAX_CHECKBOX} checkbox all with different ids`, async () => {
76
- const checkboxes = Array.from({ length: MAX_CHECKBOX }).map((_) => {
77
- return mount(FzCheckbox, {
78
- props: {
79
- label: "Test Checkbox",
80
- value: "test",
81
- modelValue: false,
82
- disabled: true,
83
- },
84
- });
85
- });
86
- await Promise.all(checkboxes.map((c) => c.vm.$nextTick()));
87
- const ids = checkboxes.map((c) => c.find("input").attributes("id"));
88
- const labelFor = checkboxes.map((c) => c.find("label").attributes("for"));
89
- expect(new Set(ids).size).toBe(MAX_CHECKBOX);
90
- expect(new Set(labelFor).size).toBe(MAX_CHECKBOX);
91
- });
92
-
93
- it("should not throw error when modelValue is undefined", async () => {
94
- const wrapper = mount(FzCheckbox, {
95
- props: {
96
- label: "Test Checkbox",
97
- value: "test",
98
- modelValue: undefined,
99
- },
100
- });
101
- await wrapper.vm.$nextTick();
102
- expect(wrapper.find("input").element.checked).toBe(false);
103
- });
104
-
105
- it("should not throw error when modelValue is null", async () => {
106
- const wrapper = mount(FzCheckbox, {
107
- props: {
108
- label: "Test Checkbox",
109
- value: "test",
110
- modelValue: null,
111
- },
112
- });
113
- await wrapper.vm.$nextTick();
114
- expect(wrapper.find("input").element.checked).toBe(false);
115
- });
116
-
117
- it("has correct ARIA attributes (not standalone, no error)", async () => {
118
- const wrapper = mount(FzCheckbox, {
119
- props: {
120
- label: "Test Checkbox",
121
- value: "test",
122
- modelValue: false,
123
- required: true,
124
- },
125
- });
126
- await wrapper.vm.$nextTick();
127
- const input = wrapper.find("input[type='checkbox']");
128
- const id = input.attributes("id");
129
- expect(input.attributes("aria-checked")).toBe("false");
130
- expect(input.attributes("aria-label")).toBeUndefined();
131
- expect(input.attributes("aria-required")).toBe("true");
132
- expect(input.attributes("aria-invalid")).toBe("false");
133
- expect(input.attributes("aria-describedby")).toBeUndefined();
134
- expect(input.attributes("aria-labelledby")).toBe(`${id}-label`);
135
- expect(wrapper.find(`#${id}-label`).exists()).toBe(true);
136
- });
137
-
138
- it("has correct ARIA attributes (standalone)", async () => {
139
- const wrapper = mount(FzCheckbox, {
140
- props: {
141
- label: "Test Checkbox",
142
- value: "test",
143
- modelValue: false,
144
- standalone: true,
145
- },
146
- });
147
- await wrapper.vm.$nextTick();
148
- const input = wrapper.find("input[type='checkbox']");
149
- expect(input.attributes("aria-labelledby")).toBeUndefined();
150
- expect(input.attributes("aria-label")).toBe("Test Checkbox");
151
- });
152
-
153
- it("has correct ARIA attributes when error is present", async () => {
154
- const wrapper = mount(FzCheckbox, {
155
- props: {
156
- label: "Test Checkbox",
157
- value: "test",
158
- modelValue: false,
159
- error: true,
160
- },
161
- slots: {
162
- error: "Test error message",
163
- },
164
- });
165
- await wrapper.vm.$nextTick();
166
- const input = wrapper.find("input[type='checkbox']");
167
- const id = input.attributes("id");
168
- expect(input.attributes("aria-invalid")).toBe("true");
169
- expect(input.attributes("aria-describedby")).toBe(`${id}-error`);
170
- expect(wrapper.find(`#${id}-error`).exists()).toBe(true);
171
- });
172
-
173
- it("has correct ARIA attributes when error is present but no error message slot", async () => {
174
- const wrapper = mount(FzCheckbox, {
175
- props: {
176
- label: "Test Checkbox",
177
- value: "test",
178
- modelValue: false,
179
- error: true,
180
- },
181
- // No error slot provided
182
- });
183
- await wrapper.vm.$nextTick();
184
- const input = wrapper.find("input[type='checkbox']");
185
- // Error state must still be indicated via aria-invalid
186
- expect(input.attributes("aria-invalid")).toBe("true");
187
- // But aria-describedby should not reference an error element when no error slot is present
188
- expect(input.attributes("aria-describedby")).toBeUndefined();
189
- // ErrorAlert should not be rendered when no error slot is provided
190
- expect(wrapper.find("[role='alert']").exists()).toBe(false);
191
- });
192
-
193
- it("has aria-checked='mixed' when indeterminate", async () => {
194
- const wrapper = mount(FzCheckbox, {
195
- props: {
196
- label: "Test Checkbox",
197
- value: "test",
198
- modelValue: false,
199
- indeterminate: true,
200
- },
201
- });
202
- await wrapper.vm.$nextTick();
203
- const input = wrapper.find("input[type='checkbox']");
204
- expect(input.attributes("aria-checked")).toBe("mixed");
205
- });
206
- });
@@ -1,263 +0,0 @@
1
- import { mount } from "@vue/test-utils";
2
- import { describe, it, expect } from "vitest";
3
- import FzCheckboxGroup from "../FzCheckboxGroup.vue";
4
- import FzCheckbox from "../FzCheckbox.vue";
5
-
6
- describe("FzCheckboxGroup", () => {
7
- it("renders correctly", async () => {
8
- const wrapper = mount(FzCheckboxGroup, {
9
- props: {
10
- label: "Test Checkbox Group",
11
- modelValue: [],
12
- options: [
13
- { label: "Option 1", value: "option1" },
14
- { label: "Option 2", value: "option2" },
15
- ],
16
- },
17
- });
18
-
19
- await wrapper.vm.$nextTick();
20
- expect(wrapper.html()).toContain("Test Checkbox Group");
21
- expect(wrapper.findAllComponents(FzCheckbox).length).toBe(2);
22
- });
23
-
24
- it("displays error text when error prop is true", async () => {
25
- const wrapper = mount(FzCheckboxGroup, {
26
- props: {
27
- label: "Test Checkbox Group",
28
- modelValue: [],
29
- options: [
30
- { label: "Option 1", value: "option1" },
31
- { label: "Option 2", value: "option2" },
32
- ],
33
- error: true,
34
- },
35
- slots: {
36
- error: "Test error message",
37
- },
38
- });
39
-
40
- await wrapper.vm.$nextTick();
41
- expect(wrapper.html()).toContain("Test error message");
42
- expect(wrapper.findAllComponents(FzCheckbox).length).toBe(2);
43
- expect(wrapper.props("error")).toBe(true);
44
-
45
- // Verify error prop is propagated to individual checkboxes
46
- expect(wrapper.findAllComponents(FzCheckbox).at(0)!.props("error")).toBe(
47
- true,
48
- );
49
- expect(wrapper.findAllComponents(FzCheckbox).at(1)!.props("error")).toBe(
50
- true,
51
- );
52
- });
53
-
54
- it("has disabled checkboxes when disabled prop is true", async () => {
55
- const wrapper = mount(FzCheckboxGroup, {
56
- props: {
57
- label: "Test Checkbox Group",
58
- modelValue: [],
59
- options: [
60
- { label: "Option 1", value: "option1" },
61
- { label: "Option 2", value: "option2" },
62
- ],
63
- disabled: true,
64
- },
65
- });
66
-
67
- await wrapper.vm.$nextTick();
68
- expect(wrapper.findAllComponents(FzCheckbox).length).toBe(2);
69
- expect(wrapper.findAllComponents(FzCheckbox).at(0)!.props("disabled")).toBe(
70
- true,
71
- );
72
- expect(wrapper.findAllComponents(FzCheckbox).at(1)!.props("disabled")).toBe(
73
- true,
74
- );
75
- });
76
-
77
- it("display emphasized checkboxes when emphasis prop is true", async () => {
78
- const wrapper = mount(FzCheckboxGroup, {
79
- props: {
80
- label: "Test Checkbox Group",
81
- modelValue: [],
82
- options: [
83
- { label: "Option 1", value: "option1" },
84
- { label: "Option 2", value: "option2" },
85
- ],
86
- emphasis: true,
87
- },
88
- });
89
-
90
- await wrapper.vm.$nextTick();
91
- expect(wrapper.findAllComponents(FzCheckbox).length).toBe(2);
92
- expect(wrapper.findAllComponents(FzCheckbox).at(0)!.props("emphasis")).toBe(
93
- true,
94
- );
95
- expect(wrapper.findAllComponents(FzCheckbox).at(1)!.props("emphasis")).toBe(
96
- true,
97
- );
98
- });
99
-
100
- it("has correct ARIA attributes for accessibility", async () => {
101
- const wrapper = mount(FzCheckboxGroup, {
102
- props: {
103
- label: "Test Checkbox Group",
104
- modelValue: [],
105
- options: [
106
- { label: "Option 1", value: "option1" },
107
- { label: "Option 2", value: "option2" },
108
- ],
109
- },
110
- });
111
- await wrapper.vm.$nextTick();
112
- const groupId = wrapper.find("[role='group']").attributes("id");
113
- const labelId = groupId + "-label";
114
- expect(wrapper.find("[role='group']").exists()).toBe(true);
115
- expect(wrapper.find("[role='group']").attributes("aria-labelledby")).toBe(
116
- labelId,
117
- );
118
- expect(wrapper.find(`#${labelId}`).exists()).toBe(true);
119
- expect(
120
- wrapper.find("[role='group']").attributes("aria-describedby"),
121
- ).toBeUndefined();
122
- });
123
-
124
- it("has aria-describedby when error is present", async () => {
125
- const wrapper = mount(FzCheckboxGroup, {
126
- props: {
127
- label: "Test Checkbox Group",
128
- modelValue: [],
129
- options: [
130
- { label: "Option 1", value: "option1" },
131
- { label: "Option 2", value: "option2" },
132
- ],
133
- error: true,
134
- },
135
- slots: {
136
- error: "Test error message",
137
- },
138
- });
139
- await wrapper.vm.$nextTick();
140
- const groupId = wrapper.find("[role='group']").attributes("id");
141
- const errorId = groupId + "-error";
142
- expect(wrapper.find("[role='group']").attributes("aria-describedby")).toBe(
143
- errorId,
144
- );
145
- expect(wrapper.find(`#${errorId}`).exists()).toBe(true);
146
- });
147
-
148
- it("has aria-invalid but no aria-describedby when error is present but no error message slot", async () => {
149
- const wrapper = mount(FzCheckboxGroup, {
150
- props: {
151
- label: "Test Checkbox Group",
152
- modelValue: [],
153
- options: [
154
- { label: "Option 1", value: "option1" },
155
- { label: "Option 2", value: "option2" },
156
- ],
157
- error: true,
158
- },
159
- // No error slot provided
160
- });
161
- await wrapper.vm.$nextTick();
162
- const group = wrapper.find("[role='group']");
163
- // Error state should still be indicated via aria-invalid
164
- expect(group.attributes("aria-invalid")).toBe("true");
165
- // But aria-describedby should not reference an error element when no error slot is present
166
- expect(group.attributes("aria-describedby")).toBeUndefined();
167
- // ErrorAlert should not be rendered when no error slot is provided
168
- expect(wrapper.find("[role='alert']").exists()).toBe(false);
169
- // Verify error prop is still propagated to individual checkboxes
170
- const checkboxes = wrapper.findAllComponents(FzCheckbox);
171
- checkboxes.forEach((checkbox) => {
172
- expect(checkbox.props("error")).toBe(true);
173
- });
174
- });
175
-
176
- it("has aria-describedby when help text is present", async () => {
177
- const wrapper = mount(FzCheckboxGroup, {
178
- props: {
179
- label: "Test Checkbox Group",
180
- modelValue: [],
181
- options: [
182
- { label: "Option 1", value: "option1" },
183
- { label: "Option 2", value: "option2" },
184
- ],
185
- },
186
- slots: {
187
- help: "This is help text",
188
- },
189
- });
190
- await wrapper.vm.$nextTick();
191
- const groupId = wrapper.find("[role='group']").attributes("id");
192
- const helpId = groupId + "-help";
193
- expect(wrapper.find("[role='group']").attributes("aria-describedby")).toBe(
194
- helpId,
195
- );
196
- expect(wrapper.find(`#${helpId}`).exists()).toBe(true);
197
- expect(wrapper.find(`#${helpId}`).text()).toBe("This is help text");
198
- });
199
-
200
- it("has aria-describedby with both help and error", async () => {
201
- const wrapper = mount(FzCheckboxGroup, {
202
- props: {
203
- label: "Test Checkbox Group",
204
- modelValue: [],
205
- options: [
206
- { label: "Option 1", value: "option1" },
207
- { label: "Option 2", value: "option2" },
208
- ],
209
- error: true,
210
- },
211
- slots: {
212
- help: "This is help text",
213
- error: "This is an error",
214
- },
215
- });
216
- await wrapper.vm.$nextTick();
217
- const groupId = wrapper.find("[role='group']").attributes("id");
218
- const helpId = groupId + "-help";
219
- const errorId = groupId + "-error";
220
- const describedby = wrapper
221
- .find("[role='group']")
222
- .attributes("aria-describedby");
223
-
224
- // Should contain both IDs separated by space
225
- expect(describedby).toContain(helpId);
226
- expect(describedby).toContain(errorId);
227
- expect(describedby).toBe(`${helpId} ${errorId}`);
228
- });
229
-
230
- it("propagates error prop to child checkboxes in hierarchical structure", async () => {
231
- const wrapper = mount(FzCheckboxGroup, {
232
- props: {
233
- label: "Test Checkbox Group",
234
- modelValue: [],
235
- options: [
236
- {
237
- label: "Parent Option",
238
- value: "parent",
239
- children: [
240
- { label: "Child 1", value: "child1" },
241
- { label: "Child 2", value: "child2" },
242
- ],
243
- },
244
- ],
245
- error: true,
246
- },
247
- slots: {
248
- error: "Test error message",
249
- },
250
- });
251
-
252
- await wrapper.vm.$nextTick();
253
- const allCheckboxes = wrapper.findAllComponents(FzCheckbox);
254
-
255
- // Should have parent + 2 children = 3 checkboxes
256
- expect(allCheckboxes.length).toBe(3);
257
-
258
- // All checkboxes should have error prop set to true
259
- allCheckboxes.forEach((checkbox) => {
260
- expect(checkbox.props("error")).toBe(true);
261
- });
262
- });
263
- });