DigitalConsumer.FixMyGlass/src/layouts/vin-lookup/vin-lookup.spec.js
Chloe Herd 2f12354ff2 Reapply "Unit tests"
This reverts commit ec782996df.
2025-05-13 16:36:32 -04:00

408 lines
13 KiB
JavaScript

import { shallowMount } from "@vue/test-utils";
import vinLookup from "./vin-lookup.vue";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { navigationScenarios } from "@/router/constants/navigation-scenarios.js";
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { experimentSettings } from "@/constants/experiments";
import store from "@/store";
jest.mock("@/store", () => ({
commit: jest.fn(),
dispatch: jest.fn(),
getters: {
vehicle: {
year: 2019,
carId: "C00000",
},
order: {
serviceLocation: {
zipCode: "45253",
},
customer: {
emailAddress: "builddigitaltest@safelite.com",
},
referralNumber: "666666",
},
payment: {
insuranceCoverage: {
isVerified: true,
},
},
damage: {
glassToReplace: "windshield",
},
isHeavyTruckVehicle: true,
},
}));
// Mock our module for promises.
jest.mock("@/helpers/layout-helper.js", () => ({
settleAllPromises: jest.fn(),
}));
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 nav-bar forward button when VIN is changed", (done) => {
//Arrange
const { wrapper } = setupMocks({});
//Act
wrapper.setData({ vin: "newValue" });
//Assert
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$refs.navbar.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({});
mockOutPromises({ carId: "C00000" });
wrapper.vm.navigateForward = jest.fn();
// Act
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
});
it("Should not call navigateForward() if the store carId does not match the vin response carId and forward button is clicked", async () => {
// Arrange
const { wrapper } = setupMocks({});
mockOutPromises({ carId: "C11111" });
wrapper.vm.vinTouched = true;
wrapper.vm.vin = "";
wrapper.vm.initialVin = "foo";
wrapper.vm.navigateForward = jest.fn();
// Act
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.navigateForward).not.toHaveBeenCalled();
});
it("Should call navigateForward() if the store carId does not match the vin response carId but does match previously enterted carId and forward button is clicked", async () => {
// Arrange
const { wrapper } = setupMocks({});
mockOutPromises({ carId: "C11111" });
wrapper.vm.lookupVehicle = jest.fn().mockImplementation(() => vinPromise);
wrapper.vm.navigateForward = jest.fn();
wrapper.vm.previouslyEnteredCarId = "C11111";
// Act
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
});
it("Should not call navigateForward() if zip service returns a non-serviceable flag", async () => {
// Arrange
const { wrapper } = setupMocks({});
const zipValidationApiResponse = {
data: {
isServiceable: false,
},
};
const zipPromise = Promise.resolve(zipValidationApiResponse);
wrapper.vm.validateZip = jest.fn().mockImplementation(() => zipPromise);
wrapper.vm.setupUiForNonServiceableZip = jest.fn();
wrapper.vm.navigateForward = jest.fn();
wrapper.vm.previouslyEnteredCarId = "new carId";
// Act
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.navigateForward).not.toHaveBeenCalled();
});
it("Should not call navigateForward() when forward button is clicked but lookupVehicle errors out.", async () => {
// Arrange
const { wrapper } = setupMocks({});
wrapper.vm.vinTouched = true;
wrapper.vm.vin = "foo";
wrapper.vm.initialVin = "!foo";
wrapper.vm.navigateForward = jest.fn();
wrapper.vm.previouslyEnteredCarId = "new carId";
// Act
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.navigateForward).not.toHaveBeenCalled();
});
describe("navigateForward", () => {
test("carId is different from returned vehicle and selected glass isn't available => continue with different glass", async () => {
// Arrange
const { wrapper } = setupMocks({
customMountOptions: {
router: {
navigateWithSaving: jest.fn(),
},
},
});
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
wrapper.setData({
isCarIdDifferent: true,
isSelectedGlassAvailableForVehicle: false,
});
// Act
await wrapper.vm.navigateForward();
//Assert
expect(wrapper.vm.$router.navigateWithSaving).toBeCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
wrapper.vm.$route,
expect.anything(),
expect.anything()
);
});
test("carId matches => navigateForwardWithSingleCarMatch", async () => {
// Arrange
const { wrapper } = setupMocks({});
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
wrapper.setData({
isCarIdDifferent: false,
});
// Act
await wrapper.vm.navigateForward();
//Assert
expect(wrapper.vm.navigateForwardWithSingleCarMatch).toBeCalledTimes(1);
});
test("selected glass is available for returned vehicle => navigateForwardWithSingleCarMatch", async () => {
// Arrange
const { wrapper } = setupMocks({});
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
wrapper.setData({
isSelectedGlassAvailableForVehicle: true,
});
// Act
await wrapper.vm.navigateForward();
//Assert
expect(wrapper.vm.navigateForwardWithSingleCarMatch).toBeCalledTimes(1);
});
});
describe("alerts", () => {
test("Zip is invalid => show AlertInvalidZipWidget", async () => {
// Arrange
const { wrapper } = setupMocks({});
mockOutPromises({ isZipValid: false });
await wrapper.setData({ serviceZipCode: "11111" });
// Act
await wrapper.vm.forwardButtonAction();
// Assert
expect(wrapper.vm.displayInvalidZipAlert).toEqual(true);
expect(wrapper.findComponent({ ref: "alertInvalidZip" }).exists()).toBe(true);
});
test("alerts are displayed and continue button is clicked with issues fixed => alerts are reset", async () => {
// Arrange
const { wrapper } = setupMocks({});
mockOutPromises({ isZipValid: true, isZipServiceable: true, carId: "CARID" });
await wrapper.setData({
displayInvalidZipAlert: true,
displayMatchedDifferentVehicleAlert: true,
displayNonServiceableZipAlert: true,
displayVinNotFoundAlert: true,
});
// sanity check that there are alerts
expect(wrapper.findAllComponents({ name: "alert" }).length).toBe(4);
// Act
wrapper.vm.forwardButtonAction();
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.findAllComponents({ name: "alert" }).length).toBe(0);
});
test("Error emitted by textbox-question element => VinScanFailed alert shown.", async () => {
// Arrange
const { wrapper } = setupMocks({});
// Act
const vinLookup = wrapper.findComponent('[data-test="vin-lookup-component"]');
vinLookup.trigger("imageLookupError");
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.findAllComponents({ name: "alert" }).length).toBe(1);
});
test("should hide the AlertNoService when displayNoServiceAlert is false", async () => {
const { wrapper } = setupMocks({
isZipServiceable: true,
displayNoServiceAlert: false,
lookupVinbyAddressResponse: {
isStatePermissible: true,
vinVehicles: [], // Return no vehicles
},
});
// Ensure displayNoServiceAlert is false
await wrapper.setData({ displayNoServiceAlert: false });
await wrapper.vm.forwardButtonAction();
// Check if the AlertNoService component is not rendered
const alertNoService = wrapper.findComponent({ ref: "AlertNoService" });
expect(alertNoService.exists()).toBe(false);
});
});
describe("getVinFromImage", () => {
test("GetVinFromImage resolves with first valid VIN when any vins are returned.", async () => {
// Arrange
const responseValue = "testResponse";
const lookup = jest.fn().mockImplementation(() => {
return new Promise((resolve, reject) => resolve([responseValue]));
});
const image = {};
const storeMixin = {
methods: {
dispatchStoreAction: lookup,
},
};
const { wrapper } = setupMocks({
mixins: [storeMixin],
});
// Act
const response = await wrapper.vm.getVinFromImage(image);
// Assert
expect(lookup).toHaveBeenCalled();
expect(response).toEqual(responseValue);
});
test("GetVinFromImage rejects if no vins are returned.", async () => {
// Arrange
const lookup = jest.fn().mockImplementation(() => {
return new Promise((resolve, reject) => resolve([]));
});
const image = {};
const storeMixin = {
methods: {
dispatchStoreAction: lookup,
},
};
const { wrapper } = setupMocks({
mixins: [storeMixin],
});
// Act
const promise = wrapper.vm.getVinFromImage(image);
// Assert
await expect(promise).rejects.toEqual("No VINs detected.");
});
test("GetVinFromImage rejects if an error occurs.", async () => {
const lookup = jest.fn().mockImplementation(() => {
return new Promise((resolve, reject) => reject());
});
const image = {};
const storeMixin = {
methods: {
dispatchStoreAction: lookup,
},
};
const { wrapper } = setupMocks({
mixins: [storeMixin],
});
// Act
const promise = wrapper.vm.getVinFromImage(image);
// Assert
await expect(promise).rejects.toEqual("An error occurred during the lookup.");
});
});
});
function setupMocks({ customMountOptions }) {
const mountOptions = getMountOptions({
...customMountOptions,
});
// Modify/augment default mount options
mountOptions.global.mocks["$store"] = store;
mountOptions.global.mixins = [mockMixin];
mountOptions["attachTo"] = document.body; // append wrapper to document.body to test DOM methods
mountOptions.route = { query: {} };
const wrapper = shallowMount(vinLookup, mountOptions);
mockOutStubFunctions(wrapper);
return { wrapper };
}
function mockOutPromises({ carId, isZipValid = true, isZipServiceable = true }) {
const apiResponses = {
vehicleLookupResponse: {
carId: carId,
},
zipCodeData: {
isValid: isZipValid,
isServiceable: isZipServiceable,
state: "OH",
},
};
settleAllPromises.mockImplementation(() => apiResponses);
}
function mockOutStubFunctions(wrapper) {
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
wrapper.vm.getZipCodeData = jest
.fn()
.mockReturnValue({ isValid: true, isServiceable: true, state: "OH" });
}
const mockMixin = {
methods: {
getCmsContent: jest.fn(() => "placeholder CMS content"),
getSettingValue: jest.fn((settingName) => {
if (settingName === experimentSettings.IS_EMAIL_OPTIONAL) {
return "true";
}
return "false";
}),
},
};