DigitalConsumer.ISS/src/layouts/vin-lookup/vin-lookup.spec.js
2023-01-23 10:17:33 -05:00

462 lines
15 KiB
JavaScript

/* eslint-env jest */
import '@testing-library/jest-dom';
import { flushPromises } from '@vue/test-utils';
import { render, waitFor } from '@testing-library/vue';
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-params';
import { useMainStore } from '@/store';
import VinLookupComponent from './vin-lookup.vue';
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,
},
},
};
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 mockRoute = {
query: {
// Needed inside vehicle-questions-mixin
issPage: issPageValues.VIN_LOOKUP,
},
};
const mockRouter = {
navigate: 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(() => ''),
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,
vehicleBanner: 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.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK, mockRoute);
});
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(VinLookupComponent.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', () => {
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(VinLookupComponent.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 },
);
});
});
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(VinLookupComponent.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 },
);
});
});
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(VinLookupComponent.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 },
);
});
});
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(VinLookupComponent.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 },
);
});
});
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(VinLookupComponent.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,
);
});
});
});
});
});