Merge pull request #542 from Safelite/feature/digital/SSR-792.5
Adding contact details drawer
This commit is contained in:
commit
0eb46c45c0
5 changed files with 335 additions and 6 deletions
|
|
@ -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",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -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>
|
||||
|
|
@ -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 () => {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue