Merge pull request #565 from Safelite/feature/digital/SSR-1132
Feature/digital/ssr 1132
This commit is contained in:
commit
40152c2df5
4 changed files with 319 additions and 2 deletions
|
|
@ -0,0 +1,11 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`cart-dropdown component initial data rendered as expected 1`] = `
|
||||
Object {
|
||||
"currencyFormatter": NumberFormat {},
|
||||
"isExpanded": false,
|
||||
"widget": Object {
|
||||
"amountDue": "AmountDueTextWidget",
|
||||
},
|
||||
}
|
||||
`;
|
||||
159
src/iss-components/cart-dropdown/cart-dropdown.spec.js
Normal file
159
src/iss-components/cart-dropdown/cart-dropdown.spec.js
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
|
||||
|
||||
// Supporting Files
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
function getMountedComponent(mainInitialState = {}, initialData = {}, propsData = {}) {
|
||||
const mountOptions = getMountOptions({
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
}
|
||||
});
|
||||
|
||||
const testingPinia = createTestingPinia({
|
||||
initialState: {
|
||||
main: mainInitialState
|
||||
}
|
||||
});
|
||||
useMainStore(testingPinia);
|
||||
|
||||
mountOptions.global.plugins = [testingPinia];
|
||||
mountOptions.data = () => (initialData);
|
||||
mountOptions.propsData = propsData;
|
||||
|
||||
const wrapper = shallowMount(cartDropdown, mountOptions);
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {});
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
describe('cart-dropdown component', () => {
|
||||
test('initial data rendered as expected', () => {
|
||||
// Arrange
|
||||
const { wrapper } = getMountedComponent();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$data).toMatchSnapshot();
|
||||
});
|
||||
describe('displays', () => {
|
||||
test('cart dropdown head', () => {
|
||||
// Arrange
|
||||
const reference = '#cart-dropdown-head';
|
||||
const { wrapper } = getMountedComponent(cartDropdown);
|
||||
|
||||
// Act
|
||||
const head = wrapper.find(reference);
|
||||
|
||||
// Assert
|
||||
expect(head.exists()).toBeTruthy();
|
||||
});
|
||||
test('cart table', () => {
|
||||
// Arrange
|
||||
const reference = '#cart-table';
|
||||
const isExpanded = true;
|
||||
const initialData = { isExpanded };
|
||||
const { wrapper } = getMountedComponent(cartDropdown, {}, initialData);
|
||||
|
||||
// Act
|
||||
const cartTable = wrapper.find(reference);
|
||||
|
||||
// Assert
|
||||
expect(cartTable.exists()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
describe('computed', () => {
|
||||
test.each([
|
||||
[true, true],
|
||||
[false, false],
|
||||
[false, null]
|
||||
])('isVerified returns %p when isVerified store value is %p', (expected, isVerified) => {
|
||||
// Arrange
|
||||
const storeData = {
|
||||
order: {
|
||||
payment: {
|
||||
insuranceCoverage: { isVerified }
|
||||
}
|
||||
}
|
||||
};
|
||||
const { wrapper } = getMountedComponent(storeData);
|
||||
|
||||
// Act
|
||||
const result = wrapper.vm.isVerified;
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
describe('amountDueDisplayed', () => {
|
||||
test('returns verifying coverage text when isVerified false', () => {
|
||||
// Arrange
|
||||
const VERIFYING_COVERAGE = 'Verifying coverage';
|
||||
const storeData = {
|
||||
order: {
|
||||
payment: {
|
||||
insuranceCoverage: {
|
||||
isVerified: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const { wrapper } = getMountedComponent(storeData);
|
||||
|
||||
// Act
|
||||
const result = wrapper.vm.amountDueDisplayed;
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(VERIFYING_COVERAGE);
|
||||
});
|
||||
test('returns formatted amount due when isVerified false', () => {
|
||||
// TODO finish when methods done
|
||||
});
|
||||
});
|
||||
describe('amountDue', () => {
|
||||
test('returns 0 when showAsPaid is true', () => {
|
||||
// Arrange
|
||||
const propsData = {
|
||||
showAsPaid: true
|
||||
};
|
||||
const { wrapper } = getMountedComponent({}, {}, propsData);
|
||||
|
||||
// Act
|
||||
const result = wrapper.vm.amountDue;
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(0);
|
||||
});
|
||||
test('returns sum of subTotal and salesTax when showAsPaid is false', () => {
|
||||
// TODO when subTotal and salesTax are finished
|
||||
});
|
||||
});
|
||||
describe('subTotal', () => {
|
||||
// TODO when method implemented
|
||||
});
|
||||
describe('salesTax', () => {
|
||||
// TODO when method implemented
|
||||
});
|
||||
});
|
||||
describe('method', () => {
|
||||
test.each([
|
||||
['$0.00', 0],
|
||||
['$12.00', 12],
|
||||
['$12.30', 12.3],
|
||||
['$12.34', 12.34],
|
||||
['$12.35', 12.345],
|
||||
['$12.34', 12.344],
|
||||
['-$1.00', -1]
|
||||
])('get FormattedAmount returns `%` when amount %', (expected, amount) => {
|
||||
// Arrange
|
||||
const { wrapper } = getMountedComponent();
|
||||
|
||||
// Act
|
||||
const result = wrapper.vm.getFormattedAmount(amount);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
136
src/iss-components/cart-dropdown/cart-dropdown.vue
Normal file
136
src/iss-components/cart-dropdown/cart-dropdown.vue
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
id="cart-dropdown-head"
|
||||
class="row cart-toggle flex align-items-center pt-4"
|
||||
:class="[isExpanded ? 'expanded' : '']"
|
||||
@click="toggleIsExpanded">
|
||||
<a
|
||||
aria-label="expand cart details"
|
||||
href="javascript:void(0)"
|
||||
class="col d-flex justify-content-between py-0">
|
||||
<span class="label color-black">{{ amountDueLabel }}</span>
|
||||
<span class="label amount-due">{{ amountDueDisplayed }}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
id="cart-table"
|
||||
class="cart-table px-4">
|
||||
<p>Cart Table Placeholder</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
const VERIFYING_COVERAGE = 'Verifying coverage';
|
||||
|
||||
export default {
|
||||
name: 'cart-dropdown',
|
||||
components: {},
|
||||
props: {
|
||||
showAsPaid: Boolean,
|
||||
amountDueLabel: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isExpanded: false,
|
||||
currencyFormatter: new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD'
|
||||
}),
|
||||
widget: {
|
||||
amountDue: 'AmountDueTextWidget'
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isVerified() {
|
||||
return useMainStore().payment?.insuranceCoverage?.isVerified ?? false;
|
||||
},
|
||||
amountDueDisplayed() {
|
||||
return this.isVerified
|
||||
? this.getFormattedAmount(this.amountDue)
|
||||
: VERIFYING_COVERAGE;
|
||||
},
|
||||
amountDue() {
|
||||
return this.showAsPaid
|
||||
? 0
|
||||
: this.subTotal + this.salesTax;
|
||||
},
|
||||
subTotal() {
|
||||
return 0;
|
||||
},
|
||||
salesTax() {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleIsExpanded() {
|
||||
this.isExpanded = !this.isExpanded;
|
||||
},
|
||||
getFormattedAmount(amount) {
|
||||
return this.currencyFormatter.format(amount);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/ux-variables-svg-strings.scss";
|
||||
|
||||
.color-black {
|
||||
color: $black;
|
||||
}
|
||||
|
||||
.cart-table {
|
||||
max-height: 0;
|
||||
transition: all 350ms ease-in;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.cart-toggle {
|
||||
margin-bottom: 1rem;
|
||||
.amount-due {
|
||||
color: $green;
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
transition: all 0.5s ease;
|
||||
background-image: url($svg-payment-method-review-toggle);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
width: 1rem;
|
||||
height: 0.5625rem;
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
right: 0.75rem;
|
||||
margin: 0.5rem 0 0.5rem 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
&.expanded:after {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
&.expanded + .cart-table {
|
||||
max-height: 50rem;
|
||||
transition: all 150ms ease-in;
|
||||
overflow: hidden;
|
||||
visibility: visible;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.label {
|
||||
font-weight: $font-weight-bold;
|
||||
line-height: 1.625;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -19,8 +19,10 @@
|
|||
<hr class="my-0" />
|
||||
<reviewDropdown ref="reviewDropdown" />
|
||||
<hr class="my-0" />
|
||||
<div>Cart Placeholder</div>
|
||||
<hr class="my-5" />
|
||||
<cartDropdown
|
||||
:showAsPaid="false"
|
||||
:amountDueLabel="amountDueText" />
|
||||
<hr class="mt-0 mb-5" />
|
||||
<div>Pia Alert Placeholder</div>
|
||||
<paymentMethodQuestion
|
||||
v-model="paymentMethodInternalModel"
|
||||
|
|
@ -47,6 +49,7 @@ import siteHeader from '@/iss-components/site-header/site-header.vue';
|
|||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import reviewDropdown from '@/layouts/payment-method/review-dropdown/review-dropdown.vue';
|
||||
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
|
||||
import paymentMethodQuestion from '@/layouts/payment-method/payment-method-question/payment-method-question.vue';
|
||||
|
||||
// Supporting Items
|
||||
|
|
@ -56,6 +59,7 @@ import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
|||
import { paymentMethods } from '@/constants/payment-method-constants';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
import { Form } from 'vee-validate';
|
||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||
|
||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||
|
||||
|
|
@ -68,6 +72,7 @@ export default {
|
|||
siteSubHeader,
|
||||
siteFooter,
|
||||
reviewDropdown,
|
||||
cartDropdown,
|
||||
paymentMethodQuestion
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
|
|
@ -102,6 +107,9 @@ export default {
|
|||
paymentMethodInternalModel: this.getPaymentMethodFromStore(),
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
},
|
||||
widget: {
|
||||
amountDue: 'AmountDueTextWidget'
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
@ -123,6 +131,9 @@ export default {
|
|||
},
|
||||
paymentMethod() {
|
||||
return this.paymentMethodInternalModel;
|
||||
},
|
||||
amountDueText() {
|
||||
return this.getCmsContent(this.widget.amountDue, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
|||
Loading…
Reference in a new issue