diff --git a/.prettierrc b/.prettierrc
index f1c8e7129..21209f49e 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,4 +1,4 @@
{
- "tabWidth": 2,
+ "tabWidth": 4,
"bracketSameLine": true
}
\ No newline at end of file
diff --git a/jest.config.js b/jest.config.js
index 83e6a5c70..ded486df9 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -28,8 +28,7 @@ module.exports = {
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
coverageThreshold: {
global: {
- // TODO KO
- statements: 55,
+ statements: 85,
// Got the go ahead from Mark to temporarily lower this. Taking out initialize component made the year,make,model and style coverage drop a bit. Once unit tests for license plate lookup, vin lookup and address lookup are in the coverage should go back up to 90
},
},
diff --git a/src/App.vue b/src/App.vue
index 71b56feaf..c934ee244 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,16 +1,65 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/common-components/base-input-button/base-input-button.spec.js b/src/common-components/base-input-button/base-input-button.spec.js
new file mode 100644
index 000000000..190448df9
--- /dev/null
+++ b/src/common-components/base-input-button/base-input-button.spec.js
@@ -0,0 +1,539 @@
+import { shallowMount, mount } from "@vue/test-utils";
+import baseInputButton from "./base-input-button";
+
+describe("baseInputButton.vue", () => {
+ describe("general", () => {
+ describe("checkbox", () => {
+ test("isMultiSelect => baseInputButton is a checkbox", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(inputElement.attributes().type).toEqual("checkbox");
+ });
+ });
+
+ describe("radio", () => {
+ test("!isMultiSelect => baseInputButton is a radio button", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(inputElement.attributes().type).toEqual("radio");
+ });
+ });
+
+ // tests in here should be test.each
+ describe("shared", () => {
+ const isMultiSelectOptions = [true, false];
+ test.each(isMultiSelectOptions)("groupName", (isMultiSelect) => {
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ groupName: "boogly",
+ isMultiSelect: isMultiSelect,
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ const inputElementAttributes = inputElement.attributes();
+ expect(inputElementAttributes.name).toEqual("boogly");
+ });
+ });
+ });
+
+ describe("mouse clicks", () => {
+ describe("checkbox", () => {
+ test("clicked => correct event and value are emitted", async () => {
+ // Arrange
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ value: "X",
+ },
+ },
+ });
+
+ // Act
+ await wrapper.trigger("mousedown.left");
+ await wrapper.trigger("click");
+
+ // Assert
+ expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual([
+ "X",
+ ]);
+ });
+ });
+
+ describe("radio", () => {
+ test("clicked => correct event and value are emitted", async () => {
+ // Arrange
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ value: "X",
+ },
+ },
+ });
+
+ // Act
+ await wrapper.trigger("mousedown.left");
+ await wrapper.trigger("click");
+
+ // Assert
+ expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual(
+ "X"
+ );
+ });
+ });
+ });
+
+ describe("keyboard navigation and events", () => {
+ describe("checkbox", () => {
+ test.todo(
+ "focus on a checkbox => inputButtonClicked is not emitted"
+ );
+
+ test.todo(
+ "blur from a checkbox => inputButtonClicked is not emitted"
+ );
+
+ test("change event fired from checkbox => inputButtonClicked is emitted with correct value", async () => {
+ // Arrange
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ value: "Hi",
+ },
+ },
+ });
+
+ const input = wrapper.find("input");
+
+ // Act
+ await input.trigger("change");
+
+ // Assert
+ expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual([
+ "Hi",
+ ]);
+ });
+
+ test("focus and click space on a checkbox => inputButtonClicked is not emitted", async () => {
+ // Arrange
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ value: "Hi",
+ },
+ },
+ });
+
+ const input = wrapper.find("input");
+
+ // Act
+ await input.trigger("keypress", { key: "space" });
+
+ // Assert
+ expect(wrapper.emitted()).not.toHaveProperty(
+ "inputButtonClicked"
+ );
+ });
+
+ test("focus and click enter on a checkbox => inputButtonClicked is emitted with correct value", async () => {
+ // Arrange
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ value: "Hi",
+ },
+ },
+ });
+
+ const input = wrapper.find("input");
+
+ // Act
+ await input.trigger("keypress", { key: "enter" });
+
+ // Assert
+ expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual([
+ "Hi",
+ ]);
+ });
+ });
+
+ describe("radio", () => {
+ test.todo(
+ "focus on a radio button => inputButtonClicked is not emitted"
+ );
+
+ test.todo(
+ "blur from a radio button => inputButtonClicked is not emitted"
+ );
+
+ test("focus and click space on a radio button => inputButtonClicked is emitted with correct value", async () => {
+ // Arrange
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ value: "Hi",
+ },
+ },
+ });
+
+ const input = wrapper.find("input");
+
+ // Act
+ await input.trigger("keypress", { key: "space" });
+
+ // Assert
+ expect(wrapper.emitted()).toHaveProperty("inputButtonClicked");
+ expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual(
+ "Hi"
+ );
+ });
+
+ test("focus and click enter on a radio button => inputButtonClicked is emitted with correct value", async () => {
+ // Arrange
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ value: "Hi",
+ },
+ },
+ });
+
+ const input = wrapper.find("input");
+
+ // Act
+ await input.trigger("keypress", { key: "enter" });
+
+ // Assert
+ expect(wrapper.emitted()).toHaveProperty("inputButtonClicked");
+ expect(wrapper.emitted()["inputButtonClicked"][0][0]).toEqual(
+ "Hi"
+ );
+ });
+ });
+ });
+
+ describe("methods", () => {
+ describe("handleEventAction", () => {});
+
+ describe("handleSelectionChange", () => {
+ test.todo("handleChange is called with valueToEmit");
+
+ describe("checkbox", () => {
+ test.todo("modelValue is null => valueToEmit is correct value");
+
+ test.todo(
+ "modelValue is undefined => valueToEmit is correct value"
+ );
+ test.todo(
+ "modelValue is empty => valueToEmit is correct value"
+ );
+
+ test.todo(
+ "modelValue is not empty and does not contain this button's value => valueToEmit is correct value"
+ );
+ test.todo(
+ "modelValue is not empty and does contain this button's value => valueToEmit is correct value"
+ );
+ });
+
+ describe("radio", () => {});
+ });
+
+ describe("handleClick", () => {
+ test.todo("handleSelectChange is also called");
+
+ test.todo("inputButtonClicked is emitted with valueToEmit");
+ });
+ });
+
+ describe("computed", () => {
+ describe("isChecked", () => {
+ describe("checkbox", () => {
+ const falsyModelValues = [[], null, undefined];
+ test.each(falsyModelValues)(
+ "modelValue is falsy/empty => checkbox isn't checked",
+ (modelValue) => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ modelValue,
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.isChecked).toEqual(false);
+ expect(inputElement.element.checked).toBe(false);
+ }
+ );
+
+ test("modelValue doesn't contain this button's value => checkbox isn't checked", async () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ modelValue: ["Aaa", "Bbb", "Ccc"],
+ value: "Ddd",
+ },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.isChecked).toEqual(false);
+ expect(inputElement.element.checked).toBe(false);
+ });
+
+ test("modelValue contains this button's value => checkbox is checked", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ modelValue: ["Aaa", "Bbb", "Ddd", "Ccc"],
+ value: "Ddd",
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.isChecked).toEqual(true);
+ expect(inputElement.element.checked).toBe(true);
+ });
+ });
+
+ describe("radio", () => {
+ const falsyModelValues = ["", null, undefined, []];
+ test.each(falsyModelValues)(
+ "modelValue is falsy/empty => radio button isn't checked",
+ (modelValue) => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ modelValue,
+ value: "Aaa",
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.isChecked).toEqual(false);
+ expect(inputElement.element.checked).toBe(false);
+ }
+ );
+
+ test("modelValue equals this button's value => radio button is checked", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ modelValue: "Ddd",
+ value: "Ddd",
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.isChecked).toEqual(true);
+ expect(inputElement.element.checked).toBe(true);
+ });
+
+ test("modelValue doesn't equal this button's value => radio button isn't checked", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ modelValue: "Aaa",
+ value: "Ddd",
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.isChecked).toEqual(false);
+ expect(inputElement.element.checked).toBe(false);
+ });
+ });
+ });
+
+ describe("buttonId", () => {
+ test("groupName and value combo yield correct id for input button with string value", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ groupName: "my test-name",
+ value: "Aaa-BBB CcC",
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.buttonId).toBe("my-test-name-Aaa-BBB-CcC");
+ expect(inputElement.attributes().id).toBe(
+ "my-test-name-Aaa-BBB-CcC"
+ );
+ });
+
+ test("groupName and value combo yield correct id for input button with number value", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ groupName: "my test-name",
+ value: 2,
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.buttonId).toBe("my-test-name-2");
+ expect(inputElement.attributes().id).toBe("my-test-name-2");
+ });
+ });
+
+ describe("inputType", () => {
+ test("isMultiSelect is true => inputType is 'checkbox'", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.inputType).toEqual("checkbox");
+ expect(inputElement.attributes().type).toBe("checkbox");
+ });
+
+ test("isMultiSelect is false => inputType is 'radio'", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ },
+ },
+ });
+
+ // Assert
+ const inputElement = wrapper.find("input");
+ expect(wrapper.vm.inputType).toEqual("radio");
+ expect(inputElement.attributes().type).toBe("radio");
+ });
+ });
+ });
+});
+
+// TODO KO look at how I tested groups of these in SFA (making sure selecting one radio changes the value, etc, that this acts like a regular input aside from a different emitted event)
+
+function setupMocks({ mockData = {}, shouldShallowMount = true }) {
+ const baseInputButtonWrapper = {
+ components: { baseInputButton },
+ template: '',
+ data() {
+ return {
+ myValue: "",
+ };
+ },
+ };
+ const mountMockData = {
+ ...mockData,
+ propsData: {
+ // to get rid of some annoying warnings
+ groupName: "groupName",
+ modelValue: mockData.propsData?.isMultiSelect ? [] : "",
+ value: "5",
+ setLastValuePushedToGa: () => {},
+ // should override the above if they exist
+ ...mockData.propsData,
+ },
+ };
+
+ const wrapper = shouldShallowMount
+ ? shallowMount(baseInputButton, mountMockData)
+ : mount(baseInputButton, mountMockData);
+
+ wrapper.vm.pushEventToGA = jest.fn();
+ wrapper.vm.$route = {
+ query: {},
+ };
+ wrapper.vm.GaActions = {}
+
+ return { wrapper };
+}
+
+function setupBaseInputButtonWrapper({ mockData = {} }) {
+ const baseInputButtonWrapper = {
+ components: { baseInputButton },
+ template:
+ '
',
+ data() {
+ return {
+ myValue: "",
+ isMultiSelect: mockData.isMultiSelect,
+ };
+ },
+
+ // const parentComponent = mount({
+ // data() {
+ // return {
+ // value: "value1",
+ // }
+ // },
+ // template: '
',
+ // components: { baseInputButton }
+ // })
+ };
+
+ const wrapper = mount(baseInputButtonWrapper, {});
+
+ return { wrapper };
+}
diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue
index a3d890234..8cd50278e 100644
--- a/src/common-components/base-input-button/base-input-button.vue
+++ b/src/common-components/base-input-button/base-input-button.vue
@@ -2,8 +2,9 @@