Merge pull request #1007 from Safelite/feature/kiener/INSR-6047
INSR-6047 | Provider-preference parity
This commit is contained in:
commit
1136e775ee
9 changed files with 178 additions and 375 deletions
|
|
@ -52,6 +52,7 @@ const errorMessages = Object.freeze({
|
||||||
POLICYHOLDER_FIRST_NAME_REQUIRED: 'First name is required.',
|
POLICYHOLDER_FIRST_NAME_REQUIRED: 'First name is required.',
|
||||||
POLICYHOLDER_LAST_NAME_REQUIRED: 'Last name is required.',
|
POLICYHOLDER_LAST_NAME_REQUIRED: 'Last name is required.',
|
||||||
ACKNOWLEDGEMENT_REQUIRED: 'You must agree to the terms to continue',
|
ACKNOWLEDGEMENT_REQUIRED: 'You must agree to the terms to continue',
|
||||||
|
NO_SELECTION_REQUIRED: 'Please make a selection to continue',
|
||||||
|
|
||||||
YEAR_REQUIRED: 'Vehicle year is required.',
|
YEAR_REQUIRED: 'Vehicle year is required.',
|
||||||
MAKE_REQUIRED: 'Vehicle make is required.',
|
MAKE_REQUIRED: 'Vehicle make is required.',
|
||||||
|
|
|
||||||
6
src/constants/provider-preference.js
Normal file
6
src/constants/provider-preference.js
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
const PROVIDER_PREFERENCE_OPTIONS = Object.freeze({
|
||||||
|
SAFELITE: 'SafeliteOption',
|
||||||
|
TPA: 'TPAOption'
|
||||||
|
});
|
||||||
|
|
||||||
|
export default PROVIDER_PREFERENCE_OPTIONS;
|
||||||
|
|
@ -43,41 +43,37 @@ function setupMocks(mockApiResponses) {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('provider-preference.vue', () => {
|
describe('provider-preference.vue', () => {
|
||||||
test('Should navigate to safelite flow when safelite selected', () => {
|
|
||||||
// Arrange
|
|
||||||
const { wrapper } = setupMocks();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
wrapper.vm.selectedProvider = 'SafeliteOption';
|
|
||||||
wrapper.vm.forwardButtonAction();
|
|
||||||
|
|
||||||
// Test
|
|
||||||
expect(wrapper.vm.$router.navigate).toBeCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, 'provider-preference');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should navigate to tpa flow when TPAOption selected and TPA Flow Enabled', () => {
|
|
||||||
// Arrange
|
|
||||||
const { wrapper } = setupMocks();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
wrapper.vm.selectedProvider = 'TPAOption';
|
|
||||||
useMainStore().issConfig.enableTPAFlow = true;
|
|
||||||
wrapper.vm.forwardButtonAction();
|
|
||||||
|
|
||||||
// Test
|
|
||||||
expect(wrapper.vm.$router.navigate).toBeCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED, 'provider-preference');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should navigate to tpa disabled route page when TPAOption selected and TPA Flow disabled', () => {
|
test('Should navigate to tpa disabled route page when TPAOption selected and TPA Flow disabled', () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = setupMocks();
|
const { wrapper } = setupMocks();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
wrapper.vm.selectedProvider = 'TPAOption';
|
|
||||||
useMainStore().issConfig.enableTPAFlow = false;
|
useMainStore().issConfig.enableTPAFlow = false;
|
||||||
wrapper.vm.forwardButtonAction();
|
wrapper.vm.findAnotherShopClicked();
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
expect(wrapper.vm.$router.navigate).toBeCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED, 'provider-preference');
|
expect(wrapper.vm.$router.navigate).toBeCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED, 'provider-preference');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Should navigate to safelite flow when navigateWithTPARecalAnswer is called with SafeliteOption', () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.navigateWithTPARecalAnswer('SafeliteOption');
|
||||||
|
|
||||||
|
// Test
|
||||||
|
expect(wrapper.vm.$router.navigate).toBeCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, 'provider-preference');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should navigate to TPA flow when navigateWithTPARecalAnswer is called with TPAOption', () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.navigateWithTPARecalAnswer('TPAOption');
|
||||||
|
|
||||||
|
// Test
|
||||||
|
expect(wrapper.vm.$router.navigate).toBeCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED, 'provider-preference');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -15,76 +15,70 @@
|
||||||
id="sub-header"
|
id="sub-header"
|
||||||
cmsWidgetName="SiteSubHeader"
|
cmsWidgetName="SiteSubHeader"
|
||||||
class="mb-0 mt-4 text-center" />
|
class="mb-0 mt-4 text-center" />
|
||||||
<buttonQuestion
|
<div
|
||||||
ref="buttonQuestion"
|
class="mt-4 mb-5"
|
||||||
v-model="selectedProvider"
|
v-html="scheduleWithSafeliteText"></div>
|
||||||
class="provider-preference"
|
<buttonMain
|
||||||
questionText="Select an option:"
|
ref="buttonMain"
|
||||||
:answers="prefAnswers"
|
class="full-width-button"
|
||||||
groupName="prefQuestions"
|
variant="navigation"
|
||||||
buttonTypeString="providerPrefRadio"
|
buttonText="Schedule now"
|
||||||
:validationRules="rules.optionRequired"
|
@clickEvent="scheduleWithSafelite" />
|
||||||
isRequired />
|
<div
|
||||||
|
class="mt-5 mb-5"
|
||||||
|
v-html="scheduleWithOtherText"></div>
|
||||||
|
<textLink
|
||||||
|
class="underlined-text"
|
||||||
|
linkType="navigation"
|
||||||
|
text="Find another shop"
|
||||||
|
href="#"
|
||||||
|
@clickEvent="findAnotherShopClicked" />
|
||||||
<siteFooter
|
<siteFooter
|
||||||
:ref="SITE_FOOTER_REF_NAME"
|
:ref="SITE_FOOTER_REF_NAME"
|
||||||
class="mt-5"
|
class="mt-6"
|
||||||
cmsWidgetName="SiteFooterWidget"
|
cmsWidgetName="SiteFooterWidget"
|
||||||
:isForwardActionDisabled="isForwardActionDisabled"
|
:isForwardButtonHidden="true"
|
||||||
:isForwardButtonNavigationDisabled="isForwardNavigationDisabled"
|
@backClicked="navigateBack" />
|
||||||
@backClicked="navigateBack"
|
|
||||||
@forwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<contentGroupModal
|
|
||||||
:ref="RECAL_MODAL_REF_NAME"
|
|
||||||
cssModalHeadlineClass="text-center"
|
|
||||||
cmsWidgetName="RecalModal" />
|
|
||||||
<steeringModal
|
<steeringModal
|
||||||
:ref="STEERING_MODAL_REF_NAME"
|
:ref="STEERING_MODAL_REF_NAME"
|
||||||
cmsWidgetName="StateSteeringModal" />
|
cmsWidgetName="StateSteeringModal" />
|
||||||
<shopPreferenceModal
|
|
||||||
:ref="SHOP_PREFERENCE_MODAL_REF_NAME"
|
|
||||||
cmsWidgetName="ShopPreferenceDrawer"
|
|
||||||
:showSteeringLink="showSteeringLink"
|
|
||||||
@openSteering="openStateSteeringModal" />
|
|
||||||
<tpaRecalModal
|
<tpaRecalModal
|
||||||
:ref="TPA_RECAL_MODAL_REF_NAME"
|
:ref="TPA_RECAL_MODAL_REF_NAME"
|
||||||
cmsWidgetName="TPARecalModal"
|
cmsWidgetName="TPARecalModal"
|
||||||
|
buttonCmsWidgetName="TPARecalQuestion"
|
||||||
:ackError="ackError"
|
:ackError="ackError"
|
||||||
@buttonClick="navigateWithTPAAck" />
|
:noSelectionError="noSelectionError"
|
||||||
|
@buttonClick="navigateWithTPARecalAnswer"/>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// Import Supporting Files
|
// Import Supporting Files
|
||||||
import {
|
import {
|
||||||
fetchCmsContentForPage,
|
fetchCmsContentForPage,
|
||||||
setupModalLink,
|
|
||||||
setupModalLinks
|
setupModalLinks
|
||||||
} from '@/helpers/cms-content-helper';
|
} from '@/helpers/cms-content-helper';
|
||||||
import settleAllPromises from '@/helpers/layout-helper';
|
import settleAllPromises from '@/helpers/layout-helper';
|
||||||
import errorMessages from '@/constants/error-messages';
|
import errorMessages from '@/constants/error-messages';
|
||||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||||
import issPageValues from '@/router/router-constants/issPage-values';
|
import showIssLoadingModal from '@/helpers/loading-modal-helper';
|
||||||
|
import bailoutMessage from '@/constants/bailoutMessage';
|
||||||
|
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||||
|
import PROVIDER_PREFERENCE_OPTIONS from '@/constants/provider-preference';
|
||||||
|
|
||||||
// Import Component
|
// Import Component
|
||||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
|
||||||
import { Form } from 'vee-validate';
|
import { Form } from 'vee-validate';
|
||||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||||
import steeringModal from '@/layouts/provider-preference/steering-modal/steering-modal.vue';
|
import steeringModal from '@/layouts/provider-preference/steering-modal/steering-modal.vue';
|
||||||
import shopPreferenceModal from '@/layouts/provider-preference/shop-preference-modal/shop-preference-modal.vue';
|
|
||||||
import tpaRecalModal from '@/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue';
|
import tpaRecalModal from '@/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue';
|
||||||
import globalRules from '@/constants/global-rules';
|
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||||
import bailoutMessage from '@/constants/bailoutMessage';
|
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||||
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
|
||||||
import showIssLoadingModal from '@/helpers/loading-modal-helper';
|
|
||||||
|
|
||||||
const options = { SAFELITE: 'SafeliteOption', TPA: 'TPAOption' };
|
|
||||||
const RECAL_MODAL_REF_NAME = 'RecalModal';
|
|
||||||
const STEERING_MODAL_REF_NAME = 'StateSteeringModal';
|
const STEERING_MODAL_REF_NAME = 'StateSteeringModal';
|
||||||
const SHOP_PREFERENCE_MODAL_REF_NAME = 'ShopPreferenceDrawer';
|
|
||||||
const TPA_RECAL_MODAL_REF_NAME = 'TPARecalModal';
|
const TPA_RECAL_MODAL_REF_NAME = 'TPARecalModal';
|
||||||
const SITE_FOOTER_REF_NAME = 'siteFooter';
|
const SITE_FOOTER_REF_NAME = 'siteFooter';
|
||||||
|
|
||||||
|
|
@ -97,10 +91,10 @@ export default {
|
||||||
// eslint-disable-next-line vue/no-reserved-component-names
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
Form,
|
Form,
|
||||||
buttonQuestion,
|
buttonQuestion,
|
||||||
|
buttonMain,
|
||||||
steeringModal,
|
steeringModal,
|
||||||
shopPreferenceModal,
|
|
||||||
tpaRecalModal,
|
tpaRecalModal,
|
||||||
contentGroupModal
|
textLink
|
||||||
},
|
},
|
||||||
mixins: [baseFormMixin],
|
mixins: [baseFormMixin],
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
@ -115,85 +109,37 @@ export default {
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
// open steering modal if it has body text, the state is defined in the CMS content and doesn't
|
||||||
vm.showSteeringLink = !!vm.$refs[STEERING_MODAL_REF_NAME].ModalBodyText;
|
// populate if the state is not listed in the CMS content
|
||||||
if (vm.showSteeringLink) {
|
if (!!vm.$refs[STEERING_MODAL_REF_NAME].ModalBodyText) {
|
||||||
vm.openStateSteeringModal();
|
vm.openStateSteeringModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedProvider: null,
|
providerPreferenceOptions: PROVIDER_PREFERENCE_OPTIONS,
|
||||||
showSteeringLink: false,
|
|
||||||
tpaAcknowledgement: false,
|
|
||||||
rules: {
|
|
||||||
optionRequired: globalRules.OPTION_REQUIRED
|
|
||||||
},
|
|
||||||
RECAL_MODAL_REF_NAME,
|
|
||||||
STEERING_MODAL_REF_NAME,
|
STEERING_MODAL_REF_NAME,
|
||||||
SHOP_PREFERENCE_MODAL_REF_NAME,
|
|
||||||
TPA_RECAL_MODAL_REF_NAME,
|
TPA_RECAL_MODAL_REF_NAME,
|
||||||
SITE_FOOTER_REF_NAME
|
SITE_FOOTER_REF_NAME
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isForwardActionDisabled() {
|
|
||||||
return this.selectedProvider === null;
|
|
||||||
},
|
|
||||||
isForwardNavigationDisabled() {
|
|
||||||
return this.selectedProvider === options.TPA && !this.tpaAcknowledgement;
|
|
||||||
},
|
|
||||||
prefAnswers() {
|
|
||||||
const cmsAnswersContent = [
|
|
||||||
{
|
|
||||||
cmsWidgetName: options.SAFELITE
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cmsWidgetName: options.TPA
|
|
||||||
}
|
|
||||||
];
|
|
||||||
// if cms content has not yet loaded, skip
|
|
||||||
if (
|
|
||||||
!this.getCmsContent(
|
|
||||||
cmsAnswersContent[0].cmsWidgetName,
|
|
||||||
'HeaderText'
|
|
||||||
)
|
|
||||||
|| this.getCmsContent(
|
|
||||||
cmsAnswersContent[0].cmsWidgetName,
|
|
||||||
'HeaderText'
|
|
||||||
) === ''
|
|
||||||
) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const modifiedAnswers = cmsAnswersContent.map((answer) => ({
|
|
||||||
value: answer.cmsWidgetName,
|
|
||||||
buttonLabel: this.getHeaderTextFromCms(answer.cmsWidgetName),
|
|
||||||
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.cmsWidgetName),
|
|
||||||
buttonBodyCopy: this.getBodyTextFromCms(answer.cmsWidgetName)
|
|
||||||
}));
|
|
||||||
return modifiedAnswers;
|
|
||||||
},
|
|
||||||
ackError() {
|
ackError() {
|
||||||
return errorMessages.ACKNOWLEDGEMENT_REQUIRED;
|
return errorMessages.ACKNOWLEDGEMENT_REQUIRED;
|
||||||
}
|
},
|
||||||
},
|
noSelectionError() {
|
||||||
watch: {
|
return errorMessages.NO_SELECTION_REQUIRED;
|
||||||
prefAnswers(newValue, oldValue) {
|
},
|
||||||
if (newValue !== oldValue) {
|
scheduleWithSafeliteText() {
|
||||||
setupModalLink(this, RECAL_MODAL_REF_NAME);
|
return this.getCmsContent('ScheduleWithSafeliteText', 'BodyText');
|
||||||
}
|
},
|
||||||
|
scheduleWithOtherText() {
|
||||||
|
return this.getCmsContent('ScheduleWithOtherText', 'BodyText');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
setupModalLinks(this);
|
setupModalLinks(this);
|
||||||
const pageData = this.mainStore.pageData(issPageValues.PROVIDER_PREFERENCE);
|
|
||||||
this.selectedProvider = pageData?.selectedProvider
|
|
||||||
? pageData.selectedProvider
|
|
||||||
: null;
|
|
||||||
this.tpaAcknowledgement = pageData?.tpaAcknowledgement
|
|
||||||
? pageData.tpaAcknowledgement
|
|
||||||
: false;
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getHeaderTextFromCms(cmsWidgetName) {
|
getHeaderTextFromCms(cmsWidgetName) {
|
||||||
|
|
@ -213,50 +159,38 @@ export default {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
navigateForward(scenario) {
|
navigateForward(scenario) {
|
||||||
|
showIssLoadingModal(true);
|
||||||
this.$router.navigate(scenario, this.$route);
|
this.$router.navigate(scenario, this.$route);
|
||||||
},
|
},
|
||||||
navigateWithTPAAck() {
|
navigateWithTPARecalAnswer(answer) {
|
||||||
this.mainStore.saveProviderPreferenceData({
|
if (answer === this.providerPreferenceOptions.TPA) {
|
||||||
selectedProvider: this.selectedProvider,
|
this.scheduleWithTPA();
|
||||||
tpaAcknowledgement: this.tpaAcknowledgement
|
} else {
|
||||||
});
|
this.scheduleWithSafelite();
|
||||||
showIssLoadingModal(true);
|
}
|
||||||
this.navigateForward(this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED);
|
|
||||||
},
|
},
|
||||||
forwardButtonAction() {
|
scheduleWithSafelite() {
|
||||||
if (this.selectedProvider) {
|
this.mainStore.updateIsSafeliteProvider(true);
|
||||||
let scenario = null;
|
const scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE;
|
||||||
switch (this.selectedProvider) {
|
this.navigateForward(scenario);
|
||||||
case options.SAFELITE:
|
},
|
||||||
this.mainStore.updateIsSafeliteProvider(true);
|
scheduleWithTPA() {
|
||||||
scenario =
|
this.mainStore.updateIsSafeliteProvider(false);
|
||||||
this.navigationScenarios
|
const scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED;
|
||||||
.CLICKED_FORWARD_WITH_SAFELITE;
|
this.navigateForward(scenario);
|
||||||
break;
|
},
|
||||||
case options.TPA:
|
findAnotherShopClicked() {
|
||||||
this.mainStore.updateIsSafeliteProvider(false);
|
if (this.mainStore.issConfig.enableTPAFlow) {
|
||||||
if (this.mainStore.issConfig.enableTPAFlow) {
|
if (this.mainStore.hasRecalibrationPart) {
|
||||||
if (this.mainStore.hasRecalibrationPart) {
|
this.$refs[TPA_RECAL_MODAL_REF_NAME].openModal();
|
||||||
this.$refs[TPA_RECAL_MODAL_REF_NAME].openModal();
|
return;
|
||||||
return;
|
} else {
|
||||||
}
|
this.scheduleWithTPA();
|
||||||
scenario =
|
|
||||||
this.navigationScenarios
|
|
||||||
.CLICKED_FORWARD_WITH_TPA_ENABLED;
|
|
||||||
} else {
|
|
||||||
this.mainStore.setBailout(bailoutMessage.TPANotEnabled());
|
|
||||||
scenario =
|
|
||||||
this.navigationScenarios
|
|
||||||
.CLICKED_FORWARD_WITH_TPA_DISABLED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.mainStore.setBailout(bailoutMessage.TPANotEnabled());
|
||||||
|
const scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED;
|
||||||
this.navigateForward(scenario);
|
this.navigateForward(scenario);
|
||||||
this.mainStore.saveProviderPreferenceData({
|
|
||||||
selectedProvider: this.selectedProvider,
|
|
||||||
tpaAcknowledgement: this.tpaAcknowledgement
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openStateSteeringModal() {
|
openStateSteeringModal() {
|
||||||
|
|
@ -279,12 +213,11 @@ export default {
|
||||||
#sub-header span {
|
#sub-header span {
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
.question-text {
|
.full-width-button {
|
||||||
margin-top: 0;
|
width: 100%;
|
||||||
margin-bottom: 0.5rem;
|
}
|
||||||
& > span {
|
.underlined-text {
|
||||||
text-align: left;
|
text-decoration: underline;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
:deep(.safeliteLogo) {
|
:deep(.safeliteLogo) {
|
||||||
background-image: url(~@/assets/img/icons/logo.svg);
|
background-image: url(~@/assets/img/icons/logo.svg);
|
||||||
|
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
import { shallowMount } from '@vue/test-utils';
|
|
||||||
import settleAllPromises from '@/helpers/layout-helper.js';
|
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
|
||||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
|
||||||
import shopPreferenceModal from '@/layouts/provider-preference/shop-preference-modal/shop-preference-modal.vue';
|
|
||||||
|
|
||||||
// Mock our module for promises.
|
|
||||||
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
|
|
||||||
|
|
||||||
// Mock fetchCmsContentForPage
|
|
||||||
jest.mock('@/helpers/cms-content-helper', () => ({
|
|
||||||
fetchCmsContentForPage: jest.fn(),
|
|
||||||
setupModalLinks: jest.fn()
|
|
||||||
}));
|
|
||||||
|
|
||||||
/** @ignore */
|
|
||||||
function setupMocks(propsData) {
|
|
||||||
const mountOptions = getMountOptions({
|
|
||||||
router: {
|
|
||||||
navigate: jest.fn()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mountOptions.propsData = propsData;
|
|
||||||
|
|
||||||
const wrapper = shallowMount(
|
|
||||||
shopPreferenceModal,
|
|
||||||
mountOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
const apiResponses = {};
|
|
||||||
|
|
||||||
settleAllPromises.mockImplementation(() => apiResponses);
|
|
||||||
fetchCmsContentForPage.mockImplementation(() => { });
|
|
||||||
|
|
||||||
return { wrapper };
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('provider-preference.vue', () => {
|
|
||||||
test('Should display state specific steering modal link when in state with steering language', async () => {
|
|
||||||
// Arrange
|
|
||||||
const { wrapper } = setupMocks({ showSteeringLink: true });
|
|
||||||
|
|
||||||
// Act
|
|
||||||
|
|
||||||
// Test
|
|
||||||
expect(wrapper.vm.showSteeringLink).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Should not display state specific steering modal link when not in state with steering language', async () => {
|
|
||||||
// Arrange
|
|
||||||
const { wrapper } = setupMocks({ showSteeringLink: false });
|
|
||||||
|
|
||||||
// Act
|
|
||||||
|
|
||||||
// Test
|
|
||||||
expect(wrapper.vm.showSteeringLink).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
<template>
|
|
||||||
<modal
|
|
||||||
:ref="ModalName"
|
|
||||||
:modalId="ModalName"
|
|
||||||
:onModalClosedCallback="onModalClosed"
|
|
||||||
:footerButtonText="ModalCloseButtonText"
|
|
||||||
@footerButtonEvent="footerButtonClick">
|
|
||||||
<h5 class="text-center mb-4">
|
|
||||||
{{ ModalHeadline }}
|
|
||||||
</h5>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="mb-4"
|
|
||||||
v-html="ModalBodyText"></div>
|
|
||||||
<a
|
|
||||||
v-if="showSteeringLink"
|
|
||||||
class="modal-text"
|
|
||||||
@click="openSteeringModal"
|
|
||||||
v-html="ModalSubBodyText">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import modal from '@/digital-components/modal/modal.vue';
|
|
||||||
import states from '@/constants/states';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'content-group-modal',
|
|
||||||
components: {
|
|
||||||
modal
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
cmsWidgetName: String,
|
|
||||||
showSteeringLink: Boolean
|
|
||||||
},
|
|
||||||
emits: ['openSteering'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
clickedSteeringLink: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
ModalName() {
|
|
||||||
return this.cmsWidgetName;
|
|
||||||
},
|
|
||||||
ModalHeadline() {
|
|
||||||
return this.getCmsContent(this.cmsWidgetName, 'HeaderText');
|
|
||||||
},
|
|
||||||
ModalSubheadertext() {
|
|
||||||
return this.getCmsContent(this.cmsWidgetName, 'SubheaderText');
|
|
||||||
},
|
|
||||||
ModalBodyText() {
|
|
||||||
return this.getCmsContent(this.cmsWidgetName, 'BodyText');
|
|
||||||
},
|
|
||||||
ModalSubBodyText() {
|
|
||||||
const header = this.getCmsContent(this.cmsWidgetName, 'BodyText2');
|
|
||||||
return header.replace('{custom:state}', states[this.mainStore.order.customer.address.state]);
|
|
||||||
},
|
|
||||||
ModalImage() {
|
|
||||||
return this.getCmsContent(this.cmsWidgetName, 'Image');
|
|
||||||
},
|
|
||||||
ModalCloseButtonText() {
|
|
||||||
return this.getCmsContent(this.cmsWidgetName, 'FooterText');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openModal() {
|
|
||||||
this.$refs[this.ModalName].openModal();
|
|
||||||
},
|
|
||||||
onModalClosed() {
|
|
||||||
if (this.clickedSteeringLink) {
|
|
||||||
this.$emit('openSteering');
|
|
||||||
this.clickedSteeringLink = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
footerButtonClick() {
|
|
||||||
this.$refs[this.ModalName].closeModal();
|
|
||||||
},
|
|
||||||
openSteeringModal() {
|
|
||||||
this.clickedSteeringLink = true;
|
|
||||||
this.$refs[this.ModalName].closeModal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.modal {
|
|
||||||
&.modal-component {
|
|
||||||
.modal-dialog {
|
|
||||||
.modal-content {
|
|
||||||
.modal-body {
|
|
||||||
.modal-sub-body {
|
|
||||||
color: $gray-600;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -38,16 +38,26 @@ describe('tpa-Recal-Modal.vue', () => {
|
||||||
test('should show error if not acknowledged', () => {
|
test('should show error if not acknowledged', () => {
|
||||||
const { wrapper } = setupMocks();
|
const { wrapper } = setupMocks();
|
||||||
wrapper.vm.acknowledged = false;
|
wrapper.vm.acknowledged = false;
|
||||||
|
wrapper.vm.tpaRecalAnswer = 'TPAOption';
|
||||||
wrapper.vm.footerButtonClick();
|
wrapper.vm.footerButtonClick();
|
||||||
|
|
||||||
expect(wrapper.vm.showError).toBeTruthy();
|
expect(wrapper.vm.showAcknowledgementError).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should not show error if acknowledged', () => {
|
test('should not show error if acknowledged', () => {
|
||||||
const { wrapper } = setupMocks();
|
const { wrapper } = setupMocks();
|
||||||
wrapper.vm.acknowledged = true;
|
wrapper.vm.acknowledged = true;
|
||||||
|
wrapper.vm.tpaRecalAnswer = 'TPAOption';
|
||||||
wrapper.vm.footerButtonClick();
|
wrapper.vm.footerButtonClick();
|
||||||
|
|
||||||
expect(wrapper.vm.showError).toBeFalsy();
|
expect(wrapper.vm.showAcknowledgementError).toBeFalsy();
|
||||||
|
});
|
||||||
|
test('should show error if no answer selected', () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
wrapper.vm.tpaRecalAnswer = '';
|
||||||
|
wrapper.vm.tpaRecalAnswer = undefined;
|
||||||
|
wrapper.vm.footerButtonClick();
|
||||||
|
|
||||||
|
expect(wrapper.vm.showNoSelectionError).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,23 @@
|
||||||
<tpaRecalToggle
|
<tpaRecalToggle
|
||||||
class="mb-5"
|
class="mb-5"
|
||||||
cmsWidgetName="TPARecalModalToggle" />
|
cmsWidgetName="TPARecalModalToggle" />
|
||||||
|
<buttonQuestion
|
||||||
|
ref="tpaRecalQuestion"
|
||||||
|
v-model="tpaRecalAnswer"
|
||||||
|
class="radioQuestion safelite-or-tpa-question windshield-chip-count-question mb-4"
|
||||||
|
:cmsWidgetName="buttonCmsWidgetName"
|
||||||
|
:questionText="tpaRecalQuestionText"
|
||||||
|
:answers="tpaRecalAnswersFromCms"
|
||||||
|
groupName="tpaRecalQuestion"
|
||||||
|
buttonID="tpaRecalQuestion"
|
||||||
|
buttonTypeString="listButtonHorizontal"
|
||||||
|
isRequired></buttonQuestion>
|
||||||
<checkBox
|
<checkBox
|
||||||
|
v-if="showAcknowledgementCheckbox"
|
||||||
ref="tpaAcknowledgement"
|
ref="tpaAcknowledgement"
|
||||||
v-model="acknowledged"
|
v-model="acknowledged"
|
||||||
class="mb-2"
|
class="mb-2"
|
||||||
:class="showError && ' has-error'"
|
:class="showAcknowledgementError && ' has-error'"
|
||||||
:validationRules="rules.optionRequired"
|
:validationRules="rules.optionRequired"
|
||||||
checkboxName="tpaAcknowledgement"
|
checkboxName="tpaAcknowledgement"
|
||||||
buttonID="tpaAcknowledgement"
|
buttonID="tpaAcknowledgement"
|
||||||
|
|
@ -29,9 +41,9 @@
|
||||||
:screenReaderOnlyText="ModalSubBodyText"
|
:screenReaderOnlyText="ModalSubBodyText"
|
||||||
isRequired />
|
isRequired />
|
||||||
<div
|
<div
|
||||||
v-if="showError"
|
v-if="showAcknowledgementError || showNoSelectionError"
|
||||||
class="row form-test-error mt-1">
|
class="row form-test-error mt-1">
|
||||||
<p>{{ ackError }}</p>
|
<p>{{ errorMessage }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -42,24 +54,31 @@
|
||||||
import modal from '@/digital-components/modal/modal.vue';
|
import modal from '@/digital-components/modal/modal.vue';
|
||||||
import tpaRecalToggle from '@/layouts/provider-preference/tpa-recal-modal/tpa-recal-toggle/tpa-recal-toggle.vue';
|
import tpaRecalToggle from '@/layouts/provider-preference/tpa-recal-modal/tpa-recal-toggle/tpa-recal-toggle.vue';
|
||||||
import checkBox from '@/ux-components/checkbox/checkbox.vue';
|
import checkBox from '@/ux-components/checkbox/checkbox.vue';
|
||||||
|
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||||
import globalRules from '@/constants/global-rules';
|
import globalRules from '@/constants/global-rules';
|
||||||
|
import PROVIDER_PREFERENCE_OPTIONS from '@/constants/provider-preference';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'content-group-modal',
|
name: 'content-group-modal',
|
||||||
components: {
|
components: {
|
||||||
modal,
|
modal,
|
||||||
tpaRecalToggle,
|
tpaRecalToggle,
|
||||||
checkBox
|
checkBox,
|
||||||
|
buttonQuestion
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
cmsWidgetName: String,
|
cmsWidgetName: String,
|
||||||
ackError: String
|
buttonCmsWidgetName: String,
|
||||||
|
ackError: String,
|
||||||
|
noSelectionError: String
|
||||||
},
|
},
|
||||||
emits: ['buttonClick'],
|
emits: ['buttonClick'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
acknowledged: false,
|
acknowledged: false,
|
||||||
showError: false,
|
showAcknowledgementError: false,
|
||||||
|
showNoSelectionError: false,
|
||||||
|
tpaRecalAnswer: '',
|
||||||
rules: {
|
rules: {
|
||||||
optionRequired: globalRules.OPTION_REQUIRED
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
}
|
}
|
||||||
|
|
@ -81,13 +100,34 @@ export default {
|
||||||
ModalCloseButtonText() {
|
ModalCloseButtonText() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, 'FooterText');
|
return this.getCmsContent(this.cmsWidgetName, 'FooterText');
|
||||||
},
|
},
|
||||||
|
tpaRecalQuestionText() {
|
||||||
|
return this.getCmsContent(this.buttonCmsWidgetName, 'QuestionText');
|
||||||
|
},
|
||||||
|
tpaRecalAnswersFromCms() {
|
||||||
|
return this.getCmsContent(this.buttonCmsWidgetName, 'Answers');
|
||||||
|
},
|
||||||
|
showAcknowledgementCheckbox() {
|
||||||
|
return this.tpaRecalAnswer === PROVIDER_PREFERENCE_OPTIONS.TPA;
|
||||||
|
},
|
||||||
isButtonDisabled() {
|
isButtonDisabled() {
|
||||||
return !this.acknowledged;
|
return !this.acknowledged;
|
||||||
|
},
|
||||||
|
errorMessage() {
|
||||||
|
if (this.showNoSelectionError) {
|
||||||
|
return this.noSelectionError;
|
||||||
|
} else if (this.showAcknowledgementError) {
|
||||||
|
return this.ackError;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
acknowledged() {
|
acknowledged() {
|
||||||
this.showError = false;
|
this.showAcknowledgementError = false;
|
||||||
|
},
|
||||||
|
tpaRecalAnswer() {
|
||||||
|
this.showNoSelectionError = false;
|
||||||
|
this.showAcknowledgementError = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -96,12 +136,15 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
footerButtonClick() {
|
footerButtonClick() {
|
||||||
// check if acked, if not show error
|
if (this.tpaRecalAnswer && (!this.showAcknowledgementCheckbox || this.acknowledged )) {
|
||||||
if (this.acknowledged) {
|
|
||||||
this.$refs[this.ModalName]?.closeModal();
|
this.$refs[this.ModalName]?.closeModal();
|
||||||
this.$emit('buttonClick');
|
this.$emit('buttonClick', this.tpaRecalAnswer);
|
||||||
|
} else if (!this.tpaRecalAnswer) {
|
||||||
|
this.showNoSelectionError = true;
|
||||||
|
this.showAcknowledgementError = false;
|
||||||
} else {
|
} else {
|
||||||
this.showError = true;
|
this.showAcknowledgementError = true;
|
||||||
|
this.showNoSelectionError = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -130,29 +173,16 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
.safelite-or-tpa-question {
|
||||||
|
:deep(.question-text) {
|
||||||
.form-check {
|
span {
|
||||||
.form-check-input {
|
font-weight: 500;
|
||||||
&:checked {
|
|
||||||
+ label {
|
|
||||||
p {
|
|
||||||
font-weight: 400 !important;
|
|
||||||
font-size: 1rem !important;
|
|
||||||
color: $gray-600 !important;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p {
|
|
||||||
font-weight: 400 !important;
|
|
||||||
font-size: 1rem !important;
|
|
||||||
color: $gray-600 !important;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.form-test-error {
|
.form-test-error {
|
||||||
p {
|
p {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
|
||||||
|
|
@ -2393,9 +2393,6 @@ export const useMainStore = defineStore({
|
||||||
|
|
||||||
return retPricedLineItems;
|
return retPricedLineItems;
|
||||||
},
|
},
|
||||||
saveProviderPreferenceData(data) {
|
|
||||||
this.updatePageData({ page: issPageValues.PROVIDER_PREFERENCE, data });
|
|
||||||
},
|
|
||||||
addEventToBus(event) {
|
addEventToBus(event) {
|
||||||
this.applicationUser.eventBus.push(event);
|
this.applicationUser.eventBus.push(event);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue