DigitalConsumer.FixMyGlass/src/layouts/vehicle-damage/vehicle-damage.spec.js

792 lines
25 KiB
JavaScript

// Components
import vehicleDamage from "@/layouts/vehicle-damage/vehicle-damage.vue";
import sideDoorOptions from "@/layouts/vehicle-damage/side-door-options/side-door-options";
import damageLocationQuestion from "@/layouts/vehicle-damage/damage-location-question/damage-location-question";
import windshieldOptions from "@/layouts/vehicle-damage/windshield-options/windshield-options";
import replaceOptionsQuestion from "@/layouts/vehicle-damage/replace-options-question/replace-options-question";
// Supporting Files
import { settleAllPromises } from "@/helpers/layout-helper.js";
import baseMixin from "@/mixins/base-mixin";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { nextTick } from "vue";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
import { validate } from "vee-validate";
import { damageLocationsSelected } from "@/constants/damage-locations-selected.js";
import { routerParams } from "@/router/router-constants/router-params";
import * as cookieHelper from "@/helpers/heritage-integration/cookie-helper";
// 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(),
}));
// Mock getFunnelCookie
jest.mock("@/helpers/heritage-integration/cookie-helper", () => ({
getFunnelCookie: jest.fn(),
}));
// Mock Store
jest.mock("@/store", () => ({
commit: jest.fn(),
dispatch: jest.fn(),
getters: {
vehicle: {
carId: "C00000000",
image: "test.jpg",
payment: {
insuranceCoverage: {
isVerified: false
}
}
},
eventBusItem: jest.fn(),
damage: {
glassToReplace: []
},
},
}));
describe("vehicle-damage.vue", () => {
describe("navigation", () => {
test("BackButtonAction triggers a router.navigateWithoutSaving change", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.backButtonAction();
//Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
});
test("Replace several pieces of glass on ForwardButtonAction triggers a router.navigate and saves selections to store", async () => {
//Arrange
const partsData = {
partsOrQuestions: [{
name: "Single",
location: "Windshield",
parts: null,
partQuestions: [{
questionSequence: 1,
questionText: "Is your vehicle equipped with a heated steering wheel?",
answers: [{
answerText: "Yes",
nextQuestionSequence: null,
answerResult: "FW04957"
},
{
answerText: "No",
nextQuestionSequence: 2,
answerResult: ""
}]
},
{
questionSequence: 2,
questionText: "Is your vehicle equipped with a remote start?",
answers: [{
answerText: "Yes",
nextQuestionSequence: null,
answerResult: "FW04181"
},
{
answerText: "No",
nextQuestionSequence: null,
answerResult: "FW04179"
}]
}]
}]
};
const { wrapper } = setupMocks({
pageHeaderWidgetHeaderText: "",
mountOptionsMockData: {
router: { navigate: jest.fn(), navigateWithSaving: jest.fn(), },
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
store: {
getters: {
vehicle: {},
payment: { insuranceCoverage: { isVerified: false } },
},
},
},
});
wrapper.vm.selectedDamageLocations = ["Windshield", "SideDoor", "RearWindow"];
wrapper.vm.selectedWindshieldOptions = {
selectedWindshieldChipCount: null,
selectedWindshieldReplaceOptions: ["Single"],
selectedWindshieldDamageType: "Replace"
};
wrapper.vm.sideDoorOptionsData = {
selectedDoorSides: ["DriverSide", "PassengerSide"],
selectedDriverSideReplaceOptions: ["Back"],
selectedPassengerSideReplaceOptions: ["Quarter"]
};
wrapper.vm.selectedRearReplaceOptions = ["Stationary"];
const expectedGlassToReplace = [{ location: "Windshield", name: "Single" }, { location: "Driver", name: "Back" },
{ location: "Passenger", name: "Quarter" }, { location: "Rear", name: "Stationary" }];
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(storeActions.GET_DAMAGE_OPTIONS, {"carId": "C00000000"});
});
test("Windshield replace with multiple parts on ForwardButtonAction triggers a router.navigate and saves selections to store", async () => {
//Arrange
const partsData = {
partsOrQuestions: [
{
location: "Windshield",
name: "Single",
partQuestions: null,
parts: [
{
color: "Green Tint, Green Shade",
description: "rain sensor, solar",
partNumber: "FW02728GGYN",
requiresCapabilityQuestions: false,
requiresRecalibration: false
},
{
color: "Green Tint, Green Shade",
description: "rain sensor, solar, hydrophobic coating",
partNumber: "FW02760GGYN",
requiresCapabilityQuestions: false,
requiresRecalibration: false
}
]
},
{
name: "Stationary",
location: "Rear",
parts: [
{
partNumber: "DB09626GTYN",
description: "heated glass, solar, antenna",
color: "Green Tint",
requiresRecalibration: false,
requiresCapabilityQuestions: false,
childParts: null
},
{
partNumber: "DB09821GTYN",
description: "heated glass, solar, antenna, onstar",
color: "Green Tint",
requiresRecalibration: false,
requiresCapabilityQuestions: false,
childParts: null
}
],
"partQuestions": null
}
]
};
const { wrapper } = setupMocks({
pageHeaderWidgetHeaderText: "",
mountOptionsMockData: {
router: { navigate: jest.fn(), navigateWithSaving: jest.fn(), },
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
store: {
getters: {
vehicle: {},
payment: { insuranceCoverage: { isVerified: false } },
},
},
},
});
wrapper.vm.selectedDamageLocations = ["Windshield"];
wrapper.vm.selectedWindshieldOptions = {
selectedWindshieldChipCount: null,
selectedWindshieldReplaceOptions: ["Single"],
selectedWindshieldDamageType: "Replace"
};
const expectedGlassToReplace = [{ location: "Windshield", name: "Single" },];
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(storeActions.GET_DAMAGE_OPTIONS, {"carId": "C00000000"});
});
});
describe("alert", () => {
test("when displayVehicleChangeAlert router params is true, the alert: 'vehicleChangeAlert' should be rendered", () => {
// Arrange & Act
const { wrapper } = setupMocks({
mountOptionsMockData: {
route: {
params: {
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true
}
}
}
});
// Assert
expect(wrapper.findComponent({ ref: 'vehicleChangeAlert' }).exists()).toBe(true);
});
test("when displayVehicleChangeAlert router params is false, the alert: 'vehicleChangeAlert' should not be rendered", () => {
// Arrange & Act
const { wrapper } = setupMocks({
mountOptionsMockData: {
route: {
params: {
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false
}
}
}
});
// Assert
expect(wrapper.findComponent({ ref: 'vehicleChangeAlert' }).exists()).toBe(false);
});
test("when displayVehicleChangeAlert router params is undefined, the alert: 'vehicleChangeAlert' should not be rendered", () => {
// Arrange & Act
const { wrapper } = setupMocks({
mountOptionsMockData: {
route: {
params: {
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: undefined
}
}
}
});
// Assert
expect(wrapper.findComponent({ ref: 'vehicleChangeAlert' }).exists()).toBe(false);
})
});
describe("glass selections and corresponding variables", () => {
test("isWindshieldDamageLocation is true when windshield is selected", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.selectedDamageLocations = ["Windshield"];
//Assert
expect(wrapper.vm.isWindshieldDamageLocation).toEqual(true);
});
test("isSideDoorDamageLocation is true Side door is selected", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.selectedDamageLocations = ["Sidedoor"];
//Assert
expect(wrapper.vm.isSideDoorDamageLocation).toEqual(true);
});
test("isRearWindowDamageLocation is true if Rear Window damage is selected", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.selectedDamageLocations = ["RearWindow"];
//Assert
expect(wrapper.vm.isRearWindowDamageLocation).toEqual(true);
});
test("isWindshieldRepair is true if windshield repair is selected", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.selectedDamageLocations = ["Windshield"];
wrapper.vm.selectedWindshieldOptions = { selectedWindshieldDamageType: "Repair" };
//Assert
expect(wrapper.vm.isWindshieldRepair).toEqual(true);
});
test("isWindshieldRepair is false if windshield damage is not selected", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.selectedDamageLocations = ["SideDoor"];
wrapper.vm.selectedWindshieldOptions = { selectedWindshieldDamageType: "Repair" };
//Assert
expect(wrapper.vm.isWindshieldRepair).toEqual(false);
});
test("isDriverSideReplace is true if side door driver is selected", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.selectedDamageLocations = ["Sidedoor"];
wrapper.vm.sideDoorOptionsData = { selectedDoorSides: ["DriverSide"] };
//Assert
expect(wrapper.vm.isDriverSideReplace).toEqual(true);
});
test("isPassengerSideReplace is true if side door passenger selected", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.selectedDamageLocations = ["Sidedoor"];
wrapper.vm.sideDoorOptionsData = { selectedDoorSides: ["PassengerSide"] };
//Assert
expect(wrapper.vm.isPassengerSideReplace).toEqual(true);
});
});
describe("state validations", () => {
test("CarId set, arePagePrerequisitesValid should be true ", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
await nextTick();
//Assert
expect(arePagePrerequisitesValid).toBe(true);
});
});
describe("input validations", () => {
// THE FOLLOWING TEST IS NOT NECESSARILY REQUIRED FOR COVERAGE
// BUT KEEP FOR AN EXAMPLE OF A VALIDATION TEST
test("when validation rules are set they should validate correctly", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
const testNull = validate("", "replace-options-required");
const testString = validate("sldfj", "replace-options-required");
//Assert
testNull.then(function (data) {
expect(data.valid).toEqual(false);
});
testString.then(function (data) {
expect(data.valid).toEqual(true);
});
});
});
describe("get glass options from store", () => {
const damageLocations = [["Windshield", [damageLocationsSelected.WINDSHIELD]],
["Driver", [damageLocationsSelected.SIDEDOOR]],
["Passenger", [damageLocationsSelected.SIDEDOOR]],
["Rear", [damageLocationsSelected.REARWINDOW]]];
test.each(damageLocations)("getDamageLocationsFromStore for %s returns expected %s", async (damageLocation, expectedGlass) => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ location: damageLocation }] }, isRepair: true };
var glassSelections = wrapper.vm.getDamageLocationsFromStore();
//Assert
expect(glassSelections).toEqual(expectedGlass);
});
const storeWindshieldOptions = [[1, false, "Windshield", "Single", {
selectedWindshieldDamageType: damageLocationsSelected.REPLACE,
selectedWindshieldChipCount: [], selectedWindshieldReplaceOptions: [damageLocationsSelected.SINGLE]
}],
[2, false, "Windshield", "Driver", {
selectedWindshieldDamageType: damageLocationsSelected.REPLACE,
selectedWindshieldChipCount: [], selectedWindshieldReplaceOptions: [damageLocationsSelected.DRIVER]
}],
[3, false, "Windshield", "Passenger", {
selectedWindshieldDamageType: damageLocationsSelected.REPLACE,
selectedWindshieldChipCount: [], selectedWindshieldReplaceOptions: [damageLocationsSelected.PASSENGER]
}],
[4, true, "", "", {
selectedWindshieldDamageType: damageLocationsSelected.REPAIR,
selectedWindshieldChipCount: [2], selectedWindshieldReplaceOptions: []
}]
];
test.each(storeWindshieldOptions)("getWindshieldOptionsFromStore test #%s", async (testNum, isRepair, damageLocation, damageName, expectedWindshieldOptions) => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
store.getters = {
vehicle:
{ carId: "C0000000" },
eventBusItem: jest.fn(),
damage:
{
glassToReplace: [{ location: damageLocation, name: damageName }],
isRepair: isRepair,
numberOfChips: 2
},
};
var windshieldSelections = wrapper.vm.getWindshieldOptionsFromStore();
//Assert
expect(windshieldSelections).toEqual(expectedWindshieldOptions);
});
const driverDoorSides = [["Driver", "Front", [damageLocationsSelected.FRONT]],
["Driver", "Back", [damageLocationsSelected.BACK]],
["Driver", "Vent", [damageLocationsSelected.VENT]],
["Driver", "Quarter", [damageLocationsSelected.QUARTER]]
];
test.each(driverDoorSides)("getDriverSideReplaceOptionsFromStore for %s-%s returns expected %s", async (damageLocation, damageName, expectedGlass) => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ location: damageLocation, name: damageName }] }, isRepair: true };
var glassSelections = wrapper.vm.getDriverSideReplaceOptionsFromStore();
//Assert
expect(glassSelections).toEqual(expectedGlass);
});
const passengerDoorSides = [["Passenger", "Front", [damageLocationsSelected.FRONT]],
["Passenger", "Back", [damageLocationsSelected.BACK]],
["Passenger", "Vent", [damageLocationsSelected.VENT]],
["Passenger", "Quarter", [damageLocationsSelected.QUARTER]]
];
test.each(passengerDoorSides)("getPassengerSideReplaceOptionsFromStore for %s-%s returns expected %s", async (damageLocation, damageName, expectedGlass) => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ location: damageLocation, name: damageName }] }, isRepair: true };
var glassSelections = wrapper.vm.getPassengerSideReplaceOptionsFromStore();
//Assert
expect(glassSelections).toEqual(expectedGlass);
});
const rearReplaceOptions = [["Rear", "Stationary", [damageLocationsSelected.STATIONARY]],
["Rear", "Slider", [damageLocationsSelected.SLIDER]]
];
test.each(rearReplaceOptions)("getRearReplaceOptionsFromStore for %s-%s returns expected %s", async (damageLocation, damageName, expectedGlass) => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ location: damageLocation, name: damageName }] }, isRepair: true };
var glassSelections = wrapper.vm.getRearReplaceOptionsFromStore();
//Assert
expect(glassSelections).toEqual(expectedGlass);
});
})
describe("hide back button", () => {
test("if claim registration is delayed => should hide back button", () => {
// Arrange
const { wrapper } = setupMocks({
funnelCookie: {
HasDelayedClaimRegistration: true
}
});
// Assert
expect(wrapper.vm.shouldHideBackButton).toBe(true);
});
test("if claim is verified => should hide back button", () => {
// Arrange
const { wrapper } = setupMocks({
mountOptionsMockData: {
router: { navigate: jest.fn(), },
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: {}, },],
store: {
getters: {
vehicle: {},
payment: { insuranceCoverage: { isVerified: true } },
},
},
},
})
// Assert
expect(wrapper.vm.shouldHideBackButton).toBe(true);
})
test("if claim isn't verified yet => allow user to go back", () => {
// Arrange
const { wrapper } = setupMocks({});
// Assert
expect(wrapper.vm.shouldHideBackButton).toBeFalsy();
})
});
});
function setupMocks({ pageHeaderWidgetHeaderText, mountOptionsMockData, funnelCookie = {} }) {
var pageHeaderWidgetHeaderTextDefault = {};
var mountOptionsMockDataDefault = {
router: {
navigate: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithSaving: jest.fn(),
},
route: {
params: {
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false
}
},
store: {
getters: {
vehicle: {},
payment: {
insuranceCoverage: {
isVerified: false
}
},
},
},
};
// Combine parameters with default values
pageHeaderWidgetHeaderText = Object.assign(pageHeaderWidgetHeaderTextDefault, pageHeaderWidgetHeaderText);
mountOptionsMockData = Object.assign(mountOptionsMockDataDefault, mountOptionsMockData);
//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",
},
},
damageOptions: {
driverSideOptions: {
availableReplacementOptions: ["Front", "Back", "Side"],
},
passengerSideOptions: {
availableReplacementOptions: ["Front", "Back", "Side"],
},
windshieldOptions: {
availableReplacementOptions: ["Single", "Driver", "Passenger"],
},
backGlassOptions: {
availableReplacementOptions: ["Front", "Back", "Side"],
},
},
};
const apiPromise = Promise.resolve(apiResponses);
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
cookieHelper.getFunnelCookie = jest.spyOn(cookieHelper, "getFunnelCookie").mockReturnValue(funnelCookie);
//Mock damage initialize methods
damageLocationQuestion.methods = {
initializeComponent: jest.fn(),
};
sideDoorOptions.methods = {
initializeComponent: jest.fn(),
};
windshieldOptions.methods = {
initializeComponent: jest.fn(),
};
replaceOptionsQuestion.methods = {
initializeComponent: jest.fn(),
updateSelectedValues: jest.fn(),
};
const mountOptions = getMountOptions(mountOptionsMockData);
mountOptions['attachTo'] = document.body; // append wrapper to document.body to test DOM methods
const wrapper = shallowMount(vehicleDamage, mountOptions);
const sideDoorOptionsWrapper = wrapper.findComponent({ name: "sideDoorOptions" });
sideDoorOptionsWrapper.vm.initializeComponent =
sideDoorOptions.methods.initializeComponent;
const windshieldOptionsWrapper = wrapper.findComponent({ name: "windshieldOptions" });
windshieldOptionsWrapper.vm.initializeComponent =
windshieldOptions.methods.initializeComponent;
const backGlassOptionsWrapper = wrapper.findComponent({ name: "replaceOptionsQuestion" });
backGlassOptionsWrapper.vm.initializeComponent =
replaceOptionsQuestion.methods.initializeComponent;
const damageLocationQuestionWrapper = wrapper.findComponent({ name: "damageLocationQuestion" });
damageLocationQuestionWrapper.vm.initializeComponent =
damageLocationQuestion.methods.initializeComponent;
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
return { wrapper, apiPromise };
}