Baseline linting of helpers & mixins and some fixup of digital-components and iss-components
This commit is contained in:
parent
c4b06b6a69
commit
a36292d384
40 changed files with 577 additions and 717 deletions
|
|
@ -23,6 +23,7 @@ module.exports = {
|
|||
'comma-dangle': ['error', 'never'],
|
||||
indent: ['error', 4],
|
||||
'max-len': ['error', { code: 140 }],
|
||||
'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
|
||||
'vue/html-indent': 'off',
|
||||
'vue/html-closing-bracket-newline': ['error', {
|
||||
singleline: 'never',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
const applicationConfig = {
|
||||
CURRENT_ENVIRONMENT: process.env.VUE_APP_CURRENT_ENVIRONMENT, // "Localhost", "Dev", "QA", and "Prod"
|
||||
CURRENT_ENVIRONMENT: process.env.VUE_APP_CURRENT_ENVIRONMENT, // "Localhost", "Dev", "QA", and "Prod"
|
||||
CONSUMER_CF_DISTRO: process.env.VUE_APP_CONSUMER_CF_DISTRO,
|
||||
ANALYTICS_SESSION_TIMEOUT_MINUTES: 30,
|
||||
SAVED_SESSION_TIMEOUT_DAYS: 45,
|
||||
|
|
@ -8,7 +8,7 @@ const applicationConfig = {
|
|||
SITE_ENTRY_TRIGGER_VALUE: 'SelfService',
|
||||
APPLICATION_ABBREVIATION: 'iss',
|
||||
PAGE_QUERYSTRING: 'issPage',
|
||||
CLIENTTAG_QUERYSTRING: 'CientTag',
|
||||
CLIENTTAG_QUERYSTRING: 'ClientTag',
|
||||
GOOGLE_PLACES_API_KEY: process.env.VUE_APP_GOOGLE_PLACES_API_KEY,
|
||||
ISS_DEV_CMS_DOMAIN: 'https://digitalisscms.dev.safelite.io',
|
||||
CASH_PARENT_ACCOUNT_NUMBER: 167132
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ import listButtonHorizontal from '@/ux-components/list-button-horizontal/list-bu
|
|||
import listCard from '@/ux-components/list-card/list-card';
|
||||
import radio from '@/ux-components/radio/radio';
|
||||
import { ErrorMessage } from 'vee-validate';
|
||||
import providerPrefRadio from '@/layouts/provider-preference/provider-pref-radio/provider-pref-radio.vue';
|
||||
import providerPrefRadio from '@/layouts/provider-preference/provider-pref-radio/provider-pref-radio';
|
||||
|
||||
export default {
|
||||
name: 'button-question',
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ const mockMixin = {
|
|||
methods: {
|
||||
getCmsContent: jest.fn().mockImplementation(() => questionText)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Remove the following from dropdown-question.vue -> :class="(errors && errors.length) || hasError ? 'has-error' : ''"
|
||||
// It is not being used.
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ export default {
|
|||
hasError: Boolean,
|
||||
placeHolderText: String
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props) {
|
||||
const propsClone = { ...props };
|
||||
const { modelValue } = propsClone;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export default {
|
|||
// NOTE: needs to have async/await here; tested and won't work without it
|
||||
await useValidateForm();
|
||||
|
||||
this.questionData.map((q, i) => {
|
||||
this.questionData.map((q) => {
|
||||
const question = {
|
||||
questionText: q.questionText,
|
||||
questionSequence: q.questionSequence,
|
||||
|
|
@ -78,6 +78,7 @@ export default {
|
|||
if (!q.suppressThisQuestion) {
|
||||
this.questions.push(question);
|
||||
}
|
||||
return q;
|
||||
});
|
||||
|
||||
if (!this.modelValue?.length > 0 && this.questions.length > 0) {
|
||||
|
|
|
|||
|
|
@ -1,44 +1,9 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import TextBlock from './text-block';
|
||||
|
||||
describe('modal.vue', () => {
|
||||
it("Should display 'Text' when 'Text' is defined in the CMS", async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(TextBlock, {
|
||||
mixins: [mockMixin],
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['Text']));
|
||||
});
|
||||
|
||||
it('Should contain the typeStyle class as defined by the prop', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(TextBlock, {
|
||||
mixins: [mockMixin],
|
||||
propsData: mockProps,
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockProps['typeStyle']));
|
||||
});
|
||||
it('Should contain the justifyText class as defined by the prop', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(TextBlock, {
|
||||
mixins: [mockMixin],
|
||||
propsData: mockProps,
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockProps['justifyText']));
|
||||
});
|
||||
it('Should contain the fontWeight class as defined by the prop', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(TextBlock, {
|
||||
mixins: [mockMixin],
|
||||
propsData: mockProps,
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockProps['fontWeight']));
|
||||
});
|
||||
});
|
||||
|
||||
///////////////
|
||||
// Constants //
|
||||
///////////////
|
||||
const mockCmsContent = {
|
||||
Text: 'Sample text here.'
|
||||
};
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
|
|
@ -52,6 +17,37 @@ const mockProps = {
|
|||
justifyText: 'mockJustifyText'
|
||||
};
|
||||
|
||||
const mockCmsContent = {
|
||||
Text: 'Sample text here.'
|
||||
};
|
||||
describe('modal.vue', () => {
|
||||
it("Should display 'Text' when 'Text' is defined in the CMS", async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(TextBlock, {
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.Text));
|
||||
});
|
||||
|
||||
it('Should contain the typeStyle class as defined by the prop', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(TextBlock, {
|
||||
mixins: [mockMixin],
|
||||
propsData: mockProps
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockProps.typeStyle));
|
||||
});
|
||||
it('Should contain the justifyText class as defined by the prop', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(TextBlock, {
|
||||
mixins: [mockMixin],
|
||||
propsData: mockProps
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockProps.justifyText));
|
||||
});
|
||||
it('Should contain the fontWeight class as defined by the prop', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(TextBlock, {
|
||||
mixins: [mockMixin],
|
||||
propsData: mockProps
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockProps.fontWeight));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<template>
|
||||
<div class="textbox-question" :class="(errors && errors.length) || hasError ? 'has-error' : ''">
|
||||
<div
|
||||
class="textbox-question"
|
||||
:class="(errors && errors.length) || hasError ? 'has-error' : ''">
|
||||
<label
|
||||
v-if="displayQuestionText"
|
||||
:for="inputId"
|
||||
|
|
@ -43,7 +45,10 @@
|
|||
@focus="$emit('focus', $event.target.value)"
|
||||
@paste="trimOnPaste"
|
||||
@drop="trimOnPaste" />
|
||||
<button v-if="includeSearchIcon" type="submit" aria-label="Search button" />
|
||||
<button
|
||||
v-if="includeSearchIcon"
|
||||
type="submit"
|
||||
aria-label="Search button" />
|
||||
<button
|
||||
v-if="includeSelectIcon"
|
||||
type="submit"
|
||||
|
|
@ -51,8 +56,12 @@
|
|||
:data-bs-target="'#' + cmsWidgetName"
|
||||
aria-label="Select button" />
|
||||
</div>
|
||||
<div v-show="errorMessage" class="row my-1 form-test-error">
|
||||
<span class="d-inline-flex mt-0" role="alert">{{ errorMessage }}</span>
|
||||
<div
|
||||
v-show="errorMessage"
|
||||
class="row my-1 form-test-error">
|
||||
<span
|
||||
class="d-inline-flex mt-0"
|
||||
role="alert">{{ errorMessage }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -107,12 +116,12 @@ export default {
|
|||
let initialValue;
|
||||
|
||||
switch (typeof modelValue) {
|
||||
case 'number':
|
||||
initialValue = modelValue;
|
||||
break;
|
||||
default:
|
||||
initialValue = modelValue && modelValue.length > 0 ? modelValue : '';
|
||||
break;
|
||||
case 'number':
|
||||
initialValue = modelValue;
|
||||
break;
|
||||
default:
|
||||
initialValue = modelValue && modelValue.length > 0 ? modelValue : '';
|
||||
break;
|
||||
}
|
||||
|
||||
const fieldOptions = {
|
||||
|
|
@ -122,11 +131,9 @@ export default {
|
|||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { errorMessage, handleBlur, handleChange, meta, validate, errors } = useField(
|
||||
props.inputId,
|
||||
const { errorMessage, handleBlur, handleChange, meta, validate, errors } = useField(props.inputId,
|
||||
props.validationRules,
|
||||
fieldOptions
|
||||
);
|
||||
fieldOptions);
|
||||
|
||||
return {
|
||||
errorMessage,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@
|
|||
let lastFocusedInputGroupName = '';
|
||||
let onButtonQuestionLostFocusCallback = null;
|
||||
|
||||
const invokeButtonQuestionLostFocusCallback = () => {
|
||||
if (onButtonQuestionLostFocusCallback) {
|
||||
onButtonQuestionLostFocusCallback();
|
||||
}
|
||||
};
|
||||
|
||||
const handleAnyComponentFocus = (e) => {
|
||||
const targetType = e.target.type;
|
||||
if (targetType !== 'radio' && targetType !== 'checkbox') {
|
||||
|
|
@ -28,10 +34,4 @@ const handleInputComponentBlur = (e) => {
|
|||
}
|
||||
};
|
||||
|
||||
const invokeButtonQuestionLostFocusCallback = () => {
|
||||
if (onButtonQuestionLostFocusCallback) {
|
||||
onButtonQuestionLostFocusCallback();
|
||||
}
|
||||
};
|
||||
|
||||
export { handleAnyComponentFocus, handleButtonComponentFocus, handleInputComponentBlur };
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import { useMainStore } from '@/store';
|
||||
|
||||
export function validateISSClientTag(clientTag) {
|
||||
const store = useMainStore()
|
||||
const store = useMainStore();
|
||||
|
||||
return store.validateClientTag(clientTag)
|
||||
.then((response) =>
|
||||
// Success
|
||||
response
|
||||
,
|
||||
response,
|
||||
(error) =>
|
||||
// Error
|
||||
null);
|
||||
|
|
|
|||
|
|
@ -3,34 +3,31 @@ import { useMainStore } from '@/store';
|
|||
|
||||
export function fetchCmsContentForPage(issPage) {
|
||||
const store = useMainStore();
|
||||
const clientName = store.issConfig.clientName;
|
||||
const accountNumber = store.issConfig.accountNumber;
|
||||
const { clientName } = store.issConfig;
|
||||
const { accountNumber } = store.issConfig;
|
||||
const clientOverride = (clientName.length > 0 && accountNumber > 0);
|
||||
|
||||
return store.getPageData(issPage)
|
||||
.then(
|
||||
// Get the base/default page first.
|
||||
(baseResponse) => {
|
||||
if (!clientOverride) {
|
||||
// Return the base page if there are no client override.
|
||||
return processPageData(baseResponse, null);
|
||||
} else {
|
||||
// Else get the client override page.
|
||||
const pageName = issPage + '_' + clientName.toLowerCase().replace(/ /g, '');
|
||||
// Get the base/default page first.
|
||||
.then((baseResponse) => {
|
||||
if (!clientOverride) {
|
||||
// Return the base page if there are no client override.
|
||||
return processPageData(baseResponse, null);
|
||||
}
|
||||
// Else get the client override page.
|
||||
const pageName = `${issPage}_${clientName.toLowerCase().replace(/ /g, '')}`;
|
||||
|
||||
return store.getPageData(pageName)
|
||||
.then((clientResponse) => {
|
||||
// Process the client override if it exists.
|
||||
return processPageData(baseResponse, clientResponse);
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
// Process the just the base if no client override exists.
|
||||
return processPageData(baseResponse, null);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
return store.getPageData(pageName)
|
||||
.then((clientResponse) =>
|
||||
// Process the client override if it exists.
|
||||
processPageData(baseResponse, clientResponse),
|
||||
(error) => {
|
||||
console.error(error);
|
||||
// Process the just the base if no client override exists.
|
||||
return processPageData(baseResponse, null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Support method for processing the page data from the CMS call.
|
||||
// widgets = current widget collection used by page.
|
||||
|
|
@ -41,8 +38,8 @@ function processPageData(baseResponse, clientResponse) {
|
|||
let widgets = [];
|
||||
|
||||
if (!baseResponse?.data?.Result) {
|
||||
console.error('No result data found'); // Something has gone terribly wrong.
|
||||
return {}
|
||||
console.error('No result data found'); // Something has gone terribly wrong.
|
||||
return {};
|
||||
}
|
||||
if (!clientResponse?.data?.Result) {
|
||||
widgets = baseResponse.data.Result;
|
||||
|
|
@ -111,7 +108,7 @@ function findAndReplaceGlobalStateValues(widgetModel, widgetName) {
|
|||
};
|
||||
|
||||
Object.keys(widgetModel).forEach((key) => {
|
||||
let modelWithReplacements = processWidgetItemForReplacement(widgetModel,
|
||||
const modelWithReplacements = processWidgetItemForReplacement(widgetModel,
|
||||
key);
|
||||
|
||||
objWithReplacements.Model[key] = modelWithReplacements;
|
||||
|
|
@ -144,8 +141,8 @@ function processWidgetItemForReplacement(widgetModel, key) {
|
|||
}
|
||||
|
||||
// If we have an object. array, etc
|
||||
if (typeof widgetModel[key] === 'object' &&
|
||||
Object.keys(widgetModel[key]).length) {
|
||||
if (typeof widgetModel[key] === 'object'
|
||||
&& Object.keys(widgetModel[key]).length) {
|
||||
Object.keys(widgetModel[key]).forEach((item) => {
|
||||
processWidgetItemForReplacement(widgetModel[key], item);
|
||||
});
|
||||
|
|
@ -158,14 +155,14 @@ function processWidgetItemForReplacement(widgetModel, key) {
|
|||
}
|
||||
|
||||
function mapStringToModal(str) {
|
||||
const startIndex = str.indexOf('{' + dynamicStrings.MODAL_LINK);
|
||||
const startIndex = str.indexOf(`{${dynamicStrings.MODAL_LINK}`);
|
||||
let linkToReplace = str.substring(startIndex, str.length);
|
||||
linkToReplace = linkToReplace.substring(0, linkToReplace.indexOf('}') + 1);
|
||||
|
||||
const params = linkToReplace.substring((dynamicStrings.MODAL_LINK).length + 2, linkToReplace.length - 1);
|
||||
const splitParams = params.split(',');
|
||||
|
||||
const bodyText = '<a modalTarget="' + splitParams[0] + '" class="modal-text" aria-label="Modal window">' + splitParams[1] + '</a>';
|
||||
const bodyText = `<a modalTarget="${splitParams[0]}" class="modal-text" aria-label="Modal window">${splitParams[1]}</a>`;
|
||||
|
||||
let returnVal = str.replace(linkToReplace, bodyText);
|
||||
|
||||
|
|
@ -176,14 +173,14 @@ function mapStringToModal(str) {
|
|||
}
|
||||
|
||||
function mapStringToLink(str) {
|
||||
const startIndex = str.indexOf('{' + dynamicStrings.EXTERNAL_LINK);
|
||||
const startIndex = str.indexOf(`{${dynamicStrings.EXTERNAL_LINK}`);
|
||||
let linkToReplace = str.substring(startIndex, str.length);
|
||||
linkToReplace = linkToReplace.substring(0, linkToReplace.indexOf('}') + 1);
|
||||
|
||||
const params = linkToReplace.substring((dynamicStrings.EXTERNAL_LINK).length + 2, linkToReplace.length - 1);
|
||||
const splitParams = params.split(',');
|
||||
|
||||
const bodyText = '<a href="' + splitParams[0] + '" class="external-text" target="_blank">' + splitParams[1] + '</a>';
|
||||
const bodyText = `<a href="${splitParams[0]}" class="external-text" target="_blank">${splitParams[1]}</a>`;
|
||||
|
||||
let returnVal = str.replace(linkToReplace, bodyText);
|
||||
|
||||
|
|
@ -196,21 +193,19 @@ function mapStringToLink(str) {
|
|||
// Function to convert a string, into a matching global state item.
|
||||
function mapStringToState(str) {
|
||||
// Pull all matches out of the string.
|
||||
const regexExp = new RegExp('{([^{}]*?):([^{}]*?)}', 'g');
|
||||
const regexExp = /{([^{}]*?):([^{}]*?)}/g;
|
||||
const regexMatches = [...str.matchAll(regexExp)];
|
||||
const globalStateMatches = regexMatches.filter(match => {
|
||||
return match[1] === dynamicStrings.GLOBAL_STATE;
|
||||
});
|
||||
const globalStateMatches = regexMatches.filter((match) => match[1] === dynamicStrings.GLOBAL_STATE);
|
||||
|
||||
// Our final string value that will be built from the matches.
|
||||
let stringBuilder = '';
|
||||
const stringBuilder = '';
|
||||
|
||||
for (const match of globalStateMatches) {
|
||||
// Reset store state for each match.
|
||||
const valueFromStore = getStoreValueFromString(match[2]);
|
||||
const valueFromStore = getStoreValueFromString(match[2]);
|
||||
if (!valueFromStore) {
|
||||
console.warning('Unable to resolve global state data.');
|
||||
return '' // if we can't map our string to state data, return an empty string.
|
||||
return ''; // if we can't map our string to state data, return an empty string.
|
||||
}
|
||||
const stringWithReplacement = str.replace(match[0], valueFromStore);
|
||||
|
||||
|
|
@ -231,7 +226,7 @@ function getStoreValueFromString(str) {
|
|||
|
||||
let storeOrStateObject = useMainStore();
|
||||
for (const s of str.split('.')) {
|
||||
if (s === 'getters') continue; //For backward compatibility
|
||||
if (s === 'getters') continue; // For backward compatibility
|
||||
if (storeOrStateObject[s] != undefined) {
|
||||
storeOrStateObject = storeOrStateObject[s];
|
||||
} else {
|
||||
|
|
@ -241,9 +236,9 @@ function getStoreValueFromString(str) {
|
|||
return storeOrStateObject ?? '';
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
/// ////////////////////////////////
|
||||
// If Statement Processing Logic //
|
||||
///////////////////////////////////
|
||||
/// ////////////////////////////////
|
||||
|
||||
/**
|
||||
* Recursive function - replaces all instances of if statements from the CMS that utilize the specified ifConditionKeyword
|
||||
|
|
@ -253,23 +248,22 @@ function getStoreValueFromString(str) {
|
|||
* @returns The processed string
|
||||
*/
|
||||
export function processIfStatements(str, ifConditionKeyword, replacePlaceholderCallback) {
|
||||
const containsRelevantIfStatement = new RegExp('{if:' + ifConditionKeyword + ':.+?}', 'g').test(str);
|
||||
const containsRelevantIfStatement = new RegExp(`{if:${ifConditionKeyword}:.+?}`, 'g').test(str);
|
||||
|
||||
const hasEmbeddedCrLf = /\r?\n|\r/g.test(str);
|
||||
if (!containsRelevantIfStatement) {
|
||||
return str;
|
||||
} else {
|
||||
const ifStatementRegexExpression = getIfStatementRegexExpression();
|
||||
const ifStatementRegexMatches = [...str.matchAll(ifStatementRegexExpression)];
|
||||
const completeIfStatementArray = getAndFlagFirstNonNestedIfStatementWithKeyword(ifStatementRegexMatches,
|
||||
ifConditionKeyword);
|
||||
executeIfStatementAndSetProcessedStrings(completeIfStatementArray,
|
||||
replacePlaceholderCallback);
|
||||
const reconstructedPostProcessedString = joinProcessedRegexArray(ifStatementRegexMatches);
|
||||
return processIfStatements(reconstructedPostProcessedString,
|
||||
ifConditionKeyword,
|
||||
replacePlaceholderCallback);
|
||||
}
|
||||
const ifStatementRegexExpression = getIfStatementRegexExpression();
|
||||
const ifStatementRegexMatches = [...str.matchAll(ifStatementRegexExpression)];
|
||||
const completeIfStatementArray = getAndFlagFirstNonNestedIfStatementWithKeyword(ifStatementRegexMatches,
|
||||
ifConditionKeyword);
|
||||
executeIfStatementAndSetProcessedStrings(completeIfStatementArray,
|
||||
replacePlaceholderCallback);
|
||||
const reconstructedPostProcessedString = joinProcessedRegexArray(ifStatementRegexMatches);
|
||||
return processIfStatements(reconstructedPostProcessedString,
|
||||
ifConditionKeyword,
|
||||
replacePlaceholderCallback);
|
||||
}
|
||||
|
||||
function getAndFlagFirstNonNestedIfStatementWithKeyword(matches, ifConditionKeyword) {
|
||||
|
|
@ -342,20 +336,18 @@ function executeIfStatementAndSetProcessedStrings(ifStatementArray, replacePlace
|
|||
function setProcessedStringOnEntry(entry, isInsideDesiredBlock) {
|
||||
if (!isInsideDesiredBlock) {
|
||||
entry.groups.processedString = '';
|
||||
} else if (entry.groups.isIfStatement) {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.ifTrailingString
|
||||
: entry[0];
|
||||
} else if (entry.groups.isElseStatement) {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.elseTrailingString
|
||||
: entry[0];
|
||||
} else {
|
||||
if (entry.groups.isIfStatement) {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.ifTrailingString
|
||||
: entry[0];
|
||||
} else if (entry.groups.isElseStatement) {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.elseTrailingString
|
||||
: entry[0];
|
||||
} else {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.endTrailingString
|
||||
: entry[0];
|
||||
}
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.endTrailingString
|
||||
: entry[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -364,43 +356,43 @@ function getIfStatementRegexExpression() {
|
|||
// {if:...} or {else} or {end}
|
||||
const anyLogicOperatorNonCapture = '(?:{(?:end|else|if:.*?)})';
|
||||
// NOTE: ?<variableName> syntax stores the captured match like so: match.groups.variableName
|
||||
const matchStartOfString =
|
||||
'(?<processedString>^.+?)' + // Match and Capture all characters (lazy), cannot be empty
|
||||
'(?=(?:{if))'; // Looks ahead but does not capture {if
|
||||
const matchIfOperator =
|
||||
'(?<isIfStatement>{if:)' + // Match & Capture {if:
|
||||
'(?<ifConditionType>.*?):' + // Match all chars up to and including next ':' - Capture all chars up to ':'
|
||||
'(?<ifCondition>.*?)}' + // Match all chars up to and including next '}' - Capture all chars up to '}'
|
||||
'(?<ifTrailingString>.*?)' + // Match and Capture all characters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
')'; // Looks ahead but does not capture the next logic operator
|
||||
const matchElseOperator =
|
||||
'(?<isElseStatement>{else})' + // Match & Capture {else}
|
||||
'(?<elseTrailingString>.*?)' + // Match & Capture all characters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
')'; // Looks ahead but does not capture the next logic operator
|
||||
const matchEndOperator =
|
||||
'(?<isEndStatement>{end})' + // Match & Capture {end}
|
||||
'(?<endTrailingString>.*?)' + // Match & Capture all chracters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
'|$)'; // Looks ahead but does not capture the next logic operator
|
||||
const matchStartOfString
|
||||
= '(?<processedString>^.+?)' // Match and Capture all characters (lazy), cannot be empty
|
||||
+ '(?=(?:{if))'; // Looks ahead but does not capture {if
|
||||
const matchIfOperator
|
||||
= '(?<isIfStatement>{if:)' // Match & Capture {if:
|
||||
+ '(?<ifConditionType>.*?):' // Match all chars up to and including next ':' - Capture all chars up to ':'
|
||||
+ '(?<ifCondition>.*?)}' // Match all chars up to and including next '}' - Capture all chars up to '}'
|
||||
+ '(?<ifTrailingString>.*?)' // Match and Capture all characters (lazy), can be empty
|
||||
+ `(?=${
|
||||
anyLogicOperatorNonCapture
|
||||
})`; // Looks ahead but does not capture the next logic operator
|
||||
const matchElseOperator
|
||||
= '(?<isElseStatement>{else})' // Match & Capture {else}
|
||||
+ '(?<elseTrailingString>.*?)' // Match & Capture all characters (lazy), can be empty
|
||||
+ `(?=${
|
||||
anyLogicOperatorNonCapture
|
||||
})`; // Looks ahead but does not capture the next logic operator
|
||||
const matchEndOperator
|
||||
= '(?<isEndStatement>{end})' // Match & Capture {end}
|
||||
+ '(?<endTrailingString>.*?)' // Match & Capture all characters (lazy), can be empty
|
||||
+ `(?=${
|
||||
anyLogicOperatorNonCapture
|
||||
}|$)`; // Looks ahead but does not capture the next logic operator
|
||||
// Combine all matching patterns, separated by 'or' pipes
|
||||
return new RegExp(matchStartOfString +
|
||||
'|' +
|
||||
matchIfOperator +
|
||||
'|' +
|
||||
matchElseOperator +
|
||||
'|' +
|
||||
matchEndOperator,
|
||||
return new RegExp(`${matchStartOfString
|
||||
}|${
|
||||
matchIfOperator
|
||||
}|${
|
||||
matchElseOperator
|
||||
}|${
|
||||
matchEndOperator}`,
|
||||
'g');
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
/// ///////////////////////////////////////
|
||||
// End of If Statement Processing Logic //
|
||||
//////////////////////////////////////////
|
||||
/// ///////////////////////////////////////
|
||||
|
||||
export function doesCopyContainTextLink(copy) {
|
||||
return copy.includes(dynamicStrings.TEXT_LINK);
|
||||
|
|
@ -409,12 +401,12 @@ export function doesCopyContainTextLink(copy) {
|
|||
export function setupModalLinks(context) {
|
||||
context.$nextTick(() => {
|
||||
const elements = document.getElementsByClassName('modal-text');
|
||||
for (let element of elements){
|
||||
for (const element of elements) {
|
||||
const target = element.getAttribute('modalTarget');
|
||||
if (target) {
|
||||
element.addEventListener('click', () => context.$refs[target].openModal() );
|
||||
element.addEventListener('click', () => context.$refs[target].openModal());
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,11 +106,9 @@ export function updateSessionIdCookie() {
|
|||
createOrUpdateCookie(cookieNames.SESSION_ID, getSessionIdValue(), { maxAge: 60 * 30 });
|
||||
}
|
||||
|
||||
export function setCookieProperties(
|
||||
properties,
|
||||
{ useDefaultISSCookieAttributes = true, maxAge, isSecure }
|
||||
) {
|
||||
if (typeof properties == 'object') {
|
||||
export function setCookieProperties(properties,
|
||||
{ useDefaultISSCookieAttributes = true, maxAge, isSecure }) {
|
||||
if (typeof properties === 'object') {
|
||||
Object.keys(properties).forEach((key) => {
|
||||
createOrUpdateCookie(key, properties[key], {
|
||||
useDefaultISSCookieAttributes,
|
||||
|
|
@ -132,8 +130,8 @@ export function setCookieProperties(
|
|||
Takes an object with properties to set. Will overwrite existing properties.
|
||||
*/
|
||||
function setISSCookieProperties(properties) {
|
||||
if (typeof properties == 'object') {
|
||||
let cookie = getISSCookie();
|
||||
if (typeof properties === 'object') {
|
||||
const cookie = getISSCookie();
|
||||
|
||||
if (cookie !== null) {
|
||||
Object.keys(properties).forEach((key) => {
|
||||
|
|
@ -150,11 +148,8 @@ function setISSCookieProperties(properties) {
|
|||
Used to create a cookie.
|
||||
`useDefaultISSCookieAttributes` will set the path and domain to our defaults
|
||||
*/
|
||||
function createOrUpdateCookie(
|
||||
key,
|
||||
value = '',
|
||||
{ useDefaultISSCookieAttributes = true, maxAge, isSecure = true }
|
||||
) {
|
||||
function createOrUpdateCookie(key, value = '',
|
||||
{ useDefaultISSCookieAttributes = true, maxAge, isSecure = true }) {
|
||||
let cookieToAdd = `${key}=${value}; `;
|
||||
|
||||
if (useDefaultISSCookieAttributes) {
|
||||
|
|
@ -163,7 +158,7 @@ function createOrUpdateCookie(
|
|||
if (isSecure && !isLocalhost()) {
|
||||
cookieToAdd += 'secure; ';
|
||||
}
|
||||
if (!isNaN(maxAge)) {
|
||||
if (!Number.isNaN(maxAge)) {
|
||||
cookieToAdd += `max-age=${maxAge};`;
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +169,7 @@ function createOrUpdateCookie(
|
|||
Gets current domain without the subdomain for cookie.
|
||||
*/
|
||||
function getDomainWithoutSubdomain() {
|
||||
let url = location.hostname;
|
||||
const url = location.hostname;
|
||||
if (isLocalhost()) {
|
||||
return 'localhost';
|
||||
}
|
||||
|
|
@ -191,8 +186,8 @@ function getDomainWithoutSubdomain() {
|
|||
Gets cookie value by name, returns empty string if not found.
|
||||
*/
|
||||
function getCookieValueByName(name) {
|
||||
const value = '; ' + document.cookie;
|
||||
const parts = value.split('; ' + name + '=');
|
||||
const value = `; ${document.cookie}`;
|
||||
const parts = value.split(`; ${name}=`);
|
||||
|
||||
if (parts.length === 2) {
|
||||
return parts.pop().split(';').shift();
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
import { randomUUID } from 'crypto';
|
||||
|
||||
export function getRandomString(minLength = 1, maxLength = 100) {
|
||||
const length = getRandomInt(minLength, maxLength + 1);
|
||||
let result = '';
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const charactersLength = characters.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getRandomInt(min = 0, max = 1000) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
|
|
@ -26,3 +15,14 @@ export function getRandomBoolean() {
|
|||
const index = getRandomInt(0, 2);
|
||||
return bools[index];
|
||||
}
|
||||
|
||||
export function getRandomString(minLength = 1, maxLength = 100) {
|
||||
const length = getRandomInt(minLength, maxLength + 1);
|
||||
let result = '';
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const charactersLength = characters.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ export default {
|
|||
// Adds event to the bus given its category, subcategory, and eventValue;
|
||||
addEventToBus(category, subCategory, eventValue) {
|
||||
useMainStore().addEventToBus({
|
||||
category: category,
|
||||
subCategory: subCategory,
|
||||
eventValue: eventValue,
|
||||
category,
|
||||
subCategory,
|
||||
eventValue
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -16,8 +16,8 @@ export default {
|
|||
|
||||
if (event) {
|
||||
useMainStore().removeEventFromBus({
|
||||
category: category,
|
||||
subCategory: subCategory,
|
||||
category,
|
||||
subCategory
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ useMainStore().removeEventFromBus = jest.fn();
|
|||
useMainStore().eventBusItem = jest.fn();
|
||||
|
||||
describe('event-bus.js', () => {
|
||||
let event = {
|
||||
const event = {
|
||||
isDismissible: true,
|
||||
messageCopy: 'You can get a quote by starting on this page.',
|
||||
messageHeadline: "We're sorry, something went wrong.",
|
||||
|
|
@ -20,15 +20,13 @@ describe('event-bus.js', () => {
|
|||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
})
|
||||
});
|
||||
|
||||
it('removes items when readandpop is called', () => {
|
||||
useMainStore().eventBusItem.mockReturnValueOnce(event);
|
||||
|
||||
const eventValue = eventBus.readAndPopEventFromBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND
|
||||
);
|
||||
const eventValue = eventBus.readAndPopEventFromBus(globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND);
|
||||
|
||||
expect(useMainStore().eventBusItem).toBeCalledTimes(1);
|
||||
expect(useMainStore().removeEventFromBus).toBeCalledTimes(1);
|
||||
|
|
@ -37,10 +35,8 @@ describe('event-bus.js', () => {
|
|||
it("doesn't try to remove items when readandpop is called and item doesn't exist", () => {
|
||||
useMainStore().eventBusItem.mockReturnValueOnce(undefined);
|
||||
|
||||
const eventValue = eventBus.readAndPopEventFromBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND
|
||||
);
|
||||
const eventValue = eventBus.readAndPopEventFromBus(globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND);
|
||||
|
||||
expect(useMainStore().eventBusItem).toBeCalledTimes(1);
|
||||
expect(useMainStore().removeEventFromBus).toBeCalledTimes(0);
|
||||
|
|
@ -49,21 +45,17 @@ describe('event-bus.js', () => {
|
|||
it('returns event from bus', () => {
|
||||
useMainStore().eventBusItem.mockReturnValueOnce(event);
|
||||
|
||||
const eventValue = eventBus.readEventFromBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND
|
||||
);
|
||||
const eventValue = eventBus.readEventFromBus(globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND);
|
||||
|
||||
expect(eventValue).toBe(event);
|
||||
});
|
||||
|
||||
it('Reads event from bus, should have event value.', () => {
|
||||
// Arrange / Act
|
||||
eventBus.addEventToBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
eventBus.addEventToBus(globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND,
|
||||
event
|
||||
);
|
||||
event);
|
||||
|
||||
expect(useMainStore().addEventToBus).toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@ export function settleAllPromises(promiseResultMap) {
|
|||
// Pull our keys out of the promise 'table'
|
||||
const promiseNames = Object.entries(promiseResultMap);
|
||||
|
||||
return Promise.allSettled(
|
||||
promiseNames.map((e) =>
|
||||
e[1]).map((n) =>
|
||||
n.promise)
|
||||
).then((results) => {
|
||||
return Promise.allSettled(promiseNames.map((e) => e[1]).map((n) => n.promise)).then((results) => {
|
||||
const resultMap = {};
|
||||
|
||||
// Build a map of the results
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
import { useMainStore } from '@/store';
|
||||
|
||||
export async function getServiceabilityDetails(serviceZipCode, lineItems) {
|
||||
const serviceabilityDetails = await useMainStore().getServiceabilityDetails(
|
||||
{
|
||||
serviceZipCode: serviceZipCode,
|
||||
lineItems: lineItems,
|
||||
},
|
||||
false
|
||||
);
|
||||
const serviceabilityDetails = await useMainStore().getServiceabilityDetails({
|
||||
serviceZipCode,
|
||||
lineItems
|
||||
},
|
||||
false);
|
||||
return Promise.resolve(serviceabilityDetails);
|
||||
}
|
||||
|
||||
export async function getZipCodeData(zipCode) {
|
||||
const serviceZipValidationResponse = await useMainStore().validateZip(
|
||||
{ zip: zipCode }
|
||||
);
|
||||
const serviceZipValidationResponse = await useMainStore().validateZip({ zip: zipCode });
|
||||
|
||||
return {
|
||||
containsMilitaryBase: serviceZipValidationResponse.data.containsMilitaryBase,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ export function isAnalyticsSessionStillActive() {
|
|||
const lastTouchedValue = getISSCookie().LastTouched;
|
||||
const timeoutAmount = applicationConfig.ANALYTICS_SESSION_TIMEOUT_MINUTES;
|
||||
|
||||
const isMoreThanHalfHourAgo =
|
||||
(new Date() - new Date(lastTouchedValue)) / 60000 > timeoutAmount;
|
||||
const isMoreThanHalfHourAgo = (new Date() - new Date(lastTouchedValue)) / 60000 > timeoutAmount;
|
||||
|
||||
if (isMoreThanHalfHourAgo) {
|
||||
return false;
|
||||
|
|
@ -19,6 +18,7 @@ export function isAnalyticsSessionStillActive() {
|
|||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -35,6 +35,7 @@ export function isSavedSessionStillActive() {
|
|||
|
||||
return !isSavedSessionTimedOut;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -9,15 +9,7 @@ import {
|
|||
getCookieDomainValue,
|
||||
setCookieProperties
|
||||
} from '@/helpers/cookie-helper';
|
||||
import {
|
||||
analyticsPageEvents,
|
||||
GaCategories,
|
||||
GaActions,
|
||||
GaLabels,
|
||||
GaEvents,
|
||||
ValueToLogTypes
|
||||
} from '@/constants/analytics';
|
||||
import { routerParams } from '@/router/router-constants/router-params';
|
||||
import { GaActions } from '@/constants/analytics';
|
||||
import { queryStrings } from '@/constants/query-strings';
|
||||
import { useMainStore } from '@/store';
|
||||
import { mapStores } from 'pinia';
|
||||
|
|
@ -53,7 +45,7 @@ export function getMountOptions(mockData) {
|
|||
mocks.prependActionToMethod = jest.fn();
|
||||
|
||||
const global = {
|
||||
mocks: mocks,
|
||||
mocks,
|
||||
mixins: [mockMixin],
|
||||
plugins: [pinia],
|
||||
stubs: {
|
||||
|
|
@ -78,10 +70,10 @@ export const cookies = {
|
|||
|
||||
export function setupCookies({ ISSCookieValue = '', includeHeritageCookie = true }) {
|
||||
Object.keys(cookies).forEach((key) => {
|
||||
const cookieValue =
|
||||
key == cookieNames.ISS_SESSION_INFO ? ISSCookieValue : cookies[key];
|
||||
if (includeHeritageCookie || key != cookieNames.ISS_SESSION_INFO)
|
||||
const cookieValue = key === cookieNames.ISS_SESSION_INFO ? ISSCookieValue : cookies[key];
|
||||
if (includeHeritageCookie || key !== cookieNames.ISS_SESSION_INFO) {
|
||||
setCookieProperties({ [key]: cookieValue }, { isSecure: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ export function regex(expression, errorMessage) {
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,18 +161,19 @@ describe('address-questions.vue', () => {
|
|||
autocompleteElement.addEventListener = jest
|
||||
.fn()
|
||||
.mockImplementation((eventName, callbackFunction) => {
|
||||
if (eventName == 'change') {
|
||||
if (eventName === 'change') {
|
||||
changeEventCallbackFunction = callbackFunction;
|
||||
}
|
||||
});
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
querySelectorFunction(query) {
|
||||
if (query == '.pac-container .pac-item') {
|
||||
if (query === '.pac-container .pac-item') {
|
||||
const element = document.createElement('div');
|
||||
element.textContent = '123 Test Street';
|
||||
return element;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
geocoderResult: {
|
||||
address_components: [
|
||||
|
|
@ -276,7 +277,7 @@ describe('address-questions.vue', () => {
|
|||
autocompleteElement.addEventListener = jest
|
||||
.fn()
|
||||
.mockImplementation((eventName, callbackFunction) => {
|
||||
if (eventName == 'change') {
|
||||
if (eventName === 'change') {
|
||||
changeEventCallbackFunction = callbackFunction;
|
||||
}
|
||||
});
|
||||
|
|
@ -306,18 +307,19 @@ describe('address-questions.vue', () => {
|
|||
autocompleteElement.addEventListener = jest
|
||||
.fn()
|
||||
.mockImplementation((eventName, callbackFunction) => {
|
||||
if (eventName == 'change') {
|
||||
if (eventName === 'change') {
|
||||
changeEventCallbackFunction = callbackFunction;
|
||||
}
|
||||
});
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
querySelectorFunction(query) {
|
||||
if (query == '.pac-container .pac-item') {
|
||||
if (query === '.pac-container .pac-item') {
|
||||
const element = document.createElement('div');
|
||||
element.textContent = '123 Test Street';
|
||||
return element;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -474,7 +476,6 @@ function setupMocks({
|
|||
const resultingMountOptions = getMountOptions({
|
||||
...mountOptions,
|
||||
router: {
|
||||
navigate: jest.fn(),
|
||||
navigate: jest.fn()
|
||||
},
|
||||
loadScript: jest.fn().mockResolvedValue()
|
||||
|
|
@ -522,7 +523,7 @@ function setupMocks({
|
|||
: mount(addressQuestions, resultingMountOptions);
|
||||
document.querySelector = jest.fn().mockImplementation((query) => {
|
||||
let result = null;
|
||||
if (query == '.pac-container') result = document.createElement('div');
|
||||
if (query === '.pac-container') result = document.createElement('div');
|
||||
else if (querySelectorFunction) {
|
||||
result = querySelectorFunction(query);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +1,6 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import ButtonQuestionModal from './button-question-modal';
|
||||
|
||||
describe('button-question-modal.vue', () => {
|
||||
it('Should display header text when QuestionText is defined in the CMS', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(ButtonQuestionModal, {
|
||||
mixins: [mockMixin],
|
||||
props: {
|
||||
cmsWidgetName: 'test'
|
||||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['QuestionText']));
|
||||
});
|
||||
|
||||
it('Should display subheader text when ButtonText is defined in the CMS', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(ButtonQuestionModal, {
|
||||
mixins: [mockMixin],
|
||||
props: {
|
||||
cmsWidgetName: 'test'
|
||||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['ButtonText']));
|
||||
});
|
||||
});
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
|
||||
return mockCmsContent[cmsFieldName];
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const mockCmsContent = {
|
||||
QuestionText: 'What caused damage.',
|
||||
ButtonText: 'Select an option.',
|
||||
|
|
@ -49,3 +15,35 @@ const mockCmsContent = {
|
|||
}
|
||||
]
|
||||
};
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => mockCmsContent[cmsFieldName])
|
||||
}
|
||||
};
|
||||
|
||||
describe('button-question-modal.vue', () => {
|
||||
it('Should display header text when QuestionText is defined in the CMS', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(ButtonQuestionModal, {
|
||||
mixins: [mockMixin],
|
||||
props: {
|
||||
cmsWidgetName: 'test'
|
||||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.QuestionText));
|
||||
});
|
||||
|
||||
it('Should display subheader text when ButtonText is defined in the CMS', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(ButtonQuestionModal, {
|
||||
mixins: [mockMixin],
|
||||
props: {
|
||||
cmsWidgetName: 'test'
|
||||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.ButtonText));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,23 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import contentGroupModal from './content-group-modal';
|
||||
import crypto from 'crypto';
|
||||
import contentGroupModal from './content-group-modal';
|
||||
|
||||
global.crypto = crypto;
|
||||
|
||||
const mockCmsContent = {
|
||||
HeaderText: 'Sample header text here.',
|
||||
SubheaderText: 'Sample subheader text here.',
|
||||
Image: 'https://www.sampleImage.sample',
|
||||
BodyText: 'Sample body text here.',
|
||||
FooterText: 'Sample footer text here.'
|
||||
};
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => mockCmsContent[cmsFieldName])
|
||||
}
|
||||
};
|
||||
|
||||
describe('content-group-modal.vue', () => {
|
||||
it('Should display header text when HeaderText is defined in the CMS', async () => {
|
||||
const wrapper = mount(contentGroupModal, {
|
||||
|
|
@ -13,7 +27,7 @@ describe('content-group-modal.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['HeaderText']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.HeaderText));
|
||||
});
|
||||
|
||||
it('Should display subheader text when SubheaderText is defined in the CMS', async () => {
|
||||
|
|
@ -24,7 +38,7 @@ describe('content-group-modal.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['SubheaderText']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.SubheaderText));
|
||||
});
|
||||
|
||||
it('Should insert image url when Image is defined in the CMS', async () => {
|
||||
|
|
@ -35,7 +49,7 @@ describe('content-group-modal.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['Image']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.Image));
|
||||
});
|
||||
|
||||
it('Should display body text when BodyText is defined in the CMS', async () => {
|
||||
|
|
@ -46,22 +60,6 @@ describe('content-group-modal.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['BodyText']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.BodyText));
|
||||
});
|
||||
});
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
|
||||
return mockCmsContent[cmsFieldName];
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const mockCmsContent = {
|
||||
HeaderText: 'Sample header text here.',
|
||||
SubheaderText: 'Sample subheader text here.',
|
||||
Image: 'https://www.sampleImage.sample',
|
||||
BodyText: 'Sample body text here.',
|
||||
FooterText: 'Sample footer text here.'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,14 @@ import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
|||
jest.mock('@/assets/img/loader.gif', () => 'loader.gif');
|
||||
jest.mock('@/assets/img/windshield.png', () => 'windshield.png');
|
||||
|
||||
function setupMocks() {
|
||||
const mountOptions = getMountOptions({
|
||||
});
|
||||
|
||||
const wrapper = shallowMount(loadingModal, mountOptions);
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
describe('loadingModal', () => {
|
||||
test('showModal sets modal visible', async () => {
|
||||
// Arrange
|
||||
|
|
@ -19,11 +27,3 @@ describe('loadingModal', () => {
|
|||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks() {
|
||||
const mountOptions = getMountOptions({
|
||||
});
|
||||
|
||||
const wrapper = shallowMount(loadingModal, mountOptions);
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import navButton from './nav-button'
|
||||
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import navButton from './nav-button';
|
||||
|
||||
describe('NavButton', () => {
|
||||
it('should display input when type is button', () => {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import questionsPageLayout from '@/iss-components/questions-page-layout/question
|
|||
// Supporting Files
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import baseMixin from '../../mixins/base-mixin';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import baseMixin from '../../mixins/base-mixin';
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock('@/helpers/layout-helper.js', () => ({
|
||||
|
|
@ -182,63 +182,59 @@ describe('questionsPageLayout.vue', () => {
|
|||
});
|
||||
|
||||
function setupMocks() {
|
||||
const baseStoreGettersPageData = () => {
|
||||
return {
|
||||
partsOrQuestions: [
|
||||
{
|
||||
parts: null,
|
||||
partQuestions: [
|
||||
{
|
||||
questionSequence: 1,
|
||||
questionText:
|
||||
const baseStoreGettersPageData = () => ({
|
||||
partsOrQuestions: [
|
||||
{
|
||||
parts: null,
|
||||
partQuestions: [
|
||||
{
|
||||
questionSequence: 1,
|
||||
questionText:
|
||||
'Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?',
|
||||
answers: [
|
||||
{
|
||||
answerResult: '',
|
||||
answerText: 'Yes',
|
||||
nextQuestionSequence: 2
|
||||
},
|
||||
{
|
||||
answerResult: '',
|
||||
answerText: 'No',
|
||||
nextQuestionSequence: 3
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerKey: 'Windshield-Single',
|
||||
answerData: null
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
const baseStoreGettersDamage = () => {
|
||||
return {
|
||||
partsQuestionAnswers: [
|
||||
{
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
result: 'FW04848',
|
||||
answeredQuestions: [
|
||||
{
|
||||
questionText:
|
||||
answers: [
|
||||
{
|
||||
answerResult: '',
|
||||
answerText: 'Yes',
|
||||
nextQuestionSequence: 2
|
||||
},
|
||||
{
|
||||
answerResult: '',
|
||||
answerText: 'No',
|
||||
nextQuestionSequence: 3
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerKey: 'Windshield-Single',
|
||||
answerData: null
|
||||
}
|
||||
]
|
||||
});
|
||||
const baseStoreGettersDamage = () => ({
|
||||
partsQuestionAnswers: [
|
||||
{
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
result: 'FW04848',
|
||||
answeredQuestions: [
|
||||
{
|
||||
questionText:
|
||||
'Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 1
|
||||
},
|
||||
{
|
||||
questionText:
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 1
|
||||
},
|
||||
{
|
||||
questionText:
|
||||
'Is your vehicle equipped with a heated windshield that melts snow and ice from underneath the windshield wiper blades?',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
const mountOptions = getMountOptions({
|
||||
mixins: [baseMixin, vehicleQuestionsMixin]
|
||||
});
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ import alert from '@/ux-components/alert/alert';
|
|||
import questionChain from '@/digital-components/question-chain/question-chain';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer';
|
||||
import loadingModal from '@/iss-components/loading-modal/loading-modal.vue';
|
||||
import loadingModal from '@/iss-components/loading-modal/loading-modal';
|
||||
|
||||
export default {
|
||||
name: 'questions-page',
|
||||
|
|
|
|||
|
|
@ -1,39 +1,6 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import siteFooter from './site-footer';
|
||||
|
||||
describe('site-footer.vue', () => {
|
||||
it('Should emit ForwardClicked on button click', async () => {
|
||||
// Act
|
||||
const wrapper = mount(siteFooter, {
|
||||
mixins: [mockMixin],
|
||||
});
|
||||
wrapper.vm.buttonClick();
|
||||
// Assert
|
||||
expect(wrapper.emitted()['forwardClicked'][0]).toHaveBeenCalled;
|
||||
});
|
||||
|
||||
it('Should emit BackClicked on link click', async () => {
|
||||
// Act
|
||||
const wrapper = mount(siteFooter, {
|
||||
mixins: [mockMixin],
|
||||
});
|
||||
wrapper.vm.linkClick();
|
||||
// Assert
|
||||
expect(wrapper.emitted()['backClicked'][0]).toHaveBeenCalled;
|
||||
});
|
||||
|
||||
it('Should change button text when update button text is called', async () => {
|
||||
// Act
|
||||
const wrapper = mount(siteFooter, {
|
||||
mixins: [mockMixin],
|
||||
});
|
||||
wrapper.vm.updateButtonText('newText');
|
||||
|
||||
// Assert
|
||||
expect(wrapper.componentVM.customButtontext).toBe('newText');
|
||||
});
|
||||
});
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn(),
|
||||
|
|
@ -41,3 +8,36 @@ const mockMixin = {
|
|||
getFooterInfoBoxHeight: jest.fn(() => 80)
|
||||
}
|
||||
};
|
||||
|
||||
describe('site-footer.vue', () => {
|
||||
it('Should emit ForwardClicked on button click', async () => {
|
||||
// Act
|
||||
const wrapper = mount(siteFooter, {
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
wrapper.vm.buttonClick();
|
||||
// Assert
|
||||
expect(wrapper.emitted().forwardClicked[0]).toHaveBeenCalled;
|
||||
});
|
||||
|
||||
it('Should emit BackClicked on link click', async () => {
|
||||
// Act
|
||||
const wrapper = mount(siteFooter, {
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
wrapper.vm.linkClick();
|
||||
// Assert
|
||||
expect(wrapper.emitted().backClicked[0]).toHaveBeenCalled;
|
||||
});
|
||||
|
||||
it('Should change button text when update button text is called', async () => {
|
||||
// Act
|
||||
const wrapper = mount(siteFooter, {
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
wrapper.vm.updateButtonText('newText');
|
||||
|
||||
// Assert
|
||||
expect(wrapper.componentVM.customButtontext).toBe('newText');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,15 +2,6 @@ import siteHeader from '@/iss-components/site-header/site-header';
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
|
||||
describe('site-header', () => {
|
||||
test('renders the logo image', () => {
|
||||
const wrapper = setupMocks({mountOptionsMockData: {}});
|
||||
|
||||
expect(wrapper.find('img')).toBeTruthy();
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({
|
||||
mountOptionsMockData = {}
|
||||
}) {
|
||||
|
|
@ -19,3 +10,12 @@ function setupMocks({
|
|||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
describe('site-header', () => {
|
||||
test('renders the logo image', () => {
|
||||
const wrapper = setupMocks({mountOptionsMockData: {} });
|
||||
|
||||
expect(wrapper.find('img')).toBeTruthy();
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@ describe('site sub header', () => {
|
|||
const subHeaderText = "let's fix your glass";
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn().mockImplementation(() => {
|
||||
return subHeaderText;
|
||||
})
|
||||
getCmsContent: jest.fn().mockImplementation(() => subHeaderText)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,17 @@ import { createPinia } from 'pinia';
|
|||
import { createApp } from 'vue';
|
||||
import steeringTextModal from './steering-text';
|
||||
|
||||
const mockCmsContent = {
|
||||
BodyText: 'MASteeringText'
|
||||
|
||||
};
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => mockCmsContent[cmsFieldName])
|
||||
}
|
||||
};
|
||||
|
||||
describe('steering-text.vue', () => {
|
||||
test('Should display steering text from CMS for state MA', async () => {
|
||||
// Act
|
||||
|
|
@ -15,26 +26,10 @@ describe('steering-text.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['BodyText']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.BodyText));
|
||||
});
|
||||
});
|
||||
|
||||
const vueApp = createApp(App);
|
||||
const pinia = createPinia();
|
||||
vueApp.use(pinia);
|
||||
///////////////
|
||||
// Constants //
|
||||
///////////////
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
|
||||
return mockCmsContent[cmsFieldName];
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const mockCmsContent = {
|
||||
BodyText: 'MASteeringText'
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,13 +24,12 @@ export default {
|
|||
|
||||
if (params.has(queryStrings.ISS_PAGE)) {
|
||||
return params.get(queryStrings.ISS_PAGE);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
logPageView(pageEvent) {
|
||||
const currentPageName = this.getPageNameByQueryString();
|
||||
var payload = {
|
||||
const payload = {
|
||||
userId: getDeviceIdValue(),
|
||||
sessionKey: getSessionKeyValue(),
|
||||
pageName: currentPageName,
|
||||
|
|
@ -47,15 +46,15 @@ export default {
|
|||
logCustomEvent(category, action, label, value) {
|
||||
const currentPageName = this.getPageNameByQueryString();
|
||||
|
||||
var payload = {
|
||||
const payload = {
|
||||
userId: getDeviceIdValue(),
|
||||
sessionKey: getSessionKeyValue(),
|
||||
pageName: currentPageName,
|
||||
sessionId: getSessionIdValue(),
|
||||
category: category,
|
||||
action: action,
|
||||
label: label,
|
||||
value: value,
|
||||
category,
|
||||
action,
|
||||
label,
|
||||
value,
|
||||
shouldUseSessionId: false,
|
||||
experimentsForUser: useMainStore().applicationUser.experiments
|
||||
};
|
||||
|
|
@ -69,8 +68,8 @@ export default {
|
|||
|
||||
const eventToBePushed = {
|
||||
event: GaEvents.GENERIC_EVENT,
|
||||
category: category,
|
||||
action: action,
|
||||
category,
|
||||
action,
|
||||
label: labelToLog,
|
||||
value: undefined,
|
||||
path: `/iss/?${queryStrings.ISS_PAGE}=${currentPageName}`
|
||||
|
|
@ -97,14 +96,14 @@ export default {
|
|||
},
|
||||
|
||||
pushExperimentsToDataLayer() {
|
||||
const experiments = useMainStore().applicationUser.experiments;
|
||||
const { experiments } = useMainStore().applicationUser;
|
||||
experiments?.forEach((exp) => {
|
||||
// Set Google Dimension Index based on experiment settings.
|
||||
let googleDimensionIndex = 99;
|
||||
|
||||
if (exp.settings[experimentSettings.GOOGLE_CUSTOM_DIMENSION_INDEX] !== undefined) {
|
||||
googleDimensionIndex =
|
||||
exp.settings[experimentSettings.GOOGLE_CUSTOM_DIMENSION_INDEX];
|
||||
googleDimensionIndex
|
||||
= exp.settings[experimentSettings.GOOGLE_CUSTOM_DIMENSION_INDEX];
|
||||
}
|
||||
|
||||
// Create object with dimension index and value.
|
||||
|
|
@ -113,7 +112,7 @@ export default {
|
|||
[`variationId_${googleDimensionIndex}`]: exp.variationId,
|
||||
[`experimentName_${googleDimensionIndex}`]: exp.universeName,
|
||||
[`variationName_${googleDimensionIndex}`]: exp.variationName,
|
||||
[`customDimension_${googleDimensionIndex}`]: `${exp.universeId}_${exp.variationId}_${exp.universeName}_${exp.variationName}`,
|
||||
[`customDimension_${googleDimensionIndex}`]: `${exp.universeId}_${exp.variationId}_${exp.universeName}_${exp.variationName}`
|
||||
};
|
||||
|
||||
// Push to the data layer with the Google Custom Dimension Index.
|
||||
|
|
@ -135,7 +134,7 @@ export default {
|
|||
async initSession() {
|
||||
const sid = getSessionIdValue();
|
||||
const skey = getSessionKeyValue();
|
||||
var payload = {
|
||||
const payload = {
|
||||
userId: getDeviceIdValue(),
|
||||
sessionId: sid,
|
||||
userAgent: navigator.userAgent,
|
||||
|
|
@ -146,28 +145,24 @@ export default {
|
|||
|
||||
if (response?.data) {
|
||||
if (response?.data.sessionKey && skey === 0) {
|
||||
setCookieProperties(
|
||||
{ [cookieNames.SESSION_KEY]: response?.data.sessionKey },
|
||||
setCookieProperties({ [cookieNames.SESSION_KEY]: response?.data.sessionKey },
|
||||
{
|
||||
useDefaultFunnelCookieAttributes: false
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
if (response?.data.sessionId && sid === '00000000-0000-0000-0000-000000000000') {
|
||||
setCookieProperties(
|
||||
{ [cookieNames.SESSION_ID]: response?.data.sessionId },
|
||||
setCookieProperties({ [cookieNames.SESSION_ID]: response?.data.sessionId },
|
||||
{
|
||||
maxAge: 60 * 30 // 30 minutes
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
noSession() {
|
||||
return (
|
||||
getSessionKeyValue() === 0 ||
|
||||
getSessionIdValue() === '00000000-0000-0000-0000-000000000000'
|
||||
getSessionKeyValue() === 0
|
||||
|| getSessionIdValue() === '00000000-0000-0000-0000-000000000000'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,20 +5,14 @@ import {
|
|||
GaCategories,
|
||||
GaActions,
|
||||
GaLabels,
|
||||
GaEvents,
|
||||
ValueToLogTypes
|
||||
} from '@/constants/analytics';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
describe('analyticsMixin.js', () => {
|
||||
test('logPageView: calls dispatch with type and payload', () => {
|
||||
const type = '';
|
||||
const payload = {};
|
||||
|
||||
const mockData = {
|
||||
};
|
||||
const mocks = setupMocksForJsFiles(mockData);
|
||||
|
||||
const testCookieValue = {
|
||||
sid: '10000000-0000-0000-0000-000000000001'
|
||||
};
|
||||
|
|
@ -31,9 +25,6 @@ describe('analyticsMixin.js', () => {
|
|||
});
|
||||
|
||||
test('logCustomEvent: calls dispatch with type and payload', () => {
|
||||
const mockData = {};
|
||||
const mocks = setupMocksForJsFiles(mockData);
|
||||
|
||||
useMainStore().logCustomEvent('someCat', 'someAction', 'someLabel', 'someVal');
|
||||
|
||||
expect(useMainStore().logCustomEvent).toBeCalled();
|
||||
|
|
@ -42,9 +33,7 @@ describe('analyticsMixin.js', () => {
|
|||
test('pushEventToGA, should call dataLayer push and logCustomEvent too', () => {
|
||||
// Arrange
|
||||
window.dataLayer = [];
|
||||
const mockData = {};
|
||||
const mocks = setupMocksForJsFiles(mockData);
|
||||
var mockDataLayer = [];
|
||||
const mockDataLayer = [];
|
||||
mockDataLayer.push({
|
||||
event: 'event',
|
||||
category: 'category',
|
||||
|
|
@ -64,7 +53,7 @@ describe('analyticsMixin.js', () => {
|
|||
test('pushEventToGA, should call dataLayer push and ValueToLogTypes.LAST_5 only logs last 5 of label', () => {
|
||||
// Arrange
|
||||
window.dataLayer = [];
|
||||
var expectedDataLayer = [];
|
||||
const expectedDataLayer = [];
|
||||
expectedDataLayer.push({
|
||||
event: 'event',
|
||||
category: 'category',
|
||||
|
|
@ -75,13 +64,11 @@ describe('analyticsMixin.js', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
analyticsMixin.methods.pushEventToGA(
|
||||
'category',
|
||||
analyticsMixin.methods.pushEventToGA('category',
|
||||
'action',
|
||||
'1111122222333333',
|
||||
false,
|
||||
ValueToLogTypes.LAST_5
|
||||
);
|
||||
ValueToLogTypes.LAST_5);
|
||||
|
||||
// Assert
|
||||
expect(expectedDataLayer).toEqual(expect.arrayContaining(window.dataLayer));
|
||||
|
|
@ -90,7 +77,7 @@ describe('analyticsMixin.js', () => {
|
|||
test('pushEventToGA, should call dataLayer push and ValueToLogTypes.LAST_5 logs only the last 3 characters for a 3 character string', () => {
|
||||
// Arrange
|
||||
window.dataLayer = [];
|
||||
var expectedDataLayer = [];
|
||||
const expectedDataLayer = [];
|
||||
expectedDataLayer.push({
|
||||
event: 'event',
|
||||
category: 'category',
|
||||
|
|
@ -101,13 +88,11 @@ describe('analyticsMixin.js', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
analyticsMixin.methods.pushEventToGA(
|
||||
'category',
|
||||
analyticsMixin.methods.pushEventToGA('category',
|
||||
'action',
|
||||
'111',
|
||||
false,
|
||||
ValueToLogTypes.LAST_5
|
||||
);
|
||||
ValueToLogTypes.LAST_5);
|
||||
|
||||
// Assert
|
||||
expect(expectedDataLayer).toEqual(expect.arrayContaining(window.dataLayer));
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ export default {
|
|||
return footerInfoBox ? footerInfoBox.offsetHeight : 0;
|
||||
},
|
||||
savePageDataToStore(page, data) {
|
||||
useMainStore().updatePageData({ page: page, data: data});
|
||||
useMainStore().updatePageData({ page, data });
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// store will be accessible globally as its id + 'Store'
|
||||
// store will be accessible globally as its id + 'Store'
|
||||
...mapStores(useMainStore),
|
||||
|
||||
navigationScenarios() {
|
||||
|
|
@ -44,10 +44,10 @@ export default {
|
|||
return dynamicStrings;
|
||||
},
|
||||
cssClassNameForCmsWidget() {
|
||||
return 'widget-name-' + this.cmsWidgetName;
|
||||
return `widget-name-${this.cmsWidgetName}`;
|
||||
},
|
||||
routerParams() {
|
||||
return routerParams;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import baseMixin from '@/mixins/base-mixin';
|
||||
import { shallowMount, mount } from '@vue/test-utils';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
|
||||
describe('base-mixin', () => {
|
||||
it('should set and get cms content', () => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useMainStore } from '@/store';
|
|||
export default {
|
||||
methods: {
|
||||
hasSettingEqualTo(settingName, settingValue) {
|
||||
return useMainStore().experimentSettings[settingName] == settingValue;
|
||||
return useMainStore().experimentSettings[settingName] === settingValue;
|
||||
},
|
||||
hasSetting(settingName) {
|
||||
return Object.hasOwn(useMainStore().experimentSettings, settingName);
|
||||
|
|
|
|||
|
|
@ -11,14 +11,10 @@ export default {
|
|||
return partsOrQuestions?.some((pq) => pq.parts?.length > 1);
|
||||
},
|
||||
hasChildPartQuestions(partsOrQuestions) {
|
||||
return partsOrQuestions?.some((pq) => {
|
||||
return pq.parts?.some((part) => part.childPartQuestions?.length > 0);
|
||||
});
|
||||
return partsOrQuestions?.some((pq) => pq.parts?.some((part) => part.childPartQuestions?.length > 0));
|
||||
},
|
||||
hasCapabilityQuestions(partsOrQuestions) {
|
||||
return partsOrQuestions?.some((pq) => {
|
||||
return pq.parts?.some((part) => part.requiresCapabilityQuestions === true);
|
||||
});
|
||||
return partsOrQuestions?.some((pq) => pq.parts?.some((part) => part.requiresCapabilityQuestions === true));
|
||||
},
|
||||
|
||||
// method to only include keys listed for lineItems.glassParts in
|
||||
|
|
@ -54,8 +50,8 @@ export default {
|
|||
];
|
||||
|
||||
return (
|
||||
orderedVehicleQuestionPages.indexOf(currentPage) -
|
||||
orderedVehicleQuestionPages.indexOf(issPage)
|
||||
orderedVehicleQuestionPages.indexOf(currentPage)
|
||||
- orderedVehicleQuestionPages.indexOf(issPage)
|
||||
);
|
||||
},
|
||||
currentPageComesBeforePage(currentPage = this.$route.query.issPage, issPage) {
|
||||
|
|
@ -75,18 +71,18 @@ export default {
|
|||
alreadyAnsweredQuestions?.forEach((answeredGlass) => {
|
||||
// if answeredGlass lacks any of these properties then exit
|
||||
if (
|
||||
!answeredGlass.glassLocation ||
|
||||
!answeredGlass.glassName ||
|
||||
!answeredGlass.answeredQuestions ||
|
||||
(!answeredGlass.result && !answeredGlass.partNum)
|
||||
!answeredGlass.glassLocation
|
||||
|| !answeredGlass.glassName
|
||||
|| !answeredGlass.answeredQuestions
|
||||
|| (!answeredGlass.result && !answeredGlass.partNum)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// test if glass parts match
|
||||
if (
|
||||
glass.glassLocation === answeredGlass.glassLocation &&
|
||||
glass.glassName === answeredGlass.glassName
|
||||
glass.glassLocation === answeredGlass.glassLocation
|
||||
&& glass.glassName === answeredGlass.glassName
|
||||
) {
|
||||
let answerString = '';
|
||||
|
||||
|
|
@ -98,12 +94,10 @@ export default {
|
|||
// determine which answer was previously chosen
|
||||
const chosenAns = glass.questions[
|
||||
answeredQuestion.questionNum - 1
|
||||
].answers.find((a) => {
|
||||
return (
|
||||
a.answerText.toUpperCase() ===
|
||||
answeredQuestion.selectedAnswerText.toUpperCase()
|
||||
);
|
||||
});
|
||||
].answers.find((a) => (
|
||||
a.answerText.toUpperCase()
|
||||
=== answeredQuestion.selectedAnswerText.toUpperCase()
|
||||
));
|
||||
// set the answerString to use for answerSelected
|
||||
if (chosenAns.nextQuestionSequence) {
|
||||
answerString = `${answeredQuestion.questionNum}|nextQuestion|${chosenAns.nextQuestionSequence}|${chosenAns.answerText}`;
|
||||
|
|
@ -112,8 +106,8 @@ export default {
|
|||
}
|
||||
|
||||
// mark this question as answered (question-chain will read this)
|
||||
glass.questions[answeredQuestion.questionNum - 1].answerSelected =
|
||||
answerString;
|
||||
glass.questions[answeredQuestion.questionNum - 1].answerSelected
|
||||
= answerString;
|
||||
// mark this question as suppressed if needed (question-chain uses this)
|
||||
if (answeredQuestion.suppressThisQuestion) {
|
||||
glass.questions[
|
||||
|
|
@ -132,8 +126,8 @@ export default {
|
|||
|
||||
// add answerData to current glass
|
||||
glass.answerData = {
|
||||
answerResult: answerResult,
|
||||
answeredQuestions: answeredGlass.answeredQuestions,
|
||||
answerResult,
|
||||
answeredQuestions: answeredGlass.answeredQuestions
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
@ -252,8 +246,8 @@ export default {
|
|||
// if the duplicate is 1ST question in array, set indexToSuppressTo
|
||||
if (questionIndex === 0) {
|
||||
if (
|
||||
!indexToSuppressTo ||
|
||||
matchedAnswer.nextQuestionSequence < indexToSuppressTo
|
||||
!indexToSuppressTo
|
||||
|| matchedAnswer.nextQuestionSequence < indexToSuppressTo
|
||||
) {
|
||||
indexToSuppressTo = matchedAnswer.nextQuestionSequence;
|
||||
}
|
||||
|
|
@ -265,8 +259,8 @@ export default {
|
|||
q.answers.forEach((a) => {
|
||||
// revert any previously set nextQuestion logic modifications
|
||||
if (
|
||||
a.originalNextQuestionSequence ===
|
||||
question.questionSequence
|
||||
a.originalNextQuestionSequence
|
||||
=== question.questionSequence
|
||||
) {
|
||||
// restore original nextQuestionSequence
|
||||
a.nextQuestionSequence = a.originalNextQuestionSequence;
|
||||
|
|
@ -283,16 +277,16 @@ export default {
|
|||
|
||||
// update questions that lead to duplicated question
|
||||
if (matchedAnswer.nextQuestionSequence) {
|
||||
a.originalNextQuestionSequence =
|
||||
a.nextQuestionSequence;
|
||||
a.nextQuestionSequence =
|
||||
matchedAnswer.nextQuestionSequence;
|
||||
a.originalNextQuestionSequence
|
||||
= a.nextQuestionSequence;
|
||||
a.nextQuestionSequence
|
||||
= matchedAnswer.nextQuestionSequence;
|
||||
} else {
|
||||
a.originalNextQuestionSequence =
|
||||
a.nextQuestionSequence;
|
||||
a.originalNextQuestionSequence
|
||||
= a.nextQuestionSequence;
|
||||
a.nextQuestionSequence = null;
|
||||
a.originalAnswerResult =
|
||||
a.originalAnswerResult || a.answerResult;
|
||||
a.originalAnswerResult
|
||||
= a.originalAnswerResult || a.answerResult;
|
||||
a.answerResult = matchedAnswer.answerResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -303,9 +297,7 @@ export default {
|
|||
question.suppressThisQuestion = true;
|
||||
|
||||
// are there any questions left that are not suppressed?
|
||||
const remainingQuestions = glass.questions.filter((q) => {
|
||||
return !q.suppressThisQuestion;
|
||||
});
|
||||
const remainingQuestions = glass.questions.filter((q) => !q.suppressThisQuestion);
|
||||
|
||||
if (remainingQuestions.length < 1) {
|
||||
// this is the final answer for this glass piece
|
||||
|
|
@ -315,14 +307,14 @@ export default {
|
|||
questionText: question.questionText,
|
||||
selectedAnswerText: matchedAnswer.answerText,
|
||||
questionNum: question.questionSequence,
|
||||
suppressThisQuestion: question.suppressThisQuestion,
|
||||
suppressThisQuestion: question.suppressThisQuestion
|
||||
};
|
||||
// set the answerData (used as indicator that it has been already answered)
|
||||
glass.answerData = {
|
||||
answerResult: matchedAnswer.nextQuestionSequence
|
||||
? matchedAnswer.nextQuestionSequence
|
||||
: matchedAnswer.answerResult,
|
||||
answeredQuestions: [answeredQuestionObj],
|
||||
answeredQuestions: [answeredQuestionObj]
|
||||
};
|
||||
|
||||
// suppress this glass piece because it has an answer
|
||||
|
|
@ -332,8 +324,7 @@ export default {
|
|||
});
|
||||
|
||||
// Update key to force re-render of glass piece with duplicate question in case user changes previous related answer in the chain
|
||||
self.questionsData[glassIndex].key =
|
||||
self.questionsData[glassIndex].key + Date.now().toString();
|
||||
self.questionsData[glassIndex].key += Date.now().toString();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -341,7 +332,7 @@ export default {
|
|||
// set final answer data for the current answered glass part
|
||||
self.questionsData[answer.index].answerData = {
|
||||
answerResult: answer.answerResult,
|
||||
answeredQuestions: answer.answeredQuestions,
|
||||
answeredQuestions: answer.answeredQuestions
|
||||
};
|
||||
|
||||
// this part has been fully answered, so advance to next part's question chain
|
||||
|
|
@ -360,74 +351,60 @@ export default {
|
|||
const currentPage = self.$route.query.issPage;
|
||||
|
||||
const hasPartQuestions = this.hasPartQuestions(partsOrQuestions);
|
||||
const hasGlassLocationWithMultipleParts =
|
||||
this.hasGlassLocationWithMultipleParts(partsOrQuestions);
|
||||
const hasGlassLocationWithMultipleParts
|
||||
= this.hasGlassLocationWithMultipleParts(partsOrQuestions);
|
||||
const hasChildPartQuestions = this.hasChildPartQuestions(partsOrQuestions);
|
||||
const hasCapabilityQuestions = this.hasCapabilityQuestions(partsOrQuestions);
|
||||
|
||||
if (hasPartQuestions && this.currentPageComesBeforePage(currentPage, issPageValues.PART_QUESTIONS))
|
||||
{
|
||||
self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS, self.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions: partsOrQuestions }
|
||||
);
|
||||
} else if (hasGlassLocationWithMultipleParts && this.currentPageComesBeforePage(currentPage, issPageValues.VEHICLE_PARTS))
|
||||
{
|
||||
if (hasPartQuestions && this.currentPageComesBeforePage(currentPage, issPageValues.PART_QUESTIONS)) {
|
||||
self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS, self.$route, {}, {}, { partsOrQuestions });
|
||||
} else if (hasGlassLocationWithMultipleParts && this.currentPageComesBeforePage(currentPage, issPageValues.VEHICLE_PARTS)) {
|
||||
// if multiple parts on any glass
|
||||
// go to vehicle-parts page and pass the partsData
|
||||
self.$router.navigate(
|
||||
self.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
self.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions: partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
} else if (
|
||||
hasChildPartQuestions &&
|
||||
this.currentPageComesBeforePage(currentPage, issPageValues.MOLDING_QUESTIONS)
|
||||
hasChildPartQuestions
|
||||
&& this.currentPageComesBeforePage(currentPage, issPageValues.MOLDING_QUESTIONS)
|
||||
) {
|
||||
// if any childpart questions
|
||||
// go to molding-questions page and pass the partsData
|
||||
self.$router.navigate(
|
||||
self.navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
self.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions: partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
} else if (
|
||||
hasCapabilityQuestions &&
|
||||
this.currentPageComesBeforePage(currentPage, issPageValues.CAPABILITY_QUESTIONS)
|
||||
hasCapabilityQuestions
|
||||
&& this.currentPageComesBeforePage(currentPage, issPageValues.CAPABILITY_QUESTIONS)
|
||||
) {
|
||||
// if has capability questions
|
||||
// go to capability-questions page and pass the partsData
|
||||
|
||||
// mimic part-questions page data for consistency
|
||||
for (let partOrQuestion of partsOrQuestions) {
|
||||
for (const partOrQuestion of partsOrQuestions) {
|
||||
if (this.hasCapabilityQuestions([partOrQuestion])) {
|
||||
let capabilityQuestionsForGlassLocation = (await useMainStore().getCapabilityQuestions(useMainStore().vehicle.carId, partOrQuestion.parts[0].partNumber)).data;
|
||||
const capabilityQuestionsForGlassLocation = (await useMainStore().getCapabilityQuestions(useMainStore().vehicle.carId, partOrQuestion.parts[0].partNumber)).data;
|
||||
|
||||
capabilityQuestionsForGlassLocation.forEach((question) => {
|
||||
question.answers = question.answers.map((answer) => {
|
||||
return {
|
||||
...answer,
|
||||
answerResult: answer.answerResult1
|
||||
};
|
||||
});
|
||||
question.answers = question.answers.map((answer) => ({
|
||||
...answer,
|
||||
answerResult: answer.answerResult1
|
||||
}));
|
||||
});
|
||||
|
||||
partOrQuestion.capabilityQuestions = capabilityQuestionsForGlassLocation;
|
||||
}
|
||||
}
|
||||
|
||||
self.$router.navigate(
|
||||
self.navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
self.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
} else {
|
||||
// if single parts only
|
||||
const collectedGlassParts = this.reducedGlassPartsArray(partsOrQuestions);
|
||||
|
|
@ -435,28 +412,27 @@ export default {
|
|||
// save to store lineItems.glassParts
|
||||
useMainStore().updateGlassParts(collectedGlassParts);
|
||||
|
||||
self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,self.$route);
|
||||
self.$router.navigate(self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS, self.$route);
|
||||
}
|
||||
},
|
||||
|
||||
navigateBack(vm) {
|
||||
const self = vm ?? this;
|
||||
const partsOrQuestions = (
|
||||
self.mainStore.pageData(issPageValues.CAPABILITY_QUESTIONS) ??
|
||||
self.mainStore.pageData(issPageValues.MOLDING_QUESTIONS) ??
|
||||
self.mainStore.pageData(issPageValues.VEHICLE_PARTS) ??
|
||||
self.mainStore.pageData(issPageValues.PART_QUESTIONS)
|
||||
self.mainStore.pageData(issPageValues.CAPABILITY_QUESTIONS)
|
||||
?? self.mainStore.pageData(issPageValues.MOLDING_QUESTIONS)
|
||||
?? self.mainStore.pageData(issPageValues.VEHICLE_PARTS)
|
||||
?? self.mainStore.pageData(issPageValues.PART_QUESTIONS)
|
||||
)?.partsOrQuestions;
|
||||
const hasPartQuestions = this.hasPartQuestions(partsOrQuestions);
|
||||
const hasGlassLocationWithMultipleParts =
|
||||
this.hasGlassLocationWithMultipleParts(partsOrQuestions);
|
||||
const hasGlassLocationWithMultipleParts
|
||||
= this.hasGlassLocationWithMultipleParts(partsOrQuestions);
|
||||
const hasChildPartQuestions = this.hasChildPartQuestions(partsOrQuestions);
|
||||
const hasCapabilityQuestions = this.hasCapabilityQuestions(partsOrQuestions);
|
||||
let backNavigationScenario = '';
|
||||
if (self.mainStore.order.damage.isRepair) {
|
||||
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_REPAIR;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
backNavigationScenario = self.mainStore.vehicle.vin
|
||||
? navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS
|
||||
: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS;
|
||||
|
|
@ -464,24 +440,24 @@ export default {
|
|||
|
||||
const currentPage = self.$route.query.issPage;
|
||||
if (
|
||||
hasCapabilityQuestions &&
|
||||
this.currentPageComesAfterPage(currentPage, issPageValues.CAPABILITY_QUESTIONS)
|
||||
hasCapabilityQuestions
|
||||
&& this.currentPageComesAfterPage(currentPage, issPageValues.CAPABILITY_QUESTIONS)
|
||||
) {
|
||||
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS;
|
||||
} else if (
|
||||
hasChildPartQuestions &&
|
||||
this.currentPageComesAfterPage(currentPage, issPageValues.MOLDING_QUESTIONS)
|
||||
hasChildPartQuestions
|
||||
&& this.currentPageComesAfterPage(currentPage, issPageValues.MOLDING_QUESTIONS)
|
||||
) {
|
||||
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS;
|
||||
} else if (
|
||||
hasGlassLocationWithMultipleParts &&
|
||||
this.currentPageComesAfterPage(currentPage, issPageValues.VEHICLE_PARTS)
|
||||
hasGlassLocationWithMultipleParts
|
||||
&& this.currentPageComesAfterPage(currentPage, issPageValues.VEHICLE_PARTS)
|
||||
) {
|
||||
backNavigationScenario =
|
||||
navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE;
|
||||
backNavigationScenario
|
||||
= navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE;
|
||||
} else if (
|
||||
hasPartQuestions &&
|
||||
this.currentPageComesAfterPage(currentPage, issPageValues.PART_QUESTIONS)
|
||||
hasPartQuestions
|
||||
&& this.currentPageComesAfterPage(currentPage, issPageValues.PART_QUESTIONS)
|
||||
) {
|
||||
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
|
|||
import { setupMocksForJsFiles, getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import { issPageValues } from '@/router/router-constants/issPage-values';
|
||||
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||
import {useMainStore} from '@/store';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
describe('vehicle-questions-mixin', () => {
|
||||
afterEach(() => {
|
||||
|
|
@ -290,8 +290,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
[issPageValues.PART_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, true],
|
||||
[issPageValues.MOLDING_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, true]
|
||||
];
|
||||
test.each(testCases)(
|
||||
'%s comes before %s is %s',
|
||||
test.each(testCases)('%s comes before %s is %s',
|
||||
(currentPage, nextPage, expectedResult) => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
|
@ -301,8 +300,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(result).toEqual(expectedResult);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('currentPageComesAfterPage', () => {
|
||||
|
|
@ -390,11 +388,9 @@ describe('vehicle-questions-mixin', () => {
|
|||
const { wrapper } = setupMocks({});
|
||||
|
||||
// Act
|
||||
const returnedGlass = await wrapper.vm.setupInitialData(
|
||||
glass,
|
||||
const returnedGlass = await wrapper.vm.setupInitialData(glass,
|
||||
i,
|
||||
alreadyAnsweredQuestions
|
||||
);
|
||||
alreadyAnsweredQuestions);
|
||||
|
||||
// Assert
|
||||
expect(returnedGlass.answerData).toMatchObject({ answerResult: 'WKT D1106 C' });
|
||||
|
|
@ -963,22 +959,12 @@ describe('vehicle-questions-mixin', () => {
|
|||
// Act
|
||||
wrapper.vm.handleAnswerUpdates(answerNo, '', wrapper.vm);
|
||||
const duplicatedQuestion = wrapper.vm.questionsData[1].questions[2];
|
||||
const duplicatedQuestionAnswer = duplicatedQuestion.answers.filter((a) => {
|
||||
return a.selected;
|
||||
});
|
||||
const answerToTest = wrapper.vm.questionsData[1].questions[0].answers.filter(
|
||||
(a) => {
|
||||
return a.originalNextQuestionSequence;
|
||||
}
|
||||
);
|
||||
const duplicatedQuestionAnswer = duplicatedQuestion.answers.filter((a) => a.selected);
|
||||
const answerToTest = wrapper.vm.questionsData[1].questions[0].answers.filter((a) => a.originalNextQuestionSequence);
|
||||
|
||||
// Assert
|
||||
expect(answerToTest[0].originalNextQuestionSequence).toEqual(
|
||||
duplicatedQuestion.questionSequence
|
||||
);
|
||||
expect(answerToTest[0].nextQuestionSequence).toEqual(
|
||||
duplicatedQuestionAnswer[0].nextQuestionSequence
|
||||
);
|
||||
expect(answerToTest[0].originalNextQuestionSequence).toEqual(duplicatedQuestion.questionSequence);
|
||||
expect(answerToTest[0].nextQuestionSequence).toEqual(duplicatedQuestionAnswer[0].nextQuestionSequence);
|
||||
});
|
||||
|
||||
describe('and the duplicate was the first question for that part', () => {
|
||||
|
|
@ -1080,15 +1066,9 @@ describe('vehicle-questions-mixin', () => {
|
|||
wrapper.vm.handleAnswerUpdates(answerNo, '', wrapper.vm);
|
||||
|
||||
// Assert
|
||||
expect(
|
||||
wrapper.vm.questionsData[1].questions[0].suppressThisQuestion
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
wrapper.vm.questionsData[1].questions[1].suppressThisQuestion
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
wrapper.vm.questionsData[1].questions[2].suppressThisQuestion
|
||||
).toBeFalsy();
|
||||
expect(wrapper.vm.questionsData[1].questions[0].suppressThisQuestion).toBeTruthy();
|
||||
expect(wrapper.vm.questionsData[1].questions[1].suppressThisQuestion).toBeTruthy();
|
||||
expect(wrapper.vm.questionsData[1].questions[2].suppressThisQuestion).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1194,19 +1174,13 @@ describe('vehicle-questions-mixin', () => {
|
|||
const questionsToTest = wrapper.vm.questionsData[1].questions;
|
||||
const answerLeadingToDuplicate = questionsToTest[0].answers[1];
|
||||
const duplicateQuestion = questionsToTest[2];
|
||||
const answerInDuplicateQuestion = duplicateQuestion.answers.filter((a) => {
|
||||
return a.selected;
|
||||
});
|
||||
const answerInDuplicateQuestion = duplicateQuestion.answers.filter((a) => a.selected);
|
||||
|
||||
// Assert
|
||||
expect(answerLeadingToDuplicate.answerResult).toEqual(
|
||||
answerInDuplicateQuestion[0].answerResult
|
||||
);
|
||||
expect(answerLeadingToDuplicate.answerResult).toEqual(answerInDuplicateQuestion[0].answerResult);
|
||||
expect(answerLeadingToDuplicate.originalAnswerResult).toBeFalsy();
|
||||
expect(answerLeadingToDuplicate.nextQuestionSequence).toEqual(null);
|
||||
expect(answerLeadingToDuplicate.originalNextQuestionSequence).toEqual(
|
||||
duplicateQuestion.questionSequence
|
||||
);
|
||||
expect(answerLeadingToDuplicate.originalNextQuestionSequence).toEqual(duplicateQuestion.questionSequence);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1244,7 +1218,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -1252,13 +1226,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
|
||||
test('multiple glass locations have part questions => go to parts-questions', async () => {
|
||||
|
|
@ -1359,7 +1331,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -1367,13 +1339,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
|
||||
test('multiple glass locations selected, one has part question => go to parts-questions', async () => {
|
||||
|
|
@ -1466,7 +1436,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -1474,13 +1444,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
|
||||
test('a selected glass location has part questions and multiple parts => go to parts-questions', async () => {
|
||||
|
|
@ -1621,7 +1589,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -1629,13 +1597,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -1669,7 +1635,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -1677,13 +1643,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
|
||||
test('multiple glass locations selected, one of them has multiple parts => go to vehicle parts', async () => {
|
||||
|
|
@ -1781,7 +1745,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -1789,13 +1753,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
|
||||
test('multiple glass locations selected, multiple have multiple parts => go to vehicle-parts', async () => {
|
||||
|
|
@ -1959,7 +1921,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -1967,13 +1929,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -2018,7 +1978,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -2026,13 +1986,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -2060,7 +2018,7 @@ describe('vehicle-questions-mixin', () => {
|
|||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions
|
||||
partsOrQuestions
|
||||
});
|
||||
|
||||
// Act
|
||||
|
|
@ -2068,13 +2026,11 @@ describe('vehicle-questions-mixin', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
{ partsOrQuestions });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -2089,10 +2045,8 @@ describe('vehicle-questions-mixin', () => {
|
|||
wrapper.vm.navigateBack();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_REPAIR,
|
||||
{ query: { issPage: issPageValues.COVERAGE_STATEMENT } }
|
||||
);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK_WITH_REPAIR,
|
||||
{ query: { issPage: issPageValues.COVERAGE_STATEMENT } });
|
||||
});
|
||||
|
||||
test('current page is molding questions and there are part questions, multiple parts to choose, and capability questions => go to vehicle-parts', () => {
|
||||
|
|
@ -2107,10 +2061,8 @@ describe('vehicle-questions-mixin', () => {
|
|||
wrapper.vm.navigateBack();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
{ query: { issPage: issPageValues.MOLDING_QUESTIONS } }
|
||||
);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
{ query: { issPage: issPageValues.MOLDING_QUESTIONS } });
|
||||
});
|
||||
|
||||
test('current page is molding questions and there are part questions and capability questions => go to part-questions', () => {
|
||||
|
|
@ -2125,15 +2077,13 @@ describe('vehicle-questions-mixin', () => {
|
|||
wrapper.vm.navigateBack();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
{ query: { issPage: issPageValues.MOLDING_QUESTIONS } }
|
||||
);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
{ query: { issPage: issPageValues.MOLDING_QUESTIONS } });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({ issPage = issPageValues.VIN_LOOKUP, hasVin, carId }) {
|
||||
function setupMocks({ issPage = issPageValues.VIN_LOOKUP }) {
|
||||
const baseMixin = setupMocksForJsFiles({
|
||||
actionList: [
|
||||
{
|
||||
|
|
@ -2168,8 +2118,8 @@ function setupMocks({ issPage = issPageValues.VIN_LOOKUP, hasVin, carId }) {
|
|||
};
|
||||
|
||||
const store = useMainStore();
|
||||
let actionResult = [];
|
||||
store.getCapabilityQuestions.mockImplementation(() => Promise.resolve({data: actionResult}));
|
||||
const actionResult = [];
|
||||
store.getCapabilityQuestions.mockImplementation(() => Promise.resolve({ data: actionResult }));
|
||||
|
||||
const wrapper = shallowMount(mockVehicleQuestionComponent, mocks);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export default {
|
|||
methods: {
|
||||
async navigateForwardWithSingleCarMatch() {
|
||||
const result = await useMainStore().getPartsOrQuestions();
|
||||
const partsOrQuestions = result.data.partsOrQuestions;
|
||||
const { partsOrQuestions } = result.data;
|
||||
|
||||
vehicleQuestionsMixin.methods.navigateForward(partsOrQuestions, this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,27 +4,6 @@ import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
|||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
describe('vin-pages-mixin', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('navigateForwardWithSingleCarMatch', () => {
|
||||
test('should navigateForward', async () => {
|
||||
// Arrange
|
||||
useMainStore().getPartsOrQuestions = () => { return { data: {partsOrQuestions: {}}} };
|
||||
const { wrapper } = setupMocks({});
|
||||
vehicleQuestionsMixin.methods.navigateForward = jest.fn();
|
||||
|
||||
// Act
|
||||
await wrapper.vm.navigateForwardWithSingleCarMatch();
|
||||
|
||||
// Assert
|
||||
expect(vehicleQuestionsMixin.methods.navigateForward).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks() {
|
||||
const mocks = getMountOptions({
|
||||
router: {
|
||||
|
|
@ -40,3 +19,24 @@ function setupMocks() {
|
|||
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
describe('vin-pages-mixin', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('navigateForwardWithSingleCarMatch', () => {
|
||||
test('should navigateForward', async () => {
|
||||
// Arrange
|
||||
useMainStore().getPartsOrQuestions = () => ({ data: { partsOrQuestions: {} } });
|
||||
const { wrapper } = setupMocks({});
|
||||
vehicleQuestionsMixin.methods.navigateForward = jest.fn();
|
||||
|
||||
// Act
|
||||
await wrapper.vm.navigateForwardWithSingleCarMatch();
|
||||
|
||||
// Assert
|
||||
expect(vehicleQuestionsMixin.methods.navigateForward).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue