Merge pull request #428 from Safelite/feature/digital/SSR-53

Feature/digital/ssr 53
This commit is contained in:
michaela-brydon-safelite 2023-09-06 13:16:40 -04:00 committed by GitHub
commit 050511338d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 749 additions and 33 deletions

View file

@ -1,7 +1,7 @@
const coverageStatuses = Object.freeze({
PENDING: 'Pending',
NO_COMP: 'No Comp',
VERIFIED: 'Verified'
PENDING: 0,
NO_COMP: 1,
VERIFIED: 2
});
export default coverageStatuses;

View file

@ -129,6 +129,10 @@ const endpoints = Object.freeze({
RegisterClaim: {
url: '/coverage/api/v1/coverage/register-claim',
method: 'POST'
},
SaveSession: {
url: '/order/api/v1/order/save-session/iss',
method: 'POST'
}
});

View file

@ -125,7 +125,8 @@ export function updateOrCreateISSCookie() {
ReferralNumber: store.order.referralNumber,
ReferralDate: store.order.referralDate,
ReferralCorrelationId: store.order.referralCorrelationId,
ReferralParentAccountNumber: store.order.accountNumber
ReferralParentAccountNumber: store.order.accountNumber,
SavedSessionId: store.applicationUser.savedSessionId
});
}

View file

@ -0,0 +1,29 @@
import { useMainStore } from '@/store';
import { updateOrCreateISSCookie } from '@/helpers/cookie-helper';
/*
Will call API to save existing order, or create new one depending where it's called from.
This will also set Referral information in the store after saving, and then
update the cookie. To force synchronous behavior pass in 'true' for shouldAwaitSaveSessionQueue
*/
export async function saveSession({ shouldAwaitSaveSessionQueue = false }) {
const store = useMainStore();
var saveSessionPromise = store.applicationUser.saveSessionPromise
? store.applicationUser.saveSessionPromise.then(() => { return saveSessionHelper(store); })
: saveSessionHelper(store);
store.setSaveSessionPromise(saveSessionPromise);
if (!store.applicationUser.savedSessionId || shouldAwaitSaveSessionQueue) {
await saveSessionPromise;
}
}
/*
Encapsulates asynchronous Save Session logic inside a promise to allow for Save Session queuing
*/
async function saveSessionHelper(store) {
const savedSessionInfo = await store.saveSession();
store.setSaveSessionInfo(savedSessionInfo.data);
updateOrCreateISSCookie();
}

View file

@ -9,6 +9,7 @@ import navigationScenarios from '@/router/router-constants/navigation-scenarios.
import { getRandomString, getRandomInt } from '@/helpers/data-generation.js';
import settleAllPromises from '@/helpers/layout-helper.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import routerParams from '@/router/router-constants/router-params';
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
@ -457,7 +458,11 @@ describe('coverageStatement.vue', () => {
// Assert
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD, undefined);
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD,
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true });
});
test('If Verified Deductible, navigate forward with CLICKED_FORWARD scenario', () => {
// Arrange
@ -493,7 +498,11 @@ describe('coverageStatement.vue', () => {
// Assert
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD, undefined);
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD,
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true });
});
test('If Verified ITAC and selected Safelite, navigate forward with CLICKED_FORWARD_WITH_SAFELITE scenario', () => {
// Arrange
@ -530,7 +539,11 @@ describe('coverageStatement.vue', () => {
// Assert
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, undefined);
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true });
});
test('If Verified ITAC, selected other shop, and TPA enabled, navigate forward w/ CLICKED_FORWARD_WITH_TPA_ENABLED', () => {
// Arrange
@ -570,7 +583,11 @@ describe('coverageStatement.vue', () => {
// Assert
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED, undefined);
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED,
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true });
});
test('If Verified ITAC, selected other shop, and TPA disabled, navigate forward w/ CLICKED_FORWARD_WITH_TPA_DISABLED', () => {
// Arrange
@ -610,7 +627,11 @@ describe('coverageStatement.vue', () => {
// Assert
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED, undefined);
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED,
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true });
});
test('If No Comp and selected Safelite, navigate forward with CLICKED_FORWARD scenario', () => {
// Arrange
@ -636,7 +657,11 @@ describe('coverageStatement.vue', () => {
// Assert
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, undefined);
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true });
});
});
describe('ADAS', () => {

View file

@ -120,6 +120,7 @@ import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin.js';
import globalRules from '@/constants/global-rules.js';
import baseFormMixin from '@/mixins/base-form-mixin.js';
import navigationScenarios from '@/router/router-constants/navigation-scenarios.js';
import routerParams from '@/router/router-constants/router-params';
export default {
name: 'coverage-statement',
@ -337,29 +338,39 @@ export default {
if (this.unverified || this.verifiedDeductible) {
this.$router.navigate(
navigationScenarios.CLICKED_FORWARD,
this.$route
this.$route,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
} else if (this.verifiedITAC || this.verifiedNoComp) {
if (this.selectedProvider === 'Safelite') {
this.$router.navigate(
navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
this.$route
this.$route,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
} else if (useMainStore().issConfig.enableTPAFlow) {
this.$router.navigate(
navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED,
this.$route
this.$route,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
} else {
this.$router.navigate(
navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED,
this.$route
this.$route,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
}
} else {
this.$router.navigate(
navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE,
this.$route
this.$route,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
}
},

View file

@ -10,6 +10,7 @@ import { getMountOptions } from '@/helpers/unit-test-helper.js';
import applicationConfig from '@/constants/application-config';
import { useMainStore } from '@/store';
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
import routerParams from '@/router/router-constants/router-params';
// Mock our module for promises.
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
@ -182,7 +183,7 @@ describe('navigation', () => {
navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
undefined,
{},
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true },
mockvehicles
);
});
@ -208,7 +209,9 @@ describe('navigation', () => {
// Assert
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
undefined
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
});
test('if policy is not found, navigate to policy-holder-details page', async () => {
@ -228,7 +231,9 @@ describe('navigation', () => {
// Assert
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
undefined
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
});
});

View file

@ -184,6 +184,7 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { useMainStore } from '@/store';
import states from '@/constants/states';
import globalRules from '@/constants/global-rules';
import routerParams from '@/router/router-constants/router-params';
// define validation rules
defineRule('loss-date-required', required(errorMessages.LOSS_DATE_REQUIRED));
@ -351,7 +352,7 @@ export default {
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
this.$route,
{},
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true },
this.vehiclesFound
);
} else {
@ -359,14 +360,18 @@ export default {
// navigate to vehicle-selection page (manual entry)
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
this.$route
this.$route,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
}
} else {
// if policy lookup is unsuccessful, navigate to policy-holder-details page
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
this.$route
this.$route,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
}
},

View file

@ -14,6 +14,8 @@ import applicationConfig from '@/constants/application-config';
import analyticsMixin from '@/mixins/analytics-mixin';
import navigationScenarios from './router-constants/navigation-scenarios';
import { saveSession } from "@/helpers/order-helper.js";
import routerParams from '@/router/router-constants/router-params';
const routes = [
{
@ -116,11 +118,25 @@ const router = createRouter({
}
});
router.afterEach((to) => {
router.afterEach(async (to, from) => {
/*eslint-disable-line*/
const store = useMainStore();
// Update lastPageVisited in the store
store.updateLastPageVisited(to.name);
if (from.redirectedFrom === undefined){
store.clearSaveSessionPromise();
}
const saveSessionSynchronous = !!from.params[routerParams.SAVE_SESSION_SYNCHRONOUS];
await saveSession({shouldAwaitSaveSessionQueue: saveSessionSynchronous}).catch((error) => {
if (from.name === issPageValues.WELCOME_PAGE) {
router.navigate(
navigationScenarios.SAVE_SESSION_FAILED,
{query: {issPage: issPageValues.WELCOME_PAGE}});
}
});
if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
// Push page view to GA
analyticsMixin.methods.pushPageViewToGA();

View file

@ -11,6 +11,7 @@ const navigationScenarios = Object.freeze({
CLICKED_FORWARD_POLICY_UNVERIFIED: 'CLICKED_FORWARD_POLICY_UNVERIFIED',
CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES: 'CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES',
CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES: 'CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES',
SAVE_SESSION_FAILED: 'SAVE_SESSION_FAILED',
// YMMS
SELECTED_YEAR: 'SELECTED_YEAR',

View file

@ -1,5 +1,6 @@
const routerParams = Object.freeze({
DISPLAY_VEHICLE_CHANGE_ALERT: 'displayVehicleChangeAlert'
DISPLAY_VEHICLE_CHANGE_ALERT: 'displayVehicleChangeAlert',
SAVE_SESSION_SYNCHRONOUS: 'saveSessionSynchronous'
});
export default routerParams;

View file

@ -363,6 +363,10 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
destinationIssPageValue: issPageValues.POLICY_VEHICLES
},
{
scenario: navigationScenarios.SAVE_SESSION_FAILED,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},

View file

@ -87,14 +87,12 @@ const getDefaultState = () => ({
vaps: null
},
payment: {
isInsurance: true,
isInsurance: true, // TODO delete; irrelevant to ISS
insuranceCoverage: {
isVerified: false,
coverageStatus: coverageStatuses.PENDING
}
},
referralNumber: null,
referralDate: null,
contactInfo: {
firstName: null,
lastName: null,
@ -102,7 +100,22 @@ const getDefaultState = () => ({
phoneNumber: null,
requestTextUpdates: false,
notesForTechnician: ''
}
},
schedule: {
date: null,
startTime: null,
endTime: null,
routeCode: null,
jobMaxMinutes: null
},
referralNumber: null,
referralDate: null,
referralCorrelationId: '00000000-0000-0000-0000-000000000000',
referralSequenceNumber: null,
eon: null,
workOrderNumber: null,
originalDeductible: null,
currentDeductible: null
},
applicationUser: {
experiments: [],
@ -335,8 +348,6 @@ export const useMainStore = defineStore({
}
},
getCoveragePolicyInfo({ accountNumber, policyNumber, dateOfLoss, zipCode }) {
// TODO: replace place holder correlationId with the real thing
const placeHolderCorrelationId = '00000000-0000-0000-0000-000000000000';
const { policy } = this.order;
try {
const response = globalMethods.callHttpClient({
@ -347,7 +358,7 @@ export const useMainStore = defineStore({
policyNumber,
dateOfLoss,
zipCode,
correlationId: placeHolderCorrelationId
correlationId: this.order.referralCorrelationId
}
}).then((r) => {
const responsePolicy = r.data.policies?.[0];
@ -368,8 +379,6 @@ export const useMainStore = defineStore({
}
},
registerClaim() {
// TODO: replace place holder correlationId with the real thing
const placeHolderCorrelationId = '00000000-0000-0000-0000-000000000000';
const nonNumberCharRegex = /[^0-9]/g;
const { order } = this;
return new Promise((resolve, reject) => {
@ -378,7 +387,7 @@ export const useMainStore = defineStore({
endpoint: endpoints.RegisterClaim.url,
payload:
{
correlationId: placeHolderCorrelationId,
correlationId: this.order.referralCorrelationId,
accountNumber: this.issConfig.accountNumber?.toString() ?? '',
insured: {
firstName: this.order.customer.firstName,
@ -682,6 +691,132 @@ export const useMainStore = defineStore({
});
},
setSaveSessionInfo(response){
this.order.referralNumber = response.referralNumber;
this.order.referralSequenceNumber = response.referralSequenceNumber;
this.order.referralDate = response.referralDate;
this.order.referralCorrelationId = response.referralCorrelationId;
this.order.eon = response.eon;
this.order.workOrderNumber = response.workOrderNumber;
this.applicationUser.savedSessionId = response.savedSessionId;
this.applicationUser.crmCustomerId = response.crmCustomerId.toString();
},
saveSession() {
const { vehicle, damage, policy, customer, contactInfo, payment,
lineItems, serviceLocation, schedule } = this.order;
const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace);
return globalMethods.callHttpClient({
method: endpoints.SaveSession.method,
endpoint: endpoints.SaveSession.url,
payload: {
applicationUser: {
crmCustomerId: this.applicationUser.crmCustomerId,
experiments: this.applicationUser.experiments,
lastPage: this.applicationUser.lastPageVisited,
pageData: this.applicationUser.pageData,
savedSessionId: this.applicationUser.savedSessionId
},
vehicle: {
year: vehicle.year,
make: vehicle.make,
model: vehicle.model,
style: vehicle.style,
vin: vehicle.vin,
carId: vehicle.carId,
licensePlateNumber: vehicle.registration?.licensePlate
},
damage: {
numberOfChips: damage.numberOfChips,
glassToReplace: newGlassToReplace,
isRepair: damage.isRepair,
partQuestionAnswers: damage.partQuestionAnswers,
moldingQuestionAnswers: damage.moldingQuestionAnswers,
capabilityQuestionAnswers: damage.capabilityQuestionAnswers,
dateOfLoss: policy.dateOfLoss,
damageCause: policy.damageCause,
damageState: policy.damageState,
damageCity: policy.damageCity,
isDamageGlassOnly: policy.isDamageGlassOnly
},
policy: {
policyHolder: {
policyFirstName: customer.firstName,
policyLastName: customer.lastName,
policyPhoneNumber: customer.phoneNumber,
policyEmail: customer.emailAddress
},
policyNumber: policy.policyNumber,
policyZipCode: policy.policyZipCode,
noCoverage: policy.noCoverage,
policyLookupSuccessful: policy.policyLookupSuccessful,
originalDeductible: this.order.originalDeductible,
currentDeductible: this.order.currentDeductible
},
customer: {
address: {
streetAddress: customer.address?.streetAddress,
streetAddress2: customer.address?.streetAddress2,
city: customer.address?.city,
state: customer.address?.state,
zipCode: customer.address?.zipCode
},
emailAddress: contactInfo.emailAddress,
firstName: contactInfo.firstName,
lastName: contactInfo.lastName,
phoneNumber: contactInfo.phoneNumber,
optInSms: contactInfo.requestTextUpdates ?? false
},
lineItems: {
glassParts: lineItems.glassParts,
supportingItems: lineItems.supportingItems,
vaps: lineItems.vaps
},
payment: {
InsuranceCoverage: {
isVerified: payment.insuranceCoverage?.isVerified ?? false,
coverageStatus: payment.insuranceCoverage?.coverageStatus
},
isInsurance: payment.isInsurance ?? true,
parentAccountNumber: this.issConfig.accountNumber
},
serviceLocation: {
address: {
streetAddress: serviceLocation.address,
city: serviceLocation.city,
state: serviceLocation.state,
zipCode: serviceLocation.zipCode,
zipCodeCtu: serviceLocation.zipCodeCtu
},
techNotes: contactInfo.notesForTechnician
},
schedule: {
date: schedule.date,
startTime: schedule.startTime,
endTime: schedule.endTime,
routeCode: schedule.routeCode,
jobMaxMinutes: schedule.jobMaxMinutes
},
referralDate: this.order.referralDate,
referralNumber: this.order.referralNumber?.toString(),
referralCorrelationId: this.order.referralCorrelationId,
referralSequenceNumber: this.order.referralSequenceNumber,
eon: this.order.eon
},
additionalSuccessEventDataHandler: (response) =>
`Email provided: ${customer.emailAddress ? 'true' : 'false'}`
});
},
setSaveSessionPromise(promise){
this.applicationUser.saveSessionPromise = promise;
},
clearSaveSessionPromise(){
this.applicationUser.saveSessionPromise = null;
},
saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) {
const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort();
const isGlassToReplaceTheSame = this.order.damage.glassToReplace?.length === selectedGlassToReplace.length
@ -765,6 +900,10 @@ export const useMainStore = defineStore({
this.order.policy.deductible.replace = vehicle.deductible;
this.order.policy.deductible.repair = vehicle?.repairWaived ?? false ? 0 : vehicle.deductible;
// TODO logic should be more complicated later on
this.order.originalDeductible = parseFloat(vehicle.deductible);
this.order.currentDeductible = parseFloat(vehicle.deductible);
this.resetSupportingItemsState();
this.resetVapsState();
},

View file

@ -3,6 +3,7 @@ import { setActivePinia, createPinia } from 'pinia';
import globalMethods from '@/global-methods.js';
import { getRandomString, getRandomGuid, getRandomInt, getRandomBoolean } from '@/helpers/data-generation.js';
import coverageStatuses from '@/constants/coverage-statuses.js';
import { endpoints } from '@/constants/endpoints';
describe('Store', () => {
let store;
@ -480,4 +481,478 @@ describe('Store', () => {
expect(store.contactInfo.notesForTechnician).toEqual('');
});
});
describe('saveSession method', () => {
describe('successful method call', () => {
it('calls save session api endpoint', () => {
// Arrange
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Asserts
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
method: endpoints.SaveSession.method,
endpoint: endpoints.SaveSession.url
}
));
});
it('Returns expected response object', async () => {
// Arrange
var response = { ReferralNumber: getRandomString(6, 6) };
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response));
// Act
const result = store.saveSession();
// Asserts
await expect(result).resolves.toBe(response);
})
it('calls api with expected application user data', () => {
// Arrange
var applicationUser = {
crmCustomerId: getRandomString(6, 6),
experiments: getRandomString(6, 6),
lastPageVisited: getRandomString(6, 6),
pageData: getRandomString(6, 6),
savedSessionId: getRandomString(6, 6)
};
store.applicationUser = applicationUser;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
const result = store.saveSession();
// Asserts
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
applicationUser: expect.objectContaining({
crmCustomerId: applicationUser.crmCustomerId,
experiments: applicationUser.experiments,
lastPage: applicationUser.lastPageVisited,
pageData: applicationUser.pageData,
savedSessionId: applicationUser.savedSessionId
})
})
})
);
});
it('calls api with expected vehicle', () => {
var vehicle = {
year: getRandomString(6, 6),
make: getRandomString(6, 6),
model: getRandomString(6, 6),
style: getRandomString(6, 6),
carId: getRandomString(6, 6),
vin: getRandomString(6, 6),
registration: { licensePlate: getRandomString(6, 6) }
};
store.order.vehicle = vehicle;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Asserts
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
vehicle: expect.objectContaining({
year: vehicle.year,
make: vehicle.make,
model: vehicle.model,
style: vehicle.style,
carId: vehicle.carId,
vin: vehicle.vin,
licensePlateNumber: vehicle.registration.licensePlate
})
})
}
));
});
it('calls api with expected damage', () => {
// Arrange
var damage = {
isRepair: getRandomString(6, 6),
numberOfChips: getRandomString(6, 6),
glassToReplace: [],
partQuestionAnswers: getRandomString(6, 6),
moldingQuestionAnswers: getRandomString(6, 6),
capabilityQuestionAnswers: getRandomString(6, 6)
};
var policy = {
dateOfLoss: getRandomString(6, 6),
damageCause: getRandomString(6, 6),
damageState: getRandomString(6, 6),
damageCity: getRandomString(6, 6),
isDamageGlassOnly: getRandomString(6, 6)
};
store.order.damage = damage;
store.order.policy = policy;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
damage: expect.objectContaining({
numberOfChips: damage.numberOfChips,
isRepair: damage.isRepair,
partQuestionAnswers: damage.partQuestionAnswers,
moldingQuestionAnswers: damage.moldingQuestionAnswers,
capabilityQuestionAnswers: damage.capabilityQuestionAnswers,
dateOfLoss: policy.dateOfLoss,
damageCause: policy.damageCause,
damageState: policy.damageState,
damageCity: policy.damageCity,
isDamageGlassOnly: policy.isDamageGlassOnly
})
})
})
);
});
it('calls api with expected policy', () => {
// Arrange
var customer = {
firstName: getRandomString(6, 6),
lastName: getRandomString(6, 6),
emailAddress: getRandomString(6, 6),
phoneNumber: getRandomString(6, 6)
};
var policy = {
policyNumber: getRandomString(6, 6),
policyZipCode: getRandomString(6, 6),
policyLookupSuccessful: getRandomString(6, 6),
noCoverage: getRandomString(6, 6)
};
var originalDeductible = getRandomString(6, 6);
var currentDeductible = getRandomString(6, 6);
store.order.originalDeductible = originalDeductible;
store.order.currentDeductible = currentDeductible;
store.order.customer = customer;
store.order.policy = policy;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Asserts
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
policy: expect.objectContaining({
policyHolder: expect.objectContaining({
policyFirstName: customer.firstName,
policyLastName: customer.lastName,
policyPhoneNumber: customer.phoneNumber,
policyEmail: customer.emailAddress
}),
policyNumber: policy.policyNumber,
policyZipCode: policy.policyZipCode,
noCoverage: policy.noCoverage,
policyLookupSuccessful: policy.policyLookupSuccessful,
originalDeductible,
currentDeductible
})
})
})
);
});
it('calls api with expected customer', () => {
// Arrange
var customer = {
address: {
streetAddress: getRandomString(6, 6),
streetAddress2: getRandomString(6, 6),
city: getRandomString(6, 6),
state: getRandomString(6, 6),
zipCode: getRandomString(6, 6)
}
};
var contactInfo = {
firstName: getRandomString(6, 6),
lastName: getRandomString(6, 6),
emailAddress: getRandomString(6, 6),
phoneNumber: getRandomString(6, 6),
requestTextUpdates: getRandomBoolean()
};
store.order.contactInfo = contactInfo;
store.order.customer = customer;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
customer: expect.objectContaining({
address: expect.objectContaining({
streetAddress: customer.address.streetAddress,
streetAddress2: customer.address.streetAddress2,
city: customer.address.city,
state: customer.address.state,
zipCode: customer.address.zipCode
}),
emailAddress: contactInfo.emailAddress,
firstName: contactInfo.firstName,
lastName: contactInfo.lastName,
phoneNumber: contactInfo.phoneNumber,
optInSms: contactInfo.requestTextUpdates
})
})
})
);
});
it('calls api with expected lineItems', () => {
// Arrange
var lineItems = {
glassParts: getRandomString(6, 6),
supportingItems: getRandomString(6, 6),
vaps: getRandomString(6, 6)
};
store.order.lineItems = lineItems;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
lineItems: expect.objectContaining({
glassParts: lineItems.glassParts,
supportingItems: lineItems.supportingItems,
vaps: lineItems.vaps
})
})
})
);
});
it.each([
[coverageStatuses.PENDING],
[coverageStatuses.NO_COMP],
[coverageStatuses.VERIFIED]
])('calls api with expected payment', (coverageStatus) => {
// Arrange
const accountNumber = getRandomString(6, 6);
const payment = {
isInsurance: getRandomBoolean(),
insuranceCoverage: {
isVerified: getRandomBoolean(),
coverageStatus
}
};
store.issConfig.accountNumber = accountNumber;
store.order.payment = payment;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
payment: expect.objectContaining({
InsuranceCoverage: expect.objectContaining({
isVerified: payment.insuranceCoverage.isVerified,
coverageStatus: coverageStatus
}),
isInsurance: payment.isInsurance,
parentAccountNumber: accountNumber
})
})
})
);
});
it('calls api with expected service location', () => {
// Arrange
var notesForTechnician = getRandomString(6, 6);
var serviceLocation = {
address: getRandomString(6, 6),
city: getRandomString(6, 6),
state: getRandomString(6, 6),
zipCode: getRandomString(6, 6),
zipCodeCtu: getRandomString(6, 6)
};
store.order.contactInfo.notesForTechnician = notesForTechnician;
store.order.serviceLocation = serviceLocation;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
serviceLocation: expect.objectContaining({
address: expect.objectContaining({
streetAddress: serviceLocation.address,
city: serviceLocation.city,
state: serviceLocation.state,
zipCode: serviceLocation.zipCode,
zipCodeCtu: serviceLocation.zipCodeCtu
}),
techNotes: notesForTechnician
})
})
})
);
});
it('calls api with expected schedule', () => {
// Arrange
var schedule = {
date: getRandomString(6, 6),
startTime: getRandomString(6, 6),
endTime: getRandomString(6, 6),
routeCode: getRandomString(6, 6),
jobMaxMinutes: getRandomString(6, 6)
};
store.order.schedule = schedule;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
schedule: expect.objectContaining({
date: schedule.date,
startTime: schedule.startTime,
endTime: schedule.endTime,
routeCode: schedule.routeCode,
jobMaxMinutes: schedule.jobMaxMinutes
})
})
})
);
});
it('calls api with expected referral date', () => {
// Arrange
var referralDate = getRandomString(6, 6);
store.order.referralDate = referralDate;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({ referralDate: referralDate })
})
);
});
it('calls api with expected referral number', () => {
// Arrange
var referralNumber = getRandomString(6, 6);
store.order.referralNumber = referralNumber;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
store.saveSession();
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({ referralNumber: referralNumber })
}
));
});
});
it('No glassArray => empty list', async () => {
store.damage.glassToReplace = null;
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
await store.saveSession();
// Asserts
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
damage: expect.objectContaining({
glassToReplace: []
})
})
})
);
});
it('glassArray empty => empty list', async () => {
store.damage.glassToReplace = [];
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
await store.saveSession();
// Asserts
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
damage: expect.objectContaining({
glassToReplace: []
})
})
})
);
});
it('Nonempty glass array => expected glass array sent', async () => {
const location1 = getRandomString(5);
const location2 = getRandomString(5);
const name1 = getRandomString(10);
const name2 = getRandomString(10);
store.damage.glassToReplace = [
{glassLocation: location1, glassName: name1},
{glassLocation: location2, glassName: name2}
],
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({}));
// Act
await store.saveSession();
// Asserts
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
payload: expect.objectContaining({
damage: expect.objectContaining({
glassToReplace: expect.arrayContaining([
{location: location1, name: name1},
{location: location2, name: name2}
])
})
})
})
);
});
it('api call throws exception', async () => {
expect.assertions(2);
const error = 'this is the error';
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
// Act
await store.saveSession().catch((e) => {
expect(e).toEqual(error);
});
// Asserts
expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining(
{
method: endpoints.SaveSession.method,
endpoint: endpoints.SaveSession.url
})
);
});
});
});