diff --git a/README.md b/README.md index b08a36a..a356fb9 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ you will need to refactor it back into a regular template. 1. If a value is not updating correctly after a `wrapper.setProps` call, follow these steps to add a `nextTick()`, which will cause Vue to update the value: 1. If it's not already imported, add `import { nextTick } from "vue"` 2. Add `async` to the test arrow function. - 3. Add `await nextTick()` between the `setProps` and the assertion. + 3. Add `await nextTick()` between the `setProps` and the assertion, or simply prepend the setProps command with `await`. (Example: `await wrapper.setProps({ show: true })`) 1. Refer to the [vue-test-utils migration guide](https://test-utils.vuejs.org/migration/) for other breaking changes. 1. Running the tests will produce a snapshot file. Compare it to the original snapshot file. If there are no substantial changes, commit it. If there are substantial changes, make any necessary changes. diff --git a/src/components/LuxInputRadio.vue b/src/components/LuxInputRadio.vue new file mode 100644 index 0000000..fb926c6 --- /dev/null +++ b/src/components/LuxInputRadio.vue @@ -0,0 +1,252 @@ + + + + + + + + ```jsx +
+ + +
+ ``` +
diff --git a/src/components/index.js b/src/components/index.js index 4dbc5e4..0f32179 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,6 +1,7 @@ export * from "./icons" import LuxInputButton from "./LuxInputButton.vue" import LuxInputCheckbox from "./LuxInputCheckbox.vue" +import LuxInputRadio from "./LuxInputRadio.vue" import LuxInputSelect from "./LuxInputSelect.vue" import LuxInputText from "./LuxInputText.vue" import _LuxCardContent from "./_LuxCardContent.vue" @@ -36,6 +37,7 @@ import LuxTag from "./LuxTag.vue" export { LuxInputButton, LuxInputCheckbox, + LuxInputRadio, LuxInputSelect, LuxInputText, _LuxCardContent, diff --git a/tests/unit/specs/components/__snapshots__/luxInputRadio.spec.js.snap b/tests/unit/specs/components/__snapshots__/luxInputRadio.spec.js.snap new file mode 100644 index 0000000..24e31f4 --- /dev/null +++ b/tests/unit/specs/components/__snapshots__/luxInputRadio.spec.js.snap @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LuxInputRadio.vue has the expected html structure 1`] = ` +
+ + +
+ + +
+
+ + +
+ + +
+`; diff --git a/tests/unit/specs/components/luxInputRadio.spec.js b/tests/unit/specs/components/luxInputRadio.spec.js new file mode 100644 index 0000000..d39b4c4 --- /dev/null +++ b/tests/unit/specs/components/luxInputRadio.spec.js @@ -0,0 +1,123 @@ +import { createLocalVue, mount } from "@vue/test-utils" +import { nextTick } from "vue" +import LuxInputRadio from "@/components/LuxInputRadio.vue" + +describe("LuxInputRadio.vue", () => { + let wrapper + + beforeEach(() => { + wrapper = mount(LuxInputRadio, { + slots: { + default: "Apply Changes.", + }, + propsData: { + id: "foo", + options: [ + { + name: "opt 1", + value: "one", + id: "radio-opt1", + checked: true, + }, + { + name: "opt 2", + value: "two", + id: "radio-opt2", + checked: false, + }, + ], + }, + }) + }) + + it("should emit a change event with the correct value when clicked", () => { + wrapper.findAll("input").at(1).trigger("change") + expect(wrapper.emitted().change[0]).toEqual(["two"]) + }) + + it("should emit an inputblur event with the correct value when focus is blurred", () => { + const radio = wrapper.findAll("input").at(1) + radio.trigger("focus") + radio.trigger("blur") + const emitted = wrapper.emitted() + expect(Object.prototype.hasOwnProperty.call(emitted, "inputblur")).toBe(true) + }) + + it("should have a label for the correct id", () => { + const label = wrapper.findAll("label").at(1) + expect(label.text()).toBe("two") + expect(label.attributes().for).toBe("radio-opt2") + }) + + it("should stack if vertical is true", async () => { + const radio = wrapper.findAll(".lux-radio").at(0) + expect(radio.classes()).toContain("lux-inline") + await wrapper.setProps({ vertical: true }) + expect(radio.classes()).not.toContain("lux-inline") + }) + + it("should display an errormessage with the proper role when passed in as a prop", async () => { + expect(wrapper.find(".lux-error").exists()).toBe(false) + await wrapper.setProps({ errormessage: "Something went wrong." }) + expect(wrapper.find(".lux-error").exists()).toBe(true) + expect(wrapper.find(".lux-error").attributes().role).toBe("alert") + }) + + it("should display a legend if groupLabel is passed in as a prop", async () => { + expect(wrapper.find("legend").exists()).toBe(false) + await wrapper.setProps({ groupLabel: "Multiple choice:" }) + expect(wrapper.find("legend").exists()).toBe(true) + }) + + it("should have the id that is passed in as a prop", () => { + const radio = wrapper.findAll("input").at(1) + expect(radio.attributes().id).toBe("radio-opt2") + }) + + it("should have a fieldset wrapper if groupLabel is passed in as a prop", async () => { + const fieldset = wrapper.find("fieldset") + expect(fieldset.exists()).toBe(false) + // can't setProps here because the component must be regenerated to change its wrapper + const wrapper2 = mount(LuxInputRadio, { + slots: { + default: "Apply Changes.", + }, + propsData: { + id: "bar", + groupLabel: "Multiple choice:", + options: [ + { + name: "opt 1", + value: "one", + id: "radio-opt1", + checked: true, + }, + ], + }, + }) + const fieldset2 = wrapper2.find("fieldset") + expect(fieldset2.exists()).toBe(true) + }) + + // checked and disabled are not showing up in snapshots + // cannot seem to test + // + // it("should not be clickable if disabled", () => { + // wrapper.setProps({ options: [ + // { + // name: "opt 1", + // value: "one", + // id: "radio-opt1", + // disabled: true, + // checked: false + // } + // ] }) + // const radio = wrapper.findAll(".radio").at(0) + // radio.trigger("click") + // expect(radio.attributes().checked).toBe(false) + // }) + + it("has the expected html structure", () => { + expect(wrapper.element).toMatchSnapshot() + }) +})