Merge branch 'develop' into feature/SSR-795

This commit is contained in:
Katie Kroell 2024-01-26 13:00:38 -05:00
commit bd72a009fe
5 changed files with 335 additions and 6 deletions

View file

@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`contact-details-drawer snapshot matches returns the initial data 1`] = `
Object {
"emailAddress": "fred.tay@gmail.com",
"firstName": "Frederick",
"isModalOpened": false,
"lastName": "Taylor",
"phoneNumber": "606-009-2943",
"rules": Object {
"emailAddress": "email-required|email-address-format",
"firstName": "first-name-required",
"lastName": "last-name-required",
"phoneNumber": "phone-number-required|phone-number-format",
},
"widget": Object {
"drawerFooter": "ContactDetailsDrawerFooterWidget",
"emailQuestion": "EmailQuestionWidget",
"firstNameQuestion": "FirstNameQuestionWidget",
"lastNameQuestion": "LastNameQuestionWidget",
"phoneNumberQuestion": "PhoneNumberQuestionWidget",
"title": "ContactDetailsDrawerHeaderWidget",
},
}
`;

View file

@ -0,0 +1,134 @@
// Components
import { shallowMount } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
import contactDetailsDrawer from '@/layouts/tpa-submit/contact-details-drawer/contact-details-drawer.vue';
// Supporting Files
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import { useMainStore } from '@/store';
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRunAfterInitializingStore = () => {}) {
const mountOptions = getMountOptions({
router: {
navigate: jest.fn()
}
});
const testingPinia = createTestingPinia({
initialState: {
main: mainInitialState
}
});
useMainStore(testingPinia);
methodToRunAfterInitializingStore();
mountOptions.global.plugins = [testingPinia];
mountOptions.data = () => (initialData);
const wrapper = shallowMount(contactDetailsDrawer, mountOptions);
return { wrapper };
}
describe('contact-details-drawer', () => {
test('snapshot matches returns the initial data', () => {
// Arrange
const firstName = 'Frederick';
const lastName = 'Taylor';
const emailAddress = 'fred.tay@gmail.com';
const phoneNumber = '606-009-2943';
const mainInitialState = {
order: {
contactInfo: {
firstName,
lastName,
emailAddress,
phoneNumber
}
}
};
const { wrapper } = getMountedComponent(mainInitialState);
// Assert
expect(wrapper.vm.$data).toMatchSnapshot();
});
test('renders modal', () => {
// Arrange
const wrapper = shallowMount(contactDetailsDrawer, getMountOptions());
// Act
const modal = wrapper.findComponent({ ref: 'contact-details-modal' });
// Assert
expect(modal.exists()).toBeTruthy();
expect(modal.classes()).toContain('contact-details-drawer');
});
describe('method', () => {
describe('saveContactDetails', () => {
test.each([
['Sarah', 'Jones', 's.jones@gmail.com', '724-996-0909'],
[null, 'Jones', 's.jones@gmail.com', '724-996-0909'],
['Sarah', null, 's.jones@gmail.com', '724-996-0909'],
['Sarah', 'Jones', null, '724-996-0909'],
['Sarah', 'Jones', 's.jones@gmail.com', null]
])(
'when first name data "%p", last name "%p", email "%p", and phone number "%p", updateContactInfo called with expected',
(firstName, lastName, emailAddress, phoneNumber) => {
// Arrange
const mainInitialState = {
order: {
contactInfo: {
firstName: 'Frederick',
lastName: 'Taylor',
emailAddress: 'fred.tay@gmail.com',
phoneNumber: '606-009-2943'
}
}
};
const initialData = {
firstName, lastName, emailAddress, phoneNumber
};
const { wrapper } = getMountedComponent(mainInitialState, initialData);
// Act
wrapper.vm.saveContactDetails();
// Assert
expect(wrapper.emitted()['update-contact-details']).toBeTruthy();
expect(useMainStore().updateContactInfo).toBeCalledTimes(1);
expect(useMainStore().updateContactInfo).toBeCalledWith({ firstName, lastName, emailAddress, phoneNumber });
}
);
});
test('resetFormValues sets data to expected values', () => {
// Arrange
const firstName = 'John';
const lastName = 'Doe';
const emailAddress = 'test@example.com';
const phoneNumber = '123-456-1234';
const mainInitialState = {
order: {
contactInfo: {
firstName,
lastName,
emailAddress,
phoneNumber
}
}
};
const initialData = {
firstName: 'some name',
lastName: 'some end name',
emailAddress: 'email@what.com',
phoneNumber: '888'
};
const { wrapper } = getMountedComponent(mainInitialState, initialData);
// Act
wrapper.vm.resetFormValues();
// Assert
expect(wrapper.vm.firstName).toBe(firstName);
});
});
});

View file

@ -0,0 +1,150 @@
<template>
<modal
:ref="modalName"
:headerText="headerText"
:footerButtonText="footerButtonText"
:onModalClosedCallback="resetFormValues"
class="contact-details-drawer"
@isModalOpened="setModalStatus"
@footerButtonEvent="clickFooterButtonEvent">
<template v-if="isModalOpened">
<textboxQuestion
ref="firstNameQuestion"
v-model="firstName"
inputId="firstName"
:cmsWidgetName="widget.firstNameQuestion"
isRequired
:validationRules="rules.firstName" />
<textboxQuestion
ref="lastNameQuestion"
v-model="lastName"
class="mt-4"
inputId="lastName"
:cmsWidgetName="widget.lastNameQuestion"
isRequired
:validationRules="rules.lastName" />
<textboxQuestion
ref="emailQuestion"
v-model="emailAddress"
class="mt-4"
inputId="emailAddress"
:cmsWidgetName="widget.emailQuestion"
isRequired
:validationRules="rules.emailAddress" />
<textboxQuestion
ref="phoneNumberQuestion"
v-model="phoneNumber"
class="mt-4"
inputId="phoneNumber"
:cmsWidgetName="widget.phoneNumberQuestion"
isRequired
:validationRules="rules.phoneNumber" />
</template>
</modal>
</template>
<script>
// Components
import modal from '@/digital-components/modal/modal.vue';
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
// Supporting Files
import { useMainStore } from '@/store/index.js';
import globalRules from '@/constants/global-rules.js';
import widgetFields from '@/constants/cms-widget-fields.js';
export default {
name: 'contact-details-drawer',
components: {
modal,
textboxQuestion
},
emits: ['update-contact-details'],
data() {
const { firstName,
lastName,
emailAddress,
phoneNumber } = useMainStore().contactInfo;
return {
isModalOpened: false,
firstName,
lastName,
emailAddress,
phoneNumber,
widget: {
title: 'ContactDetailsDrawerHeaderWidget',
firstNameQuestion: 'FirstNameQuestionWidget',
lastNameQuestion: 'LastNameQuestionWidget',
emailQuestion: 'EmailQuestionWidget',
phoneNumberQuestion: 'PhoneNumberQuestionWidget',
drawerFooter: 'ContactDetailsDrawerFooterWidget'
},
rules: {
firstName: globalRules.FIRST_NAME_REQUIRED,
lastName: globalRules.LAST_NAME_REQUIRED,
emailAddress: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`
}
};
},
computed: {
modalName() {
return 'contact-details-modal';
},
modal() {
return this.$refs[this.modalName];
},
headerText() {
return this.getCmsContent(this.widget.title, widgetFields.SUB_HEADER_WIDGET.SUB_HEADER_TEXT);
},
footerButtonText() {
return this.getCmsContent(this.widget.drawerFooter, widgetFields.FOOTER_WIDGET.FORWARD_BUTTON_TEXT);
}
},
methods: {
setModalStatus(isOpened) {
this.isModalOpened = isOpened;
},
clickFooterButtonEvent() {
this.saveContactDetails();
this.closeModal();
},
saveContactDetails() {
const contactInfo = {
firstName: this.firstName,
lastName: this.lastName,
emailAddress: this.emailAddress,
phoneNumber: this.phoneNumber
};
useMainStore().updateContactInfo(contactInfo);
this.$emit('update-contact-details');
},
resetFormValues() {
const { firstName,
lastName,
emailAddress,
phoneNumber } = useMainStore().contactInfo;
this.firstName = firstName;
this.lastName = lastName;
this.emailAddress = emailAddress;
this.phoneNumber = phoneNumber;
},
openModal() {
this.modal.openModal();
},
closeModal() {
this.modal.closeModal();
}
}
};
</script>
<style lang="scss" scoped>
.contact-details-drawer {
:deep(.modal-title) {
font-size: $h5-font-size;
font-weight: $font-weight-normal !important;
}
}
</style>

View file

@ -299,6 +299,16 @@ describe('tpa-submit', () => {
expect(siteFooter.props().cmsWidgetName).toBe('SiteFooterWidget');
expect(siteFooter.classes()).toContain('mt-5');
});
test('contact details drawer', () => {
// Arrange
const wrapper = shallowMount(tpaSubmit, getMountOptions());
// Act
const contactDetailsDrawer = wrapper.findComponent({ ref: 'contactDetailsDrawer' });
// Assert
expect(contactDetailsDrawer.exists()).toBeTruthy();
});
});
describe('before route enter', () => {
test('produces 4 sections', async () => {

View file

@ -91,6 +91,9 @@
@forwardClicked="forwardButtonAction" />
</div>
</div>
<contactDetailsDrawer
ref="contactDetailsDrawer"
@updateContactDetails="setSections" />
</div>
</Form>
</template>
@ -102,6 +105,7 @@ import textBlock from '@/digital-components/text-block/text-block.vue';
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import reviewBlock from '@/layouts/tpa-submit/review-block/review-block.vue';
import deductibleBox from '@/layouts/tpa-submit/deductible-box/deductible-box.vue';
import contactDetailsDrawer from '@/layouts/tpa-submit/contact-details-drawer/contact-details-drawer.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
// Supporting files
@ -126,6 +130,7 @@ export default {
reviewBlock,
deductibleBox,
siteFooter,
contactDetailsDrawer,
// eslint-disable-next-line vue/no-reserved-component-names
Form
},
@ -246,18 +251,20 @@ export default {
? this.navigationScenarios.EDIT_POLICY_VEHICLE
: this.navigationScenarios.EDIT_VEHICLE;
this.sections = [
this.getSection(this.widget.subheader.vehicle, this.getVehicleLines, vehicleScenario),
this.getSection(this.widget.subheader.damage, this.getDamageLines, this.navigationScenarios.EDIT_DAMAGE),
this.getSection(this.widget.subheader.shop, this.getPreferredShopLines, this.navigationScenarios.EDIT_PREFERRED_SHOP),
this.getSection(this.widget.subheader.vehicle, this.getVehicleLines, () => this.navigate(vehicleScenario)),
// eslint-disable-next-line max-len
this.getSection(this.widget.subheader.contactInfo, this.getContactInfoLines, this.navigationScenarios.EDIT_CONTACT_DETAILS)
this.getSection(this.widget.subheader.damage, this.getDamageLines, () => this.navigate(this.navigationScenarios.EDIT_DAMAGE)),
// eslint-disable-next-line max-len
this.getSection(this.widget.subheader.shop, this.getPreferredShopLines, () => this.navigate(this.navigationScenarios.EDIT_PREFERRED_SHOP)),
// eslint-disable-next-line max-len
this.getSection(this.widget.subheader.contactInfo, this.getContactInfoLines, this.openContactDetailsModal)
];
},
getSection(widgetName, lines, scenario) {
getSection(widgetName, lines, onClick) {
return {
title: this.getCmsContent(widgetName, widgetFields.TEXT_BLOCK_WIDGET.TEXT),
lines,
onClickEdit: () => this.navigate(scenario)
onClickEdit: onClick
};
},
forwardButtonAction() {
@ -281,6 +288,9 @@ export default {
getAnswersNullSafe(widgetName) {
const rawAnswers = this.getCmsContent(widgetName, 'Answers');
return rawAnswers || [];
},
openContactDetailsModal() {
this.$refs.contactDetailsDrawer.openModal();
}
}
};