diff --git a/jest.config.js b/jest.config.js
index 40025f122..aaf2d9ff8 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -26,7 +26,7 @@ module.exports = {
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
coverageThreshold: {
global: {
- statements: 76,
+ statements: 75,
// 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/constants/error-messages.js b/src/constants/error-messages.js
index 810929d20..415647879 100644
--- a/src/constants/error-messages.js
+++ b/src/constants/error-messages.js
@@ -27,6 +27,8 @@ const errorMessages = {
VEHICLE_REQUIRED: "Please select a vehicle",
MOBILE_LOCATION_REQUIRED: "Please enter your service address",
DATE_REQUIRED: "Please select a date",
+ PHONE_REQUIRED: "Please enter your phone number",
+ PHONE_FORMAT: "Phone number must be 10 digits",
};
export { errorMessages };
diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js
index 392e7b59e..9d7d3ea6a 100644
--- a/src/constants/store-actions.js
+++ b/src/constants/store-actions.js
@@ -84,6 +84,7 @@ const storeActions = {
SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING:
"saveSupportingItemsSuppressingStateResetting",
SAVE_VAPS: "saveVaps",
+ SAVE_CUSTOMER_DETAILS: "saveCustomerDetails",
};
export { storeActions };
diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js
index d4e07cf0a..76d510507 100644
--- a/src/constants/store-mutations.js
+++ b/src/constants/store-mutations.js
@@ -38,6 +38,9 @@ const storeMutations = {
UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress",
+ //CUSTOMER MUTATIONS
+ UPDATE_CUSTOMER_DETAILS: "updateCustomerDetails",
+
// ORDER MUTATIONS
UPDATE_REFERRAL_NUMBER: "updateReferralNumber",
UPDATE_REFERRAL_DATE: "updateReferralDate",
diff --git a/src/digital-components/button-question/button-question.vue b/src/digital-components/button-question/button-question.vue
index 610f8d4f8..a53958dd5 100644
--- a/src/digital-components/button-question/button-question.vue
+++ b/src/digital-components/button-question/button-question.vue
@@ -189,7 +189,7 @@ export default {
classes = "d-flex flex-row p-0";
break;
case "listCard":
- classes = "row g-2 justify-content-center";
+ classes = "row g-2 justify-content-center mb-1";
if (this.isWide) {
classes += " flex-column";
}
diff --git a/src/ux-components/checkbox/checkbox.spec.js b/src/digital-components/checkbox-question/checkbox-question.spec.js
similarity index 66%
rename from src/ux-components/checkbox/checkbox.spec.js
rename to src/digital-components/checkbox-question/checkbox-question.spec.js
index e231ecc77..3c5d75bf9 100644
--- a/src/ux-components/checkbox/checkbox.spec.js
+++ b/src/digital-components/checkbox-question/checkbox-question.spec.js
@@ -1,14 +1,25 @@
import { shallowMount } from "@vue/test-utils";
-import checkbox from "./checkbox";
+import checkboxQuestion from "./checkbox-question";
import { nextTick } from "vue";
-describe("checkbox.vue", () => {
+// Mock CMS content
+const questionText = "Question Text";
+const mockMixin = {
+ methods: {
+ getCmsContent: jest.fn().mockImplementation(() => {
+ return questionText;
+ }),
+ },
+};
+
+describe("checkbox-question.vue", () => {
it("Should return checkbox name", async () => {
// Act
- const wrapper = shallowMount(checkbox, {
+ const wrapper = shallowMount(checkboxQuestion, {
propsData: {
checkboxName: "Checkbox",
},
+ mixins: [mockMixin],
});
// Assert
@@ -20,10 +31,11 @@ describe("checkbox.vue", () => {
it("Should return checkbox id", async () => {
// Act
- const wrapper = shallowMount(checkbox, {
+ const wrapper = shallowMount(checkboxQuestion, {
propsData: {
buttonID: "Checkbox ID",
},
+ mixins: [mockMixin],
});
// Assert
@@ -35,10 +47,11 @@ describe("checkbox.vue", () => {
it("Should return tabindex value", async () => {
// Act
- const wrapper = shallowMount(checkbox, {
+ const wrapper = shallowMount(checkboxQuestion, {
propsData: {
tabIndex: "1",
},
+ mixins: [mockMixin],
});
// Assert
@@ -50,24 +63,11 @@ describe("checkbox.vue", () => {
it("Should return label text", async () => {
// Act
- const wrapper = shallowMount(checkbox, {
- propsData: {
- checkboxLabel: "label text",
- },
- });
-
- // Assert
- const paragraph = wrapper.find("p");
-
- expect(paragraph.text()).toEqual("label text");
- });
-
- it("Should return label text", async () => {
- // Act
- const wrapper = shallowMount(checkbox, {
+ const wrapper = shallowMount(checkboxQuestion, {
propsData: {
screenReaderOnlyText: "screenreader text",
},
+ mixins: [mockMixin],
});
// Assert
diff --git a/src/ux-components/checkbox/checkbox.vue b/src/digital-components/checkbox-question/checkbox-question.vue
similarity index 72%
rename from src/ux-components/checkbox/checkbox.vue
rename to src/digital-components/checkbox-question/checkbox-question.vue
index cbc1120c5..e63c24523 100644
--- a/src/ux-components/checkbox/checkbox.vue
+++ b/src/digital-components/checkbox-question/checkbox-question.vue
@@ -2,6 +2,7 @@
@@ -18,15 +19,32 @@
diff --git a/src/digital-components/date-picker/date-picker.vue b/src/digital-components/date-picker/date-picker.vue
index a20884d40..50ecfeb88 100644
--- a/src/digital-components/date-picker/date-picker.vue
+++ b/src/digital-components/date-picker/date-picker.vue
@@ -924,7 +924,8 @@ export default {
.btn-link {
font-weight: 500;
text-underline-offset: 4px;
- flex-grow: 0;
+ position: absolute;
+ bottom: 0;
}
.past {
@@ -987,7 +988,7 @@ export default {
.btn-link {
display: block;
position: relative;
- height: 3rem;
+ height: 2rem;
width: 100%;
justify-content: center;
background: transparent;
diff --git a/src/digital-components/modal/modal.vue b/src/digital-components/modal/modal.vue
index ba59f9d86..899a63b8f 100644
--- a/src/digital-components/modal/modal.vue
+++ b/src/digital-components/modal/modal.vue
@@ -175,8 +175,7 @@ export default {
}
.modal-footer {
border-top: none;
- background-color: $gray-100;
- box-shadow: 0px -1px 0px rgba(179, 180, 181, 0.3);
+
button {
margin: 0;
}
diff --git a/src/digital-components/phone-number-question/phone-number-question.spec.js b/src/digital-components/phone-number-question/phone-number-question.spec.js
new file mode 100644
index 000000000..78ff60bf7
--- /dev/null
+++ b/src/digital-components/phone-number-question/phone-number-question.spec.js
@@ -0,0 +1,64 @@
+// Components
+import phoneNumberQuestion from "./phone-number-question";
+
+// Supporting Files
+import { shallowMount } from "@vue/test-utils";
+
+describe("phone-number-question.vue", () => {
+ it("Should render phoneNumberQuestion sub-component (textbox-question)", async () => {
+ // Arrange
+ const wrapper = shallowMount(phoneNumberQuestion, {});
+
+ wrapper.getCmsContent = jest.fn();
+
+ // Act
+ const phoneNumber = wrapper.findComponent({ ref: "phoneNumber" });
+
+ // Assert
+ expect(phoneNumber.exists()).toBe(true);
+ });
+
+ it("Should emit new value when modelValue is changed", async () => {
+ // Act
+ const wrapper = shallowMount(phoneNumberQuestion, {
+ propsData: {
+ modelValue: "val",
+ },
+ });
+
+ const phoneNumber = wrapper.findComponent({ ref: "phoneNumber" });
+ await phoneNumber.setValue("val2");
+
+ // Assert
+ expect(wrapper.emitted("update:modelValue")).toEqual([["val2"]]);
+ });
+
+ it("Should emit new value when modelValue is changed", async () => {
+ // Act
+ const wrapper = shallowMount(phoneNumberQuestion, {
+ propsData: {
+ modelValue: "val",
+ },
+ });
+
+ const phoneNumber = wrapper.findComponent({ ref: "phoneNumber" });
+ await phoneNumber.setValue("val2");
+
+ // Assert
+ expect(wrapper.emitted("update:modelValue")).toEqual([["val2"]]);
+ });
+
+ it("Should combine external and internal validation rules to pass to textbox-question", async () => {
+ // Act
+ const wrapper = shallowMount(phoneNumberQuestion, {
+ propsData: {
+ validationRules: "outsideValidation",
+ },
+ });
+
+ // Assert
+ expect(wrapper.vm.validationRulesForTextBoxQuestion).toEqual(
+ "outsideValidation|phone-number-format"
+ );
+ });
+});
diff --git a/src/digital-components/phone-number-question/phone-number-question.vue b/src/digital-components/phone-number-question/phone-number-question.vue
new file mode 100644
index 000000000..f3fdc6cd6
--- /dev/null
+++ b/src/digital-components/phone-number-question/phone-number-question.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/digital-components/text-block/text-block.vue b/src/digital-components/text-block/text-block.vue
index 50927781c..bb7ae8963 100644
--- a/src/digital-components/text-block/text-block.vue
+++ b/src/digital-components/text-block/text-block.vue
@@ -91,5 +91,8 @@ export default {
&.bold {
font-weight: 500;
}
+ &.dark {
+ color: $black;
+ }
}
diff --git a/src/digital-components/textarea-question/textarea-question.spec.js b/src/digital-components/textarea-question/textarea-question.spec.js
new file mode 100644
index 000000000..26c0b21ef
--- /dev/null
+++ b/src/digital-components/textarea-question/textarea-question.spec.js
@@ -0,0 +1,61 @@
+// Components
+import textareaQuestion from "./textarea-question";
+
+// Supporting Files
+import { shallowMount } from "@vue/test-utils";
+
+const maska = jest.fn();
+
+const questionText = "textareaQuestionText";
+const mockMixin = {
+ methods: {
+ getCmsContent: jest.fn().mockImplementation(() => {
+ return questionText;
+ }),
+ },
+};
+
+describe("textarea-question.vue", () => {
+ it("Should render a textarea", async () => {
+ // Arrange
+ const wrapper = shallowMount(textareaQuestion, {
+ global: {
+ directives: {
+ maska: maska,
+ },
+ },
+ propsData: {
+ modelValue: "",
+ },
+ mixins: [mockMixin],
+ });
+
+ wrapper.getCmsContent = jest.fn();
+
+ // Act
+ const textarea = wrapper.find("textarea");
+
+ // Assert
+ expect(textarea.exists()).toBe(true);
+ });
+
+ it("Should emit new value when modelValue is changed", async () => {
+ // Act
+ const wrapper = shallowMount(textareaQuestion, {
+ global: {
+ directives: {
+ maska: maska,
+ },
+ },
+ propsData: {
+ modelValue: "val",
+ },
+ mixins: [mockMixin],
+ });
+
+ await wrapper.find("textarea").setValue("val2");
+
+ // Assert
+ expect(wrapper.emitted("update:modelValue")).toEqual([["val2"]]);
+ });
+});
diff --git a/src/digital-components/textarea-question/textarea-question.vue b/src/digital-components/textarea-question/textarea-question.vue
new file mode 100644
index 000000000..0ffe5ec0a
--- /dev/null
+++ b/src/digital-components/textarea-question/textarea-question.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+ (Optional)
+
+
+
+ {{ remainingCount }}/{{ maxLength }} characters remaining
+
+
+
+
+
+
+
diff --git a/src/digital-components/textbox-question/textbox-question.vue b/src/digital-components/textbox-question/textbox-question.vue
index 5e9662c87..b82153895 100644
--- a/src/digital-components/textbox-question/textbox-question.vue
+++ b/src/digital-components/textbox-question/textbox-question.vue
@@ -44,7 +44,8 @@
@change="handleChange"
@blur="handleChange"
:maxlength="maxLength ? maxLength : '999'"
- @focus="$emit('focus', $event.target.value)" />
+ @focus="$emit('focus', $event.target.value)"
+ @keydown="keyDownHandler" />
@@ -118,6 +119,7 @@ export default {
maxFileSize: Number,
hideInput: Boolean,
centerErrorMessage: Boolean,
+ keyDownHandler: Function,
},
setup(props) {
const uuid = uuidv4();
diff --git a/src/fmg-components/funnel-footer/funnel-footer.vue b/src/fmg-components/funnel-footer/funnel-footer.vue
index f1900596b..c036f8d0a 100644
--- a/src/fmg-components/funnel-footer/funnel-footer.vue
+++ b/src/fmg-components/funnel-footer/funnel-footer.vue
@@ -1,6 +1,6 @@
-
-