DigitalConsumer.ISS/src/layouts/vin-lookup/vin-lookup.spec.js
Bill Richardson c85ec1e09e remove vehicle banner from tests and snapshots
for pages i have done
2025-12-03 14:13:55 -05:00

605 lines
24 KiB
JavaScript

/* eslint-env jest */
import '@testing-library/jest-dom';
import { flushPromises } from '@vue/test-utils';
import { render, waitFor } from '@testing-library/vue';
import baseMixin from '@/mixins/base-mixin';
import { createTestingPinia } from '@pinia/testing';
import userEvent from '@testing-library/user-event';
import errorMessages from '@/constants/error-messages';
import issPageValues from '@/router/router-constants/issPage-values';
import queryStrings from '@/constants/query-strings';
import { GaActions } from '@/constants/analytics';
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
import routerParams from '@/router/router-constants/router-params';
import { useMainStore } from '@/store';
import VinLookupComponent from '@/layouts/vin-lookup/vin-lookup.vue';
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
const continueButtonQuerySelector = '[data-test-id="site-footer-main-button"]';
const errorMessageWrapperElSelector = '#vin-question-wrapper .form-test-error';
const vinInputSelector = '#vin-question';
const mockValidVin = '12345678901234567';
const mockCarId = 'Mock Car Id';
const lookupVehicleByVin = {
methodName: 'lookupVehicleByVin',
mockResponse: {
data: {
carId: mockCarId,
canSafeliteService: true
}
}
};
const lookupVehicleByVinCannotService = {
methodName: 'lookupVehicleByVin',
mockResponse: {
data: {
carId: mockCarId,
isBigTruck: true,
canSafeliteService: false
}
}
};
const lookupVehicleByVinError = {
methodName: 'lookupVehicleByVin',
mockResponse: {
data: {
error: true
}
}
};
const getPartsOrQuestions = {
methodName: 'getPartsOrQuestions',
mockResponse: null
};
const vehicleWithPartQuestionsMockResponse = {
data: {
partsOrQuestions: [
{
partQuestions: [
{
id: 1
}
]
}
]
}
};
const vehicleWithMultiplePartsMockResponse = {
data: {
partsOrQuestions: [
{
parts: [
{
id: 1
},
{
id: 2
}
]
}
]
}
};
const vehicleWithMoldingQuestionsMockResponse = {
data: {
partsOrQuestions: [
{
parts: [
{
childPartQuestions: [
{
id: 1
}
]
}
]
}
]
}
};
const vehicleWithCapabilityQuestionsMockResponse = {
data: {
partsOrQuestions: [
{
parts: [
{
requiresCapabilityQuestions: true,
partNumber: 1
}
]
}
]
}
};
const vehicleWithNoAdditionalPartsOrQuestionsMockResponse = {
data: {
partsOrQuestions: [
{
parts: [
{
childPartQuestions: [],
requiresCapabilityQuestions: false
}
]
}
],
partQuestions: null
}
};
const partsOrQuestionsErrorMockResponse = {
error: 'Error getting parts'
};
jest.mock('bootstrap', () => ({
getInstance: jest.fn(),
getOrCreateInstance: jest.fn()
}));
const mockRoute = {
query: {
// Needed inside vehicle-questions-mixin
issPage: issPageValues.VIN_LOOKUP
}
};
const mockRouter = {
navigate: jest.fn(),
navigateWithSpinner: jest.fn()
};
const maska = jest.fn();
jest.mock('@/helpers/damage-helper', () => ({
isGlassAvailableForCarId: jest.fn().mockResolvedValue(false)
}));
const mountOptions = {
global: {
directives: {
maska
},
mixins: [
{
methods: {
getCmsContent: jest.fn(() => ''),
navigateBack: baseMixin.methods.navigateBack,
getFooterInfoBoxHeight: jest.fn(() => 80),
cssClassNameForCmsWidget: jest.fn(() => 'widget-name-mock-class'),
getPageNameByQueryString: jest.fn(() => ''),
pushEventToGA: jest.fn()
},
computed: {
GaActions() {
return GaActions;
},
navigationScenarios() {
return navigationScenarios;
},
queryStrings() {
return queryStrings;
}
}
}
],
mocks: {
$route: mockRoute,
$router: mockRouter
},
plugins: [createTestingPinia({
initialState: {
main: {
order: {
vehicle: {
carId: mockCarId
}
}
}
},
stubActions: false
})],
stubs: {
siteHeader: true,
siteSubHeader: true,
vinLocationInformation: true,
vinLookupAlerts: true,
vinQuestion: true
}
}
};
beforeEach(() => {
jest.clearAllMocks();
});
describe('vin-lookup.vue', () => {
describe('Client-side validation', () => {
test.each([
{ vin: null },
{ vin: '' }
])('VIN Required error messsage is displayed.', async ({ vin }) => {
const user = userEvent.setup();
mountOptions.data = () => ({
vin
});
mountOptions.global.stubs.vinQuestion = false;
const { container } = render(VinLookupComponent, mountOptions);
const continueButton = container.querySelector(continueButtonQuerySelector);
user.click(continueButton);
await flushPromises();
await waitFor(() => {
const errorMessageWrapperEl = container.querySelector(errorMessageWrapperElSelector);
expect(errorMessageWrapperEl).toBeVisible();
const errorMessageEl = errorMessageWrapperEl.querySelector('span');
expect(errorMessageEl.textContent).toBe(errorMessages.VIN_REQUIRED);
});
});
test.each([
{ vin: '11' },
{ vin: 'I1234567890123456' },
{ vin: 'O1234567890123456' },
{ vin: 'Q1234567890123456' }
])('VIN Invalid Format error messsage is displayed.', async ({ vin }) => {
const user = userEvent.setup();
mountOptions.data = () => ({
vin
});
mountOptions.global.stubs.vinQuestion = false;
const { container } = render(VinLookupComponent, mountOptions);
const continueButton = container.querySelector(continueButtonQuerySelector);
user.click(continueButton);
await flushPromises();
await waitFor(() => {
const errorMessageWrapperEl = container.querySelector(errorMessageWrapperElSelector);
expect(errorMessageWrapperEl).toBeVisible();
const errorMessageEl = errorMessageWrapperEl.querySelector('span');
expect(errorMessageEl.textContent).toBe(errorMessages.VIN_FORMAT);
});
});
test('No error message is displayed when the vin is in the accepted format.', async () => {
const user = userEvent.setup();
mountOptions.data = () => ({
vin: '12345678901234567'
});
mountOptions.global.stubs.vinQuestion = false;
const { container } = render(VinLookupComponent, mountOptions);
const continueButton = container.querySelector(continueButtonQuerySelector);
user.click(continueButton);
await flushPromises();
await waitFor(() => {
const errorMessageWrapperEl = container.querySelector(errorMessageWrapperElSelector);
expect(errorMessageWrapperEl).not.toBeVisible();
const errorMessageEl = errorMessageWrapperEl.querySelector('span');
expect(errorMessageEl.textContent).toBeFalsy();
});
});
});
describe('Navigation', () => {
test('Click "Back", execute navigate with navigationScenario.CLICKED_BACK.', async () => {
const user = userEvent.setup();
const { container } = render(VinLookupComponent, mountOptions);
const backButton = container.querySelector('[data-test-id="site-footer-back-button"]');
await user.click(backButton);
expect(mockRouter.navigateWithSpinner).toHaveBeenCalledTimes(1);
expect(mockRouter.navigateWithSpinner).toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK, mockRoute);
});
// eslint-disable-next-line max-len
test('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 () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
getPartsOrQuestions.mockResponse = vehicleWithPartQuestionsMockResponse;
lookupVehicleByVin.mockResponse.data.carId = 'Different Car Id';
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
mountOptions.data = () => ({
activeVehicleLookupAlertType: null,
needToLookupVehicle: false,
vehicleFromLookup: {
carId: 'Different Car Id'
},
vin: mockValidVin
});
const { container } = render(VinLookupComponent, mountOptions);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate).toHaveBeenCalledWith(
navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
mockRoute,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
});
});
describe('Succesful navigateForward', () => {
// eslint-disable-next-line max-len
test('Vehicle with Part Questions. Click "Continue", execute navigate with navigationScenario.CLICKED_FORWARD_WITH_PART_QUESTIONS', async () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
getPartsOrQuestions.mockResponse = vehicleWithPartQuestionsMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
mockRoute,
{},
{},
{ partsOrQuestions: getPartsOrQuestions.mockResponse.data.partsOrQuestions }
);
});
});
// eslint-disable-next-line max-len
test('Vehicle with Multiple Parts. Click "Continue", execute navigate with navigationScenario.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE', async () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
getPartsOrQuestions.mockResponse = vehicleWithMultiplePartsMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
mockRoute,
{},
{},
{ partsOrQuestions: getPartsOrQuestions.mockResponse.data.partsOrQuestions }
);
});
});
// eslint-disable-next-line max-len
test('Vehicle with Molding Questions. Click "Continue", execute navigate with navigationScenario.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS', async () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
getPartsOrQuestions.mockResponse = vehicleWithMoldingQuestionsMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
mockRoute,
{},
{},
{ partsOrQuestions: getPartsOrQuestions.mockResponse.data.partsOrQuestions }
);
});
});
// eslint-disable-next-line max-len
test('Vehicle with Capability Questions. Click "Continue", execute navigate with navigationScenario.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS', async () => {
const user = userEvent.setup();
const store = useMainStore();
mountOptions.global.stubs.vinQuestion = false;
getPartsOrQuestions.mockResponse = vehicleWithCapabilityQuestionsMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
store.getCapabilityQuestions.mockResolvedValueOnce({ data: [] });
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
mockRoute,
{},
{},
{ partsOrQuestions: getPartsOrQuestions.mockResponse.data.partsOrQuestions }
);
});
});
// eslint-disable-next-line max-len
test('Vehicle no additional Parts or Questions. Click "Continue", execute navigate with navigationScenario.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS', async () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
getPartsOrQuestions.mockResponse = vehicleWithNoAdditionalPartsOrQuestionsMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
mockRoute
);
});
});
test('Display no service alert if entered vin cannot be serviced', async () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
mountOptions.data = () => ({
vinWithNonMatchingCarId: false,
isCarIdDifferentFromTheStore: false,
vin: mockValidVin
});
getPartsOrQuestions.mockResponse = vehicleWithNoAdditionalPartsOrQuestionsMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVinCannotService.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(container).toContainHTML('noService');
});
});
// eslint-disable-next-line max-len
test('Policy Vehicle with invalid vin corrected. Click "Continue", execute navigate with navigationScenario.CORRECTED_VIN_FROM_POLICY_VEHICLE', async () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
mountOptions.data = () => ({
vinWithNonMatchingCarId: true,
isCarIdDifferentFromTheStore: false,
vin: mockValidVin
});
getPartsOrQuestions.mockResponse = vehicleWithNoAdditionalPartsOrQuestionsMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CORRECTED_VIN_FROM_POLICY_VEHICLE,
mockRoute
);
});
});
test(
'Error in getPartsOrQuestions call => bailout true and navigate forward with CLICKED_FORWARD_WITH_BAILOUT scenario',
async () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
mountOptions.data = () => ({
vinWithNonMatchingCarId: false,
isCarIdDifferentFromTheStore: false,
vin: mockValidVin,
hasBailedOut: true
});
getPartsOrQuestions.mockResponse = partsOrQuestionsErrorMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
mockRoute
);
});
}
);
});
});
});