Merge pull request #543 from Safelite/rlsmerge/release2022.06.23-to-develop
Rlsmerge/release2022.06.23 to develop
This commit is contained in:
commit
81099d222a
13 changed files with 1353 additions and 312 deletions
|
|
@ -18,11 +18,10 @@ module.exports = {
|
||||||
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
|
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
|
||||||
"!src/layouts/part-questions/**/*.vue",
|
"!src/layouts/part-questions/**/*.vue",
|
||||||
"!src/layouts/reveal/**/*.vue",
|
"!src/layouts/reveal/**/*.vue",
|
||||||
"!src/layouts/estimate/**/*.vue",
|
"!src/layouts/estimate/**/*.vue",
|
||||||
// TODO REMOVE THESE AFTER WRITING UNIT TESTS
|
// TODO REMOVE THESE AFTER WRITING UNIT TESTS
|
||||||
"!src/layouts/address-lookup/address-lookup.vue",
|
"!src/layouts/address-vehicles/address-vehicles.vue",
|
||||||
"!src/layouts/address-lookup/customer-questions/customer-questions.vue",
|
"!src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue",
|
||||||
"!src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue",
|
|
||||||
"!src/ux-components/alert\alert.vue",
|
"!src/ux-components/alert\alert.vue",
|
||||||
"!src/helpers/validation-rules.js",
|
"!src/helpers/validation-rules.js",
|
||||||
// END
|
// END
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
"test:unit": "vue-cli-service test:unit --coverage --ci",
|
"test:unit": "vue-cli-service test:unit --coverage --ci",
|
||||||
|
"test:unit:lite": "vue-cli-service test:unit --ci",
|
||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
<div class="modal fade" id="footerModal" tabindex="-1" aria-labelledby="footerModalLabel" aria-hidden="true" :style="`height: calc(100% - ${currentFooterAndHeaderHeight}px);`">
|
<div class="modal fade" id="footerModal" tabindex="-1" aria-labelledby="footerModalLabel" aria-hidden="true" v-on="{ 'show.bs.modal' : show, 'hide.bs.modal' : hide }" :style="`height: calc(100% - ${currentFooterAndHeaderHeight}px);`">
|
||||||
<div class="modal-dialog modal-fullscreen">
|
<div class="modal-dialog modal-fullscreen">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header visually-hidden">
|
<div class="modal-header visually-hidden">
|
||||||
|
|
@ -36,19 +36,18 @@ export default {
|
||||||
currentFooterAndHeaderHeight: 0,
|
currentFooterAndHeaderHeight: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
methods: {
|
||||||
const myModalEl = document.getElementById('footerModal');
|
show() {
|
||||||
var self = this;
|
this.currentFooterAndHeaderHeight = this.getFooterInfoBoxHeight() + 72;
|
||||||
myModalEl.addEventListener('hide.bs.modal', function (event) {
|
this.isActive = true;
|
||||||
self.isActive = false;
|
|
||||||
});
|
|
||||||
myModalEl.addEventListener('show.bs.modal', function (event) {
|
|
||||||
self.currentFooterAndHeaderHeight = self.getFooterInfoBoxHeight() + 72;
|
|
||||||
self.isActive = true;
|
|
||||||
document.querySelector('.page-container-grouped-styles').scrollTo({
|
document.querySelector('.page-container-grouped-styles').scrollTo({
|
||||||
top: 0, behavior: 'smooth'
|
top: 0, behavior: 'smooth'
|
||||||
});
|
});
|
||||||
})
|
},
|
||||||
|
hide() {
|
||||||
|
var self = this;
|
||||||
|
self.isActive = false;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
textLink,
|
textLink,
|
||||||
|
|
@ -81,7 +80,7 @@ export default {
|
||||||
.bar3 {
|
.bar3 {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background-color: $blue-400;
|
background-color: $blue;
|
||||||
margin: 1px 0;
|
margin: 1px 0;
|
||||||
transition: 0.25s;
|
transition: 0.25s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ export function getMountOptions(mockData) {
|
||||||
mocks.$store = mockData.store;
|
mocks.$store = mockData.store;
|
||||||
mocks.$router = mockData.router;
|
mocks.$router = mockData.router;
|
||||||
mocks.$route = mockData.route;
|
mocks.$route = mockData.route;
|
||||||
|
mocks.$loadScript = mockData.loadScript;
|
||||||
|
|
||||||
const global = {
|
const global = {
|
||||||
mocks: mocks,
|
mocks: mocks,
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,16 @@
|
||||||
// Components
|
// Components
|
||||||
import addressLookup from "@/layouts/address-lookup/address-lookup.vue";
|
import addressLookup from "@/layouts/address-lookup/address-lookup.vue";
|
||||||
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
|
||||||
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
|
|
||||||
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
|
||||||
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
|
||||||
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
|
|
||||||
import addressQuestions from "@/layouts/address-lookup/customer-questions/address-questions/address-questions";
|
|
||||||
import router from "@/router";
|
|
||||||
|
|
||||||
// Supporting Files
|
// Supporting Files
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
|
||||||
import baseMixin from "@/mixins/base-mixin";
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { shallowMount } from "@vue/test-utils";
|
||||||
import { mount, flushPromises, shallowMount } from "@vue/test-utils";
|
|
||||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import { maska } from 'maska';
|
|
||||||
import { nextTick } from "vue";
|
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { storeMutations } from "@/constants/store-mutations";
|
import { storeMutations } from "@/constants/store-mutations";
|
||||||
|
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { validate } from "vee-validate";
|
|
||||||
import { isGlassAvailableForCarId } from "@/helpers/damage-helper.js"
|
|
||||||
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
import { EXPECTATION_FAILED } from "http-status-codes";
|
|
||||||
|
|
||||||
// Mock our module for promises.
|
|
||||||
// jest.mock("@/helpers/layout-helper.js", () => ({
|
|
||||||
// settleAllPromises: jest.fn(),
|
|
||||||
// }));
|
|
||||||
|
|
||||||
// // Mock fetchCmsContentForPage
|
|
||||||
// jest.mock("@/helpers/cms-content-helper", () => ({
|
|
||||||
// fetchCmsContentForPage: jest.fn(),
|
|
||||||
// }));
|
|
||||||
|
|
||||||
jest.mock("@/helpers/damage-helper", () => ({
|
jest.mock("@/helpers/damage-helper", () => ({
|
||||||
isGlassAvailableForCarId: jest.fn().mockImplementation(() => true),
|
isGlassAvailableForCarId: jest.fn().mockImplementation(() => true),
|
||||||
|
|
@ -43,17 +21,530 @@ jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
|
||||||
navigateAfterSaveToHeritageFunnel: jest.fn()
|
navigateAfterSaveToHeritageFunnel: jest.fn()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
// const questionText = "Question Text";
|
|
||||||
// const mockMixin = {
|
|
||||||
// methods: {
|
|
||||||
// getCmsContent: jest.fn().mockImplementation(() => {
|
|
||||||
// return questionText;
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
describe("address-lookup.vue", () => {
|
describe("address-lookup.vue", () => {
|
||||||
|
describe("page level alerts", () => {
|
||||||
|
test("if the address is not serviceable display the Non-Serviceable Zip Alert", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.findComponent({ ref: "alertNonServiceableZip" }).isVisible()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if the address matches a different vehicle display the Matched Different VehicleAlert", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID2");
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.findComponent({ ref: "alertMatchedDifferentVehicle" }).isVisible()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if the looking up VIN by address is not allowed in the state selected display the Vin Lookup By HomeAddress Not Allowed Alert", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction = jest.fn();
|
||||||
|
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
|
||||||
|
let data = {};
|
||||||
|
if (actionName == storeActions.VALIDATE_ZIP) {
|
||||||
|
data = {
|
||||||
|
isServiceable: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
|
||||||
|
data = {
|
||||||
|
isStatePermissible: false,
|
||||||
|
vinVehicles: [{
|
||||||
|
vin: "TEST_VIN",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vin: "TEST_VIN2",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({ data });
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.findComponent({ ref: "alertVinLookupsByHomeAddressNotAllowed" }).isVisible()).toBe(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if no vehicles found, display Vin Not Found alert", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction = jest.fn();
|
||||||
|
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
|
||||||
|
let data = {};
|
||||||
|
if (actionName == storeActions.VALIDATE_ZIP) {
|
||||||
|
data = {
|
||||||
|
isServiceable: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
|
||||||
|
data = {
|
||||||
|
isStatePermissible: true,
|
||||||
|
vinVehicles: [] // Return no vehicles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({ data });
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.navigateForward = jest.fn();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.findComponent({ ref: "alertVinNotFound" }).isVisible()).toBe(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("navigation", () => {
|
||||||
|
|
||||||
|
test("if the back button is clicked, navigate back", async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.backButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if the car entered matches one of the vehicles found and the zip is serviceable, navigate forward", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction = jest.fn();
|
||||||
|
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
|
||||||
|
let data = {};
|
||||||
|
if (actionName == storeActions.VALIDATE_ZIP) {
|
||||||
|
data = {
|
||||||
|
isServiceable: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
|
||||||
|
data = {
|
||||||
|
isStatePermissible: true,
|
||||||
|
vinVehicles: [{
|
||||||
|
vin: "TEST_VIN",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vin: "TEST_VIN2",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({ data });
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.navigateForward = jest.fn();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if the car entered matches one of multiple vehicles found, update vehicle info and navigate to the heritage funnel", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction = jest.fn();
|
||||||
|
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
|
||||||
|
let data = {};
|
||||||
|
if (actionName == storeActions.VALIDATE_ZIP) {
|
||||||
|
data = {
|
||||||
|
isServiceable: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
|
||||||
|
data = {
|
||||||
|
isStatePermissible: true,
|
||||||
|
vinVehicles: [{
|
||||||
|
vin: "TEST_VIN",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vin: "TEST_VIN2",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({ data });
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.updateVehicleInfo = jest.fn();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.updateVehicleInfo).toHaveBeenCalled();
|
||||||
|
expect(navigateAfterSaveToHeritageFunnel).toHaveBeenCalled();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if the car entered does not match any of the multiple vehicles found, navigate to address-vehicles page", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID_A");
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction = jest.fn();
|
||||||
|
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
|
||||||
|
let data = {};
|
||||||
|
if (actionName == storeActions.VALIDATE_ZIP) {
|
||||||
|
data = {
|
||||||
|
isServiceable: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
|
||||||
|
data = {
|
||||||
|
isStatePermissible: true,
|
||||||
|
vinVehicles: [{
|
||||||
|
vin: "TEST_VIN",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vin: "TEST_VIN2",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({ data });
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
const carsFound = [{
|
||||||
|
vin: "TEST_VIN",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vin: "TEST_VIN2",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.updateVehicleInfo = jest.fn();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, undefined, {}, {}, carsFound);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if the car entered matches one of the vehicles found but the zip is NOT serviceable, do not navigate forward", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction = jest.fn();
|
||||||
|
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
|
||||||
|
let data = {};
|
||||||
|
if (actionName == storeActions.VALIDATE_ZIP) {
|
||||||
|
data = {
|
||||||
|
isServiceable: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
|
||||||
|
data = {
|
||||||
|
isStatePermissible: true,
|
||||||
|
vinVehicles: [{
|
||||||
|
vin: "TEST_VIN",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vin: "TEST_VIN2",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({ data });
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.navigateForward = jest.fn();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.navigateForward).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("if a different vehicle is found than the one entered and the selected glass is not available for that vehicle, navigate back to vehicle-damage page", async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockRegistrationAddress = {
|
||||||
|
streetAddress: "1234 Main St",
|
||||||
|
city: "Columbus",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "43215"
|
||||||
|
}
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction = jest.fn();
|
||||||
|
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
|
||||||
|
let data = {};
|
||||||
|
if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
|
||||||
|
data = {
|
||||||
|
isStatePermissible: true,
|
||||||
|
vinVehicles: [{
|
||||||
|
vin: "TEST_VIN",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({ data });
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
customerQuestions: {
|
||||||
|
addressQuestions: mockRegistrationAddress
|
||||||
|
},
|
||||||
|
isCarIdDifferent: true,
|
||||||
|
isGlassAvailableForCarId: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
let carEntered = [{
|
||||||
|
vin: "TEST_VIN",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID"
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
let carsFound = [{
|
||||||
|
vin: "TEST_VIN2",
|
||||||
|
vehicle: {
|
||||||
|
carId: "CARID2"
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.navigateForward(carEntered, carsFound);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.CONTINUING_WITH_DIFFERENT_GLASS, undefined, {}, {"displayVehicleChangeAlert": true}, {});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("reseting dependent state", () => {
|
||||||
|
test("when reseting dependent state, license plate is set to null and parts state and dependencies are reset", async () => {
|
||||||
|
// Arrange
|
||||||
|
const commitSpy = jest.spyOn(store, "commit");
|
||||||
|
const dispatchSpy = jest.spyOn(store, "dispatch");
|
||||||
|
const { wrapper } = setupMocks(addressLookup, {
|
||||||
|
isZipServiceable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.resetDependentState();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(commitSpy).toBeCalledWith(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, null);
|
||||||
|
expect(dispatchSpy).toBeCalledWith(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("registration and service zips", () => {
|
describe("registration and service zips", () => {
|
||||||
describe("if registration zip is serviceable", () => {
|
describe("if registration zip is serviceable", () => {
|
||||||
test("if registration address is provided => update service address on successful continue", async () => {
|
test("if registration address is provided => update service address on successful continue", async () => {
|
||||||
|
|
@ -242,77 +733,6 @@ describe("address-lookup.vue", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe.skip("initialization", () => {
|
|
||||||
test("Page header is initialized with api data", async (done) => {
|
|
||||||
//Arrange
|
|
||||||
const pageHeaderWidgetHeaderText = "Select Damage";
|
|
||||||
const { wrapper, apiPromise } = setupMocks({
|
|
||||||
pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText,
|
|
||||||
});
|
|
||||||
|
|
||||||
//Act
|
|
||||||
addressLookup.beforeRouteEnter.call(
|
|
||||||
wrapper.vm,
|
|
||||||
{ query: { fmgPage: "address-lookup" } },
|
|
||||||
undefined,
|
|
||||||
(c) => c(wrapper.vm)
|
|
||||||
);
|
|
||||||
|
|
||||||
//Assert
|
|
||||||
apiPromise.finally(() => {
|
|
||||||
expect(funnelSubHeader.methods.initializeComponent).toHaveBeenCalledWith(
|
|
||||||
pageHeaderWidgetHeaderText
|
|
||||||
);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Customer Questions component is initialized with api data", async (done) => {
|
|
||||||
//Arrange
|
|
||||||
const StreetAddressQuestionWidget = { QuestionText: "test" };
|
|
||||||
const CityQuestionWidget = { QuestionText: "test" };
|
|
||||||
const StateQuestionWidget = { QuestionText: "test" };
|
|
||||||
const ZipQuestionWidget = { QuestionText: "test" };
|
|
||||||
const FirstNameQuestionWidget = { QuestionText: "test" };
|
|
||||||
const LastNameQuestionWidget = { QuestionText: "test" };
|
|
||||||
const EmailAddressQuestionWidget = { QuestionText: "test" };
|
|
||||||
const AlertVerificationWarningWidget = { HeaderText: "test", BodyText: "test" };
|
|
||||||
const AlertNoMatchWarningWidget = { HeaderText: "test", BodyText: "test" };
|
|
||||||
|
|
||||||
const widgets = [
|
|
||||||
StreetAddressQuestionWidget,
|
|
||||||
CityQuestionWidget,
|
|
||||||
StateQuestionWidget,
|
|
||||||
ZipQuestionWidget,
|
|
||||||
AlertVerificationWarningWidget,
|
|
||||||
AlertNoMatchWarningWidget,
|
|
||||||
FirstNameQuestionWidget,
|
|
||||||
LastNameQuestionWidget,
|
|
||||||
EmailAddressQuestionWidget,
|
|
||||||
];
|
|
||||||
|
|
||||||
const { wrapper, apiPromise } = setupMocks({
|
|
||||||
cmsContent: widgets,
|
|
||||||
});
|
|
||||||
|
|
||||||
//Act
|
|
||||||
addressLookup.beforeRouteEnter.call(
|
|
||||||
wrapper.vm,
|
|
||||||
{ query: { fmgPage: "address-lookup" } },
|
|
||||||
undefined,
|
|
||||||
(c) => c(wrapper.vm)
|
|
||||||
);
|
|
||||||
|
|
||||||
//Assert
|
|
||||||
apiPromise.finally(() => {
|
|
||||||
expect(customerQuestions.methods.initializeComponent).toHaveBeenCalledWith(
|
|
||||||
widgets
|
|
||||||
);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks(mountOptions, { isZipServiceable = true, lookupVinbyAddressResponse }) {
|
function setupMocks(mountOptions, { isZipServiceable = true, lookupVinbyAddressResponse }) {
|
||||||
|
|
@ -351,154 +771,7 @@ function setupMocks(mountOptions, { isZipServiceable = true, lookupVinbyAddressR
|
||||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
||||||
wrapper.vm.$refs.loadingModal.showModal = jest.fn();
|
wrapper.vm.$refs.loadingModal.showModal = jest.fn();
|
||||||
|
|
||||||
// jest.mock("@/store", () => ({
|
|
||||||
// commit: jest.fn(),
|
|
||||||
// dispatch: jest.fn(),
|
|
||||||
// getters: {
|
|
||||||
// vehicle: {
|
|
||||||
// carId: "CARID"
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// }));
|
|
||||||
|
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// function setupMocks({
|
|
||||||
// pageHeaderWidgetHeaderText = {},
|
|
||||||
// mountOptionsMockData = {
|
|
||||||
// router: {
|
|
||||||
// navigate: jest.fn(),
|
|
||||||
// },
|
|
||||||
// store: {
|
|
||||||
// getters: {
|
|
||||||
// vehicle: {},
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// }) {
|
|
||||||
// //Mock api responses
|
|
||||||
// baseMixin.methods.dispatchStoreAction = jest.fn();
|
|
||||||
// const apiResponses = {
|
|
||||||
// cmsContent: {
|
|
||||||
// FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
|
|
||||||
// VehicleBannerWidget: {
|
|
||||||
// GenericVehicleImage:
|
|
||||||
// "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
|
||||||
// },
|
|
||||||
// FunnelHeaderWidget: {
|
|
||||||
// LogoImage:
|
|
||||||
// "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
|
||||||
// },
|
|
||||||
// StreetAddressQuestionWidget: {
|
|
||||||
// QuestionText:
|
|
||||||
// "test"
|
|
||||||
// },
|
|
||||||
// CityQuestionWidget: {
|
|
||||||
// QuestionText:
|
|
||||||
// "test"
|
|
||||||
// },
|
|
||||||
// StateQuestionWidget: {
|
|
||||||
// QuestionText:
|
|
||||||
// "test"
|
|
||||||
// },
|
|
||||||
// ZipQuestionWidget: {
|
|
||||||
// QuestionText:
|
|
||||||
// "test"
|
|
||||||
// },
|
|
||||||
// FirstNameQuestionWidget: {
|
|
||||||
// QuestionText:
|
|
||||||
// "test"
|
|
||||||
// },
|
|
||||||
// LastNameQuestionWidget: {
|
|
||||||
// QuestionText:
|
|
||||||
// "test"
|
|
||||||
// },
|
|
||||||
// EmailAddressQuestionWidget: {
|
|
||||||
// QuestionText:
|
|
||||||
// "test"
|
|
||||||
// },
|
|
||||||
// AlertVerificationWarningWidget: {
|
|
||||||
// HeaderText:
|
|
||||||
// "test",
|
|
||||||
// BodyText:
|
|
||||||
// "test",
|
|
||||||
// },
|
|
||||||
// AlertNoMatchWarningWidget: {
|
|
||||||
// HeaderText:
|
|
||||||
// "test",
|
|
||||||
// BodyText:
|
|
||||||
// "test",
|
|
||||||
// },
|
|
||||||
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const apiPromise = Promise.resolve(apiResponses);
|
|
||||||
|
|
||||||
// settleAllPromises.mockImplementation(() => apiPromise);
|
|
||||||
// fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
|
||||||
|
|
||||||
// //Mock damage initialize methods
|
|
||||||
// funnelHeader.methods = {
|
|
||||||
// initializeComponent: jest.fn(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// vehicleBanner.methods = {
|
|
||||||
// initializeComponent: jest.fn(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// funnelSubHeader.methods = {
|
|
||||||
// initializeComponent: jest.fn(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// funnelFooter.methods = {
|
|
||||||
// initializeComponent: jest.fn(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// customerQuestions.methods = {
|
|
||||||
// initializeComponent: jest.fn(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// addressQuestions.methods = {
|
|
||||||
// initializeComponent: jest.fn(),
|
|
||||||
// setupAddressLookup: jest.fn(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const mountOptions = getMountOptions(mountOptionsMockData);
|
|
||||||
// mountOptions['attachTo'] = document.body; // append wrapper to document.body to test DOM methods
|
|
||||||
|
|
||||||
// mountOptions.global.directives = {
|
|
||||||
// maska: maska
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const wrapper = mount(addressLookup, mountOptions);
|
|
||||||
|
|
||||||
// const funnelHeaderWrapper = wrapper.findComponent({ name: "funnelHeader" });
|
|
||||||
// funnelHeaderWrapper.vm.initializeComponent =
|
|
||||||
// funnelHeader.methods.initializeComponent;
|
|
||||||
|
|
||||||
// const vehicleBannerWrapper = wrapper.findComponent({ name: "vehicleBanner" });
|
|
||||||
// vehicleBannerWrapper.vm.initializeComponent =
|
|
||||||
// vehicleBanner.methods.initializeComponent;
|
|
||||||
|
|
||||||
// const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" });
|
|
||||||
// funnelSubHeaderWrapper.vm.initializeComponent =
|
|
||||||
// funnelSubHeader.methods.initializeComponent;
|
|
||||||
|
|
||||||
// const funnelFooterWrapper = wrapper.findComponent({ name: "funnelFooter" });
|
|
||||||
// funnelFooterWrapper.vm.initializeComponent =
|
|
||||||
// funnelFooter.methods.initializeComponent;
|
|
||||||
|
|
||||||
// const customerQuestionsWrapper = wrapper.findComponent({ name: "customerQuestions" });
|
|
||||||
// customerQuestionsWrapper.vm.initializeComponent =
|
|
||||||
// customerQuestions.methods.initializeComponent;
|
|
||||||
|
|
||||||
// const addressQuestionsWrapper = wrapper.findComponent({ name: "addressQuestions" });
|
|
||||||
// addressQuestionsWrapper.vm.initializeComponent =
|
|
||||||
// addressQuestions.methods.initializeComponent;
|
|
||||||
// addressQuestionsWrapper.vm.setupAddressLookup =
|
|
||||||
// addressQuestions.methods.setupAddressLookup;
|
|
||||||
|
|
||||||
// return { wrapper, apiPromise };
|
|
||||||
// }
|
|
||||||
|
|
@ -151,15 +151,15 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
attachCustomEvents() {
|
attachCustomEvents() {
|
||||||
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||||
this.pushEventToGA(
|
this.pushEventToGA(
|
||||||
this.$route.query[this.queryStrings.FMG_PAGE],
|
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||||
this.GaActions.SUBMITTED,
|
this.GaActions.SUBMITTED,
|
||||||
this.GaLabels.ADDRESS_LOOKUP,
|
this.GaLabels.ADDRESS_LOOKUP,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getRegistrationAddressFromStore() {
|
getRegistrationAddressFromStore() {
|
||||||
return store.getters.vehicle.registration.address;
|
return store.getters.vehicle.registration.address;
|
||||||
},
|
},
|
||||||
|
|
@ -207,7 +207,7 @@ export default {
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the neither the registration zip code or service zip code are not serviceable
|
// if the neither the registration zip code or service zip code are not serviceable
|
||||||
this.isZipServicable = serviceZipValidationResponse.data.isServiceable;
|
this.isZipServicable = serviceZipValidationResponse.data.isServiceable;
|
||||||
if (!this.isZipServicable) {
|
if (!this.isZipServicable) {
|
||||||
|
|
@ -368,22 +368,22 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.attachCustomEvents();
|
this.attachCustomEvents();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
AlertNonServiceableZipHeader(){
|
AlertNonServiceableZipHeader() {
|
||||||
const zipCode = this.serviceZipCode ? this.serviceZipCode : this.customerQuestions.addressQuestions.zipCode;
|
const zipCode = this.serviceZipCode ? this.serviceZipCode : this.customerQuestions.addressQuestions.zipCode;
|
||||||
const text = this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", zipCode);
|
const text = this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", zipCode);
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
AlertNonServiceableZipBody(){
|
AlertNonServiceableZipBody() {
|
||||||
return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText");
|
return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText");
|
||||||
},
|
},
|
||||||
AlertMatchedDifferentVehicleHeader(){
|
AlertMatchedDifferentVehicleHeader() {
|
||||||
const text = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:glassText}", getDamageString());
|
const text = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:glassText}", getDamageString());
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
AlertMatchedDifferentVehicleBody(){
|
AlertMatchedDifferentVehicleBody() {
|
||||||
|
|
||||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||||
const vinYmmExpected = `${store.getters.vehicle.year} ${store.getters.vehicle.make} ${store.getters.vehicle.model}`;
|
const vinYmmExpected = `${store.getters.vehicle.year} ${store.getters.vehicle.make} ${store.getters.vehicle.model}`;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,630 @@
|
||||||
|
// Components
|
||||||
|
import addressQuestions from "@/layouts/address-lookup/customer-questions/address-questions/address-questions";
|
||||||
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import { mount, shallowMount } from "@vue/test-utils";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
import { storeMutations } from "@/constants/store-mutations";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
|
let autocompleteElement;
|
||||||
|
describe("address-questions.vue", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
// Create the `addressField1` element (autocomplete's input)
|
||||||
|
autocompleteElement = document.createElement("input")
|
||||||
|
autocompleteElement.getPlace = jest.fn();
|
||||||
|
document.getElementById = jest.fn().mockReturnValue(autocompleteElement);
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("initial state", () => {
|
||||||
|
test("only street address field is shown", () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const streetAddressField = wrapper.findComponent({ ref: "autocomplete" });
|
||||||
|
const cityField = wrapper.findComponent({ ref: "city" });
|
||||||
|
const stateField = wrapper.findComponent({ ref: "state" });
|
||||||
|
const zipCodeField = wrapper.findComponent({ ref: "zipCode" });
|
||||||
|
|
||||||
|
expect(streetAddressField.exists()).toBe(true);
|
||||||
|
expect(streetAddressField.isVisible()).toBe(true);
|
||||||
|
expect(cityField.exists()).toBe(true);
|
||||||
|
expect(cityField.isVisible()).toBe(false);
|
||||||
|
expect(stateField.exists()).toBe(true);
|
||||||
|
expect(stateField.isVisible()).toBe(false);
|
||||||
|
expect(zipCodeField.exists()).toBe(true);
|
||||||
|
expect(zipCodeField.isVisible()).toBe(false);
|
||||||
|
|
||||||
|
const alerts = wrapper.findAllComponents(alert);
|
||||||
|
expect(alerts.length).toEqual(0);
|
||||||
|
})
|
||||||
|
|
||||||
|
test("Should render addressQuestions sub-components (textbox-questions and dropdown-questions)", async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const streetAddress = wrapper.findComponent({ ref: 'autocomplete' });
|
||||||
|
const city = wrapper.findComponent({ ref: 'city' });
|
||||||
|
const state = wrapper.findComponent({ ref: 'state' });
|
||||||
|
const zipCode = wrapper.findComponent({ ref: 'zipCode' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(streetAddress.exists()).toBe(true);
|
||||||
|
expect(city.exists()).toBe(true);
|
||||||
|
expect(state.exists()).toBe(true);
|
||||||
|
expect(zipCode.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Should set this.displayNoMatchWarning to false when it is set to true, if the model if prepopulated", async () => {
|
||||||
|
// Arrange
|
||||||
|
const newAddressModel = {
|
||||||
|
streetAddress: "foo",
|
||||||
|
city: "foo",
|
||||||
|
state: "foo",
|
||||||
|
zipCode: "55555",
|
||||||
|
};
|
||||||
|
const wrapper = shallowMount(addressQuestions, {
|
||||||
|
propsData: {
|
||||||
|
modelValue: newAddressModel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
displayNoMatchWarning: true
|
||||||
|
})
|
||||||
|
expect(wrapper.vm.displayNoMatchWarning).toBeTruthy();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.$options.watch.addressModel.handler.call(wrapper.vm, wrapper.vm.addressModel);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.displayNoMatchWarning).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Should it set this.showAddressFields to true when the model is prepopulated", async () => {
|
||||||
|
// Arrange
|
||||||
|
// Act
|
||||||
|
const newAddressModel = {
|
||||||
|
streetAddress: "foo",
|
||||||
|
city: "foo",
|
||||||
|
state: "foo",
|
||||||
|
zipCode: "55555",
|
||||||
|
};
|
||||||
|
const wrapper = shallowMount(addressQuestions, {
|
||||||
|
propsData: {
|
||||||
|
modelValue: newAddressModel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.setupAddressLookup();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.showAddressFields).toBe(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("happy paths", () => {
|
||||||
|
test("full street address is passed in => address fields are displayed", async () => {
|
||||||
|
// Arrange/Act
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
streetAddress: "12345 Test Road",
|
||||||
|
city: "Tests",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "12312"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const cityField = wrapper.findComponent({ ref: "city" });
|
||||||
|
const stateField = wrapper.findComponent({ ref: "state" });
|
||||||
|
const zipField = wrapper.findComponent({ ref: "zipCode" });
|
||||||
|
expect(cityField.exists()).toBeTruthy();
|
||||||
|
expect(cityField.isVisible()).toBeTruthy();
|
||||||
|
expect(stateField.exists()).toBeTruthy();
|
||||||
|
expect(cityField.isVisible()).toBeTruthy();
|
||||||
|
expect(zipField.exists()).toBeTruthy();
|
||||||
|
expect(cityField.isVisible()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("full street address is passed in => don't load Google Autocomplete script", async () => {
|
||||||
|
// Arrange/Act
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
streetAddress: "12345 Test Road",
|
||||||
|
city: "Tests",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "12312"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.$loadScript).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("address field is focused => disable autocomplete", async () => {
|
||||||
|
// Arrange
|
||||||
|
let focusEventCallbackFunction;
|
||||||
|
autocompleteElement.addEventListener = jest.fn().mockImplementation((eventName, callbackFunction) => {
|
||||||
|
if (eventName == "focus") {
|
||||||
|
focusEventCallbackFunction = callbackFunction;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
focusEventCallbackFunction();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(autocompleteElement.getAttribute("autocomplete")).toEqual("do-not-autofill");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("street address is entered, user chooses good result from autocomplete results => other fields are filled in", async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
await wrapper.setData({
|
||||||
|
addressModel: {
|
||||||
|
streetAddress: "123 Test Street"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedPlace = {
|
||||||
|
address_components: [
|
||||||
|
{
|
||||||
|
long_name: "1234",
|
||||||
|
short_name: "1234",
|
||||||
|
types: ["street_number"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Test Road",
|
||||||
|
short_name: "Test Road",
|
||||||
|
types: ["route"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "East Columbus",
|
||||||
|
short_name: "Columbus",
|
||||||
|
types: ["neighborhood", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Columbus",
|
||||||
|
short_name: "Columbus",
|
||||||
|
types: ["locality", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Franklin County",
|
||||||
|
short_name: "Franklin County",
|
||||||
|
types: ["administrative_area_level_2", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Ohio",
|
||||||
|
short_name: "OH",
|
||||||
|
types: ["administrative_area_level_1", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "United States",
|
||||||
|
short_name: "US",
|
||||||
|
types: ["country", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "43215",
|
||||||
|
short_name: "43215",
|
||||||
|
types: ["postal_code"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Act
|
||||||
|
autocompleteElement.dispatchEvent(new CustomEvent("place_changed", { detail: selectedPlace }));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const addressModel = wrapper.vm.addressModel;
|
||||||
|
expect(addressModel.streetAddress).toEqual("1234 Test Road");
|
||||||
|
expect(addressModel.city).toEqual("Columbus");
|
||||||
|
expect(addressModel.state).toEqual("OH");
|
||||||
|
expect(addressModel.zipCode).toEqual("43215");
|
||||||
|
})
|
||||||
|
|
||||||
|
test("street address is entered, user chooses good result from autocomplete results => alerts are cleared", async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
await wrapper.setData({
|
||||||
|
addressModel: {
|
||||||
|
streetAddress: "123 Test Street"
|
||||||
|
},
|
||||||
|
displayVerificationWarning: true,
|
||||||
|
displayNoMatchWarning: true
|
||||||
|
})
|
||||||
|
|
||||||
|
let alerts = wrapper.findAllComponents(alert);
|
||||||
|
alerts.forEach(alert => expect(alert.isVisible()).toBeTruthy());
|
||||||
|
|
||||||
|
const selectedPlace = {
|
||||||
|
address_components: [
|
||||||
|
{
|
||||||
|
long_name: "1234",
|
||||||
|
short_name: "1234",
|
||||||
|
types: ["street_number"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Test Road",
|
||||||
|
short_name: "Test Road",
|
||||||
|
types: ["route"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "East Columbus",
|
||||||
|
short_name: "Columbus",
|
||||||
|
types: ["neighborhood", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Columbus",
|
||||||
|
short_name: "Columbus",
|
||||||
|
types: ["locality", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Franklin County",
|
||||||
|
short_name: "Franklin County",
|
||||||
|
types: ["administrative_area_level_2", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Ohio",
|
||||||
|
short_name: "OH",
|
||||||
|
types: ["administrative_area_level_1", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "United States",
|
||||||
|
short_name: "US",
|
||||||
|
types: ["country", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "43215",
|
||||||
|
short_name: "43215",
|
||||||
|
types: ["postal_code"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Act
|
||||||
|
autocompleteElement.dispatchEvent(new CustomEvent("place_changed", { detail: selectedPlace }));
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
alerts = wrapper.findAllComponents(alert);
|
||||||
|
alerts.forEach(alert => expect(alert.exists()).toBeFalsy());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("street address is entered, but user clicks away => first result is selected and other fields are filled in", async () => {
|
||||||
|
// Arrange
|
||||||
|
let changeEventCallbackFunction;
|
||||||
|
autocompleteElement.addEventListener = jest.fn().mockImplementation((eventName, callbackFunction) => {
|
||||||
|
if (eventName == "change") {
|
||||||
|
changeEventCallbackFunction = callbackFunction;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
querySelectorFunction: function (query) {
|
||||||
|
if (query == ".pac-container .pac-item") {
|
||||||
|
let element = document.createElement("div");
|
||||||
|
element.textContent = "123 Test Street"
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
geocoderResult: {
|
||||||
|
address_components: [
|
||||||
|
{
|
||||||
|
long_name: "1234",
|
||||||
|
short_name: "1234",
|
||||||
|
types: ["street_number"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Test Road",
|
||||||
|
short_name: "Test Road",
|
||||||
|
types: ["route"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "East Columbus",
|
||||||
|
short_name: "Columbus",
|
||||||
|
types: ["neighborhood", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Columbus",
|
||||||
|
short_name: "Columbus",
|
||||||
|
types: ["locality", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Franklin County",
|
||||||
|
short_name: "Franklin County",
|
||||||
|
types: ["administrative_area_level_2", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "Ohio",
|
||||||
|
short_name: "OH",
|
||||||
|
types: ["administrative_area_level_1", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "United States",
|
||||||
|
short_name: "US",
|
||||||
|
types: ["country", "political"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
long_name: "43215",
|
||||||
|
short_name: "43215",
|
||||||
|
types: ["postal_code"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
let verificationAlert = wrapper.findComponent({ ref: "alertVerificationWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeFalsy();
|
||||||
|
expect(verificationAlert.exists()).toBeFalsy();
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
changeEventCallbackFunction();
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const addressModel = wrapper.vm.addressModel;
|
||||||
|
expect(addressModel.streetAddress).toEqual("1234 Test Road");
|
||||||
|
expect(addressModel.city).toEqual("Columbus");
|
||||||
|
expect(addressModel.state).toEqual("OH");
|
||||||
|
expect(addressModel.zipCode).toEqual("43215");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("alerts", () => {
|
||||||
|
const places = [null, { address_components: null }, undefined, {}];
|
||||||
|
test.each(places)("selected place/place properties is null => display verification alert", async (place) => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
await wrapper.setData({
|
||||||
|
addressModel: {
|
||||||
|
streetAddress: "123 Test Street"
|
||||||
|
},
|
||||||
|
displayVerificationWarning: true,
|
||||||
|
displayNoMatchWarning: true
|
||||||
|
})
|
||||||
|
|
||||||
|
let alerts = wrapper.findAllComponents(alert);
|
||||||
|
alerts.forEach(alert => expect(alert.isVisible()).toBeTruthy());
|
||||||
|
|
||||||
|
const selectedPlace = place;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
autocompleteElement.dispatchEvent(new CustomEvent("place_changed", { detail: selectedPlace }));
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const verificationAlert = wrapper.findComponent({ ref: "alertVerificationWarning" });
|
||||||
|
expect(verificationAlert.exists()).toBe(true);
|
||||||
|
expect(verificationAlert.isVisible()).toBe(true);
|
||||||
|
const noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("user enters address that yields no autocomplete results => show noMatch alert", async () => {
|
||||||
|
// Arrange
|
||||||
|
let changeEventCallbackFunction;
|
||||||
|
autocompleteElement.addEventListener = jest.fn().mockImplementation((eventName, callbackFunction) => {
|
||||||
|
if (eventName == "change") {
|
||||||
|
changeEventCallbackFunction = callbackFunction;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeFalsy();
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
changeEventCallbackFunction();
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.displayNoMatchWarning).toBeTruthy();
|
||||||
|
noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeTruthy();
|
||||||
|
expect(noMatchAlert.isVisible()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("user enters address that yields autocomplete results, but doesn't select => show verification alert", async () => {
|
||||||
|
// Arrange
|
||||||
|
let changeEventCallbackFunction;
|
||||||
|
autocompleteElement.addEventListener = jest.fn().mockImplementation((eventName, callbackFunction) => {
|
||||||
|
if (eventName == "change") {
|
||||||
|
changeEventCallbackFunction = callbackFunction;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
querySelectorFunction: function (query) {
|
||||||
|
if (query == ".pac-container .pac-item") {
|
||||||
|
let element = document.createElement("div");
|
||||||
|
element.textContent = "123 Test Street"
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
let verificationAlert = wrapper.findComponent({ ref: "alertVerificationWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeFalsy();
|
||||||
|
expect(verificationAlert.exists()).toBeFalsy();
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
changeEventCallbackFunction();
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
verificationAlert = wrapper.findComponent({ ref: "alertVerificationWarning" });
|
||||||
|
expect(wrapper.vm.displayVerificationWarning).toBeTruthy();
|
||||||
|
expect(verificationAlert.exists()).toBeTruthy();
|
||||||
|
expect(verificationAlert.isVisible()).toBeTruthy();
|
||||||
|
noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(wrapper.vm.displayNoMatchWarning).toBeFalsy();
|
||||||
|
expect(noMatchAlert.exists()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("noMatch alert is cleared on address change", () => {
|
||||||
|
test("user sees noMatch warning and enters city => noMatch warning is removed", async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
wrapper.setData({
|
||||||
|
displayNoMatchWarning: true
|
||||||
|
});
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeTruthy();
|
||||||
|
expect(noMatchAlert.isVisible()).toBeTruthy();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.$options.watch.addressModel.handler.call(wrapper.vm, {
|
||||||
|
city: "Somewhere"
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.displayNoMatchWarning).toBeFalsy();
|
||||||
|
noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("user sees noMatch warning and enters state => noMatch warning is removed", async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
wrapper.setData({
|
||||||
|
displayNoMatchWarning: true
|
||||||
|
});
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeTruthy();
|
||||||
|
expect(noMatchAlert.isVisible()).toBeTruthy();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.$options.watch.addressModel.handler.call(wrapper.vm, {
|
||||||
|
state: "KO"
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.displayNoMatchWarning).toBeFalsy();
|
||||||
|
noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("user sees noMatch warning and enters zip code => noMatch warning is removed", async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
wrapper.setData({
|
||||||
|
displayNoMatchWarning: true
|
||||||
|
});
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeTruthy();
|
||||||
|
expect(noMatchAlert.isVisible()).toBeTruthy();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.$options.watch.addressModel.handler.call(wrapper.vm, {
|
||||||
|
zipCode: "12345"
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.displayNoMatchWarning).toBeFalsy();
|
||||||
|
noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
|
||||||
|
expect(noMatchAlert.exists()).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupMocks({ mountOptions, props, isShallowMount = true, querySelectorFunction, geocoderResult = ["1234 Test Street"] }) {
|
||||||
|
store.commit(storeMutations.RESET_STATE);
|
||||||
|
|
||||||
|
const resultingMountOptions = getMountOptions({
|
||||||
|
...mountOptions,
|
||||||
|
router: {
|
||||||
|
navigate: jest.fn(),
|
||||||
|
navigateAfterSave: jest.fn()
|
||||||
|
},
|
||||||
|
loadScript: jest.fn().mockResolvedValue()
|
||||||
|
});
|
||||||
|
|
||||||
|
window.google = {
|
||||||
|
maps: {
|
||||||
|
event: {
|
||||||
|
addListener: jest.fn().mockImplementation((element, eventName, callbackFunction) => {
|
||||||
|
function interceptedCallbackFunction(e) {
|
||||||
|
callbackFunction(e.detail);
|
||||||
|
}
|
||||||
|
// selectedPlace = "Woogly";
|
||||||
|
element.addEventListener(eventName, interceptedCallbackFunction);
|
||||||
|
}),
|
||||||
|
removeListener: jest.fn(),
|
||||||
|
clearInstanceListeners: jest.fn()
|
||||||
|
},
|
||||||
|
places: {
|
||||||
|
Autocomplete: jest.fn().mockImplementation((el) => el)
|
||||||
|
},
|
||||||
|
Geocoder: class Geocoder {
|
||||||
|
// constructor();
|
||||||
|
|
||||||
|
geocode(request, callback) {
|
||||||
|
callback([geocoderResult], true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GeocoderStatus: {
|
||||||
|
OK: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (props)
|
||||||
|
resultingMountOptions.propsData = props;
|
||||||
|
|
||||||
|
const wrapper = isShallowMount ? shallowMount(addressQuestions, resultingMountOptions) : mount(addressQuestions, resultingMountOptions);
|
||||||
|
document.querySelector = jest.fn().mockImplementation(query => {
|
||||||
|
let result = null;
|
||||||
|
if (query == ".pac-container")
|
||||||
|
result = document.createElement("div");
|
||||||
|
else if (querySelectorFunction) {
|
||||||
|
result = querySelectorFunction(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result ?? null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
|
|
@ -185,11 +185,10 @@ export default ({
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setupAddressLookup() {
|
setupAddressLookup() {
|
||||||
|
if (this.addressModel.streetAddress &&
|
||||||
if (this.addressModel.streetAddress !== null &
|
this.addressModel.city &&
|
||||||
this.addressModel.city !== null &
|
this.addressModel.state &&
|
||||||
this.addressModel.state !== null &
|
this.addressModel.zipCode) {
|
||||||
this.addressModel.zipCode !== null) {
|
|
||||||
|
|
||||||
this.showAddressFields = true;
|
this.showAddressFields = true;
|
||||||
return;
|
return;
|
||||||
|
|
@ -215,12 +214,12 @@ export default ({
|
||||||
// Standard place_changed event handling
|
// Standard place_changed event handling
|
||||||
const autocompleteListener = window.google.maps.event.addListener(autocomplete, 'place_changed', fillInAddress);
|
const autocompleteListener = window.google.maps.event.addListener(autocomplete, 'place_changed', fillInAddress);
|
||||||
|
|
||||||
// Wrapping the addressField1 element in the Google Address Autocomplete object
|
// Wrapping the addressField1 element in the Google Address Autocomplete object
|
||||||
// will cause "autocomplete='off'" which Chrome completely ignores. This event
|
// will cause "autocomplete='off'" which Chrome completely ignores. This event
|
||||||
// handler will set the value to something arbitrary so autofill doesn't work.
|
// handler will set the value to something arbitrary so autofill doesn't work.
|
||||||
// https://stackoverflow.com/a/30976223
|
// https://stackoverflow.com/a/30976223
|
||||||
addressField1.addEventListener("focus", () => {
|
addressField1.addEventListener("focus", () => {
|
||||||
addressField1.setAttribute("autocomplete", "do-not-autofill");
|
addressField1.setAttribute("autocomplete", "do-not-autofill");
|
||||||
|
|
||||||
// Make place results box stick to the input on scroll
|
// Make place results box stick to the input on scroll
|
||||||
const streetAddressField = document.getElementById("streetAddressField");
|
const streetAddressField = document.getElementById("streetAddressField");
|
||||||
|
|
@ -228,10 +227,9 @@ export default ({
|
||||||
if (autocompleteResultsContainer) {
|
if (autocompleteResultsContainer) {
|
||||||
streetAddressField.appendChild(autocompleteResultsContainer);
|
streetAddressField.appendChild(autocompleteResultsContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
addressField1.onchange = function() {
|
addressField1.addEventListener("change", () => {
|
||||||
const hover = document.querySelector(".pac-container .pac-item:hover");
|
const hover = document.querySelector(".pac-container .pac-item:hover");
|
||||||
// if an item has been clicked, do nothing, otherwise get first solution and use Geocoder to get the place
|
// if an item has been clicked, do nothing, otherwise get first solution and use Geocoder to get the place
|
||||||
if (hover === null) {
|
if (hover === null) {
|
||||||
|
|
@ -258,7 +256,7 @@ export default ({
|
||||||
self.displayNoMatchWarning = true;
|
self.displayNoMatchWarning = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
function fillInAddress(place) {
|
function fillInAddress(place) {
|
||||||
if (!place) {
|
if (!place) {
|
||||||
|
|
@ -310,7 +308,6 @@ export default ({
|
||||||
addressField1.onchange = null;
|
addressField1.onchange = null;
|
||||||
const pacContainer = document.querySelector(".pac-container");
|
const pacContainer = document.querySelector(".pac-container");
|
||||||
pacContainer.remove();
|
pacContainer.remove();
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|
@ -325,16 +322,10 @@ export default ({
|
||||||
watch: {
|
watch: {
|
||||||
addressModel: {
|
addressModel: {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
// The first time the address model changes is w
|
// Clear no match warning on address change
|
||||||
if (!newValue.city &&
|
if (newValue.city || newValue.state || newValue.zipCode) {
|
||||||
!newValue.state &&
|
|
||||||
!newValue.zipCode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.displayNoMatchWarning === true) {
|
|
||||||
this.displayNoMatchWarning = false;
|
this.displayNoMatchWarning = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
|
||||||
|
|
||||||
|
const customerModel = {
|
||||||
|
addressQuestions: {
|
||||||
|
streetAddress: "",
|
||||||
|
city: "",
|
||||||
|
state: "",
|
||||||
|
zipCode: "",
|
||||||
|
},
|
||||||
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
|
emailAddress: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("customerQuestions.vue", () => {
|
||||||
|
|
||||||
|
it("Should render customerQuestions sub-components (addressQuestions, first name, last name, and email textbox-questions)", async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(customerQuestions);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const addressQuestions = wrapper.findComponent({ ref: 'addressQuestions' });
|
||||||
|
const firstName = wrapper.findComponent({ ref: 'firstName' });
|
||||||
|
const lastName = wrapper.findComponent({ ref: 'lastName' });
|
||||||
|
const emailAddress = wrapper.findComponent({ ref: 'emailAddress' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(addressQuestions.exists()).toBe(true);
|
||||||
|
expect(firstName.exists()).toBe(true);
|
||||||
|
expect(lastName.exists()).toBe(true);
|
||||||
|
expect(emailAddress.exists()).toBe(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<addressQuestions ref="addressQuestions" v-model="customerModel.addressQuestions" :alertNotifications="alertNotifications" />
|
<addressQuestions ref="addressQuestions" v-model="customerModel.addressQuestions" />
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
|
|
|
||||||
|
|
@ -1 +1,112 @@
|
||||||
test.todo("some test to be written in the future");
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import vinLookup from "./vin-lookup.vue";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
|
jest.mock("@/store", () => ({
|
||||||
|
commit: jest.fn(),
|
||||||
|
dispatch: jest.fn(),
|
||||||
|
getters: {
|
||||||
|
vehicle: {
|
||||||
|
year: 2019,
|
||||||
|
carId: 'initial carId'
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
serviceLocation: {
|
||||||
|
zipCode: "45253"
|
||||||
|
},
|
||||||
|
customer: {
|
||||||
|
emailAddress: "builddigitaltest@safelite.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
insuranceCoverage: {
|
||||||
|
isVerified: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
glassToReplace: "windshield"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
import { getDamageString, getIsWindshieldOnly,isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
||||||
|
|
||||||
|
jest.mock("@/helpers/damage-helper", () => ({
|
||||||
|
isGlassAvailableForCarId: jest.fn(() => {
|
||||||
|
return Promise.resolve();
|
||||||
|
}),
|
||||||
|
getIsWindshieldOnly: jest.fn(),
|
||||||
|
getDamageString: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
describe("vin-lookup.vue", () => {
|
||||||
|
it("Should update the funnel-footer forward button when VIN is changed", (done) => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({ });
|
||||||
|
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||||
|
//Act
|
||||||
|
wrapper.setData({vin: "newValue"});
|
||||||
|
//Assert
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toBeCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should call navigateForward() if the store carId matches the vin response carId and forward button is clicked", async () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({ });
|
||||||
|
const zipValidationApiResponse = {
|
||||||
|
data: {
|
||||||
|
isServiceable: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const vehicleLookupApiResponse = {
|
||||||
|
data: {
|
||||||
|
carId: 'initial carId'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const zipPromise = Promise.resolve(zipValidationApiResponse);
|
||||||
|
const vinPromise = Promise.resolve(vehicleLookupApiResponse);
|
||||||
|
|
||||||
|
wrapper.vm.validateZip = jest.fn().mockImplementation(() => zipPromise);
|
||||||
|
wrapper.vm.lookupVehicle = jest.fn().mockImplementation(() => vinPromise);
|
||||||
|
|
||||||
|
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||||
|
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
||||||
|
wrapper.vm.navigateForward = jest.fn();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function setupMocks({ customMountOptions }) {
|
||||||
|
|
||||||
|
|
||||||
|
const mountOptions = getMountOptions({});
|
||||||
|
|
||||||
|
const finalMountOptions = Object.assign(mountOptions, customMountOptions);
|
||||||
|
// Modify/augment default mount options
|
||||||
|
finalMountOptions.global.mocks["$store"] = store;
|
||||||
|
finalMountOptions.global.mixins = [mockMixin];
|
||||||
|
finalMountOptions['attachTo'] = document.body; // append wrapper to document.body to test DOM methods
|
||||||
|
|
||||||
|
const wrapper = shallowMount(vinLookup, finalMountOptions);
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockMixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn(() => "placeholder CMS content"),
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue