From 6d45b96e4ec8e04c48688a726fe43075bfdfaeb8 Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Wed, 20 Apr 2022 14:40:16 +0800 Subject: [PATCH] feat: add checkbox and checkbox-group component Signed-off-by: Ryan Wang --- src/components/base/checkbox/CheckBox.vue | 56 ++++++++ .../base/checkbox/CheckBoxGroup.vue | 59 +++++++++ .../base/checkbox/__tests__/CheckBox.spec.ts | 61 +++++++++ .../checkbox/__tests__/CheckBoxGroup.spec.ts | 124 ++++++++++++++++++ .../__snapshots__/CheckBox.spec.ts.snap | 8 ++ .../__snapshots__/CheckBoxGroup.spec.ts.snap | 12 ++ src/components/base/checkbox/index.ts | 2 + src/components/base/radio/Radio.vue | 8 +- .../__snapshots__/Radio.spec.ts.snap | 4 +- .../__snapshots__/RadioGroup.spec.ts.snap | 4 +- src/views/ViewComponents.vue | 42 +++++- 11 files changed, 369 insertions(+), 11 deletions(-) create mode 100644 src/components/base/checkbox/CheckBox.vue create mode 100644 src/components/base/checkbox/CheckBoxGroup.vue create mode 100644 src/components/base/checkbox/__tests__/CheckBox.spec.ts create mode 100644 src/components/base/checkbox/__tests__/CheckBoxGroup.spec.ts create mode 100644 src/components/base/checkbox/__tests__/__snapshots__/CheckBox.spec.ts.snap create mode 100644 src/components/base/checkbox/__tests__/__snapshots__/CheckBoxGroup.spec.ts.snap create mode 100644 src/components/base/checkbox/index.ts diff --git a/src/components/base/checkbox/CheckBox.vue b/src/components/base/checkbox/CheckBox.vue new file mode 100644 index 00000000..766cb2e3 --- /dev/null +++ b/src/components/base/checkbox/CheckBox.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/components/base/checkbox/CheckBoxGroup.vue b/src/components/base/checkbox/CheckBoxGroup.vue new file mode 100644 index 00000000..a9e91a57 --- /dev/null +++ b/src/components/base/checkbox/CheckBoxGroup.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/components/base/checkbox/__tests__/CheckBox.spec.ts b/src/components/base/checkbox/__tests__/CheckBox.spec.ts new file mode 100644 index 00000000..813f40b9 --- /dev/null +++ b/src/components/base/checkbox/__tests__/CheckBox.spec.ts @@ -0,0 +1,61 @@ +import { describe, expect, it } from "vitest"; +import { VCheckbox } from "../index"; +import { mount } from "@vue/test-utils"; + +describe("CheckBox", () => { + it("should render", () => { + expect(VCheckbox).toBeDefined(); + expect(mount(VCheckbox).html()).toMatchSnapshot(); + }); + + it("should work with v-model:checked", async function () { + const wrapper = mount({ + data() { + return { + checked: false, + }; + }, + template: ` + + `, + components: { + VCheckbox, + }, + }); + + expect(wrapper.find("input").element.checked).toBe(false); + expect(wrapper.findComponent(VCheckbox).classes()).not.toContain( + "checkbox-wrapper-checked" + ); + + // change checked value + await wrapper.setData({ checked: true }); + expect(wrapper.find("input").element.checked).toBe(true); + expect(wrapper.findComponent(VCheckbox).classes()).toContain( + "checkbox-wrapper-checked" + ); + + // click on checkbox + await wrapper.find("input").setValue(false); + expect(wrapper.vm.checked).toBe(false); + expect(wrapper.find("input").element.checked).toBe(false); + expect(wrapper.findComponent(VCheckbox).classes()).not.toContain( + "checkbox-wrapper-checked" + ); + }); + + it("should work with label prop", async function () { + const wrapper = mount(VCheckbox, { + props: { + checked: true, + }, + }); + + expect(wrapper.html()).not.toContain("label"); + + await wrapper.setProps({ label: "label" }); + + expect(wrapper.html()).toContain("label"); + expect(wrapper.find("label").text()).toBe("label"); + }); +}); diff --git a/src/components/base/checkbox/__tests__/CheckBoxGroup.spec.ts b/src/components/base/checkbox/__tests__/CheckBoxGroup.spec.ts new file mode 100644 index 00000000..6a302cb6 --- /dev/null +++ b/src/components/base/checkbox/__tests__/CheckBoxGroup.spec.ts @@ -0,0 +1,124 @@ +import { describe, expect, it } from "vitest"; +import { VCheckbox, VCheckboxGroup } from "../index"; +import { mount } from "@vue/test-utils"; + +const options = [ + { + value: "foo", + label: "foo", + }, + { + value: "bar", + label: "bar", + }, +]; + +describe("CheckBoxGroup", () => { + it("should render", () => { + expect(VCheckboxGroup).toBeDefined(); + expect( + mount(VCheckboxGroup, { + props: { + options, + }, + }).html() + ).toMatchSnapshot(); + }); + + it("should work with options prop", function () { + const wrapper = mount({ + data() { + return { + options: options, + }; + }, + template: ` + + `, + components: { + VCheckboxGroup, + }, + }); + + expect(wrapper.findAllComponents(VCheckbox).length).toBe(2); + expect(wrapper.findAllComponents(VCheckbox)[0].vm.$props.value).toBe("foo"); + expect(wrapper.findAllComponents(VCheckbox)[0].vm.$props.label).toBe("foo"); + expect(wrapper.findAllComponents(VCheckbox)[1].vm.$props.value).toBe("bar"); + expect(wrapper.findAllComponents(VCheckbox)[1].vm.$props.label).toBe("bar"); + }); + + it("should work with v-model", async function () { + const wrapper = mount({ + data() { + return { + value: ["foo"], + options: options, + }; + }, + template: ` + + `, + components: { + VCheckboxGroup, + }, + }); + + expect(wrapper.findAllComponents(VCheckbox)[0].classes()).toContain( + "checkbox-wrapper-checked" + ); + expect( + wrapper.findAllComponents(VCheckbox)[0].find("input").element.checked + ).toBe(true); + + // mock click event + await wrapper.findAllComponents(VCheckbox)[1].find("input").setValue(true); + + expect(wrapper.findAllComponents(VCheckbox)[1].classes()).toContain( + "checkbox-wrapper-checked" + ); + expect( + wrapper.findAllComponents(VCheckbox)[1].find("input").element.checked + ).toBe(true); + expect(wrapper.vm.value).toEqual(["foo", "bar"]); + }); + + it("should work with valueKey and labelKey props", async function () { + const wrapper = mount({ + data() { + return { + value: ["foo"], + options: [ + { + id: "foo", + name: "foo", + }, + { + id: "bar", + name: "bar", + }, + ], + }; + }, + template: ` + + `, + components: { + VCheckboxGroup, + }, + }); + + expect( + wrapper.findAllComponents(VCheckbox)[0].find("input").attributes("value") + ).toBe("foo"); + expect( + wrapper.findAllComponents(VCheckbox)[0].find(".checkbox-label").text() + ).toBe("foo"); + + await wrapper.findAllComponents(VCheckbox)[1].find("input").setValue(true); + expect(wrapper.findAllComponents(VCheckbox)[1].classes()).toContain( + "checkbox-wrapper-checked" + ); + + expect(wrapper.vm.value).toEqual(["foo", "bar"]); + }); +}); diff --git a/src/components/base/checkbox/__tests__/__snapshots__/CheckBox.spec.ts.snap b/src/components/base/checkbox/__tests__/__snapshots__/CheckBox.spec.ts.snap new file mode 100644 index 00000000..8aaef497 --- /dev/null +++ b/src/components/base/checkbox/__tests__/__snapshots__/CheckBox.spec.ts.snap @@ -0,0 +1,8 @@ +// Vitest Snapshot v1 + +exports[`CheckBox > should render 1`] = ` +"
+
+ +
" +`; diff --git a/src/components/base/checkbox/__tests__/__snapshots__/CheckBoxGroup.spec.ts.snap b/src/components/base/checkbox/__tests__/__snapshots__/CheckBoxGroup.spec.ts.snap new file mode 100644 index 00000000..3f947977 --- /dev/null +++ b/src/components/base/checkbox/__tests__/__snapshots__/CheckBoxGroup.spec.ts.snap @@ -0,0 +1,12 @@ +// Vitest Snapshot v1 + +exports[`CheckBoxGroup > should render 1`] = ` +"
+
+
+
+
+
+
+
" +`; diff --git a/src/components/base/checkbox/index.ts b/src/components/base/checkbox/index.ts new file mode 100644 index 00000000..fc2c8cc5 --- /dev/null +++ b/src/components/base/checkbox/index.ts @@ -0,0 +1,2 @@ +export { default as VCheckbox } from "./CheckBox.vue"; +export { default as VCheckboxGroup } from "./CheckBoxGroup.vue"; diff --git a/src/components/base/radio/Radio.vue b/src/components/base/radio/Radio.vue index 09e96ddd..00b98637 100644 --- a/src/components/base/radio/Radio.vue +++ b/src/components/base/radio/Radio.vue @@ -31,18 +31,18 @@ function handleChange(e: Event) { }