SSR-1064 linting

This commit is contained in:
Matt Caimi 2024-02-01 15:17:16 -05:00
parent 2935eefde0
commit 462e4f9337
9 changed files with 241 additions and 252 deletions

View file

@ -1,7 +1,7 @@
export const paymentMethods = {
NONE: null,
LATER: "Later",
CREDIT_CARD: "CreditCard",
PAYPAL: "Paypal",
AFTERPAY: "Afterpay",
LATER: 'Later',
CREDIT_CARD: 'CreditCard',
PAYPAL: 'Paypal',
AFTERPAY: 'Afterpay'
};

View file

@ -1,48 +1,55 @@
import { mount } from "@vue/test-utils";
import navbar from "./nav-bar";
import { mount } from '@vue/test-utils';
import navbar from './nav-bar';
describe("nav-bar.vue", () => {
test("Should emit ForwardClicked on button click", async () => {
const mockMixin = {
methods: {
getCmsContent: jest.fn(),
getFooterInfoBoxHeight: jest.fn(() => 80)
}
};
describe('nav-bar.vue', () => {
test('Should emit ForwardClicked on button click', async () => {
// Act
const wrapper = mount(navbar, {
mixins: [mockMixin],
mixins: [mockMixin]
});
wrapper.vm.buttonClick();
// Assert
expect(wrapper.emitted()["ForwardClicked"][0]).toHaveBeenCalled;
expect(wrapper.emitted()['ForwardClicked'][0]).toHaveBeenCalled;
});
test("Should emit BackClicked on link click", async () => {
test('Should emit BackClicked on link click', async () => {
// Act
const wrapper = mount(navbar, {
mixins: [mockMixin],
mixins: [mockMixin]
});
wrapper.vm.linkClick();
// Assert
expect(wrapper.emitted()["BackClicked"][0]).toHaveBeenCalled;
expect(wrapper.emitted()['BackClicked'][0]).toHaveBeenCalled;
});
test("Should change button text when update button text is called", async () => {
test('Should change button text when update button text is called', async () => {
// Act
const wrapper = mount(navbar, {
mixins: [mockMixin],
mixins: [mockMixin]
});
wrapper.vm.updateButtonText("newText");
wrapper.vm.updateButtonText('newText');
// Assert
expect(wrapper.componentVM.customButtontext).toBe("newText");
expect(wrapper.componentVM.customButtontext).toBe('newText');
});
test("should run removeLoader fn on buttonMain and return false for onkeydown fn", async () => {
test('should run removeLoader fn on buttonMain and return false for onkeydown fn', async () => {
// Arrange
const wrapper = mount(navbar, {
mixins: [mockMixin],
mixins: [mockMixin]
});
// Act
wrapper.vm.$refs.buttonMain.removeLoader = jest.fn();
wrapper.vm.removeLoader();
const spy = jest.spyOn(document, "onkeydown");
const spy = jest.spyOn(document, 'onkeydown');
document.onkeydown();
// Assert
@ -50,10 +57,3 @@ describe("nav-bar.vue", () => {
expect(spy).toReturnWith(true);
});
});
const mockMixin = {
methods: {
getCmsContent: jest.fn(),
getFooterInfoBoxHeight: jest.fn(() => 80),
},
};

View file

@ -43,41 +43,40 @@
</template>
<script>
import textLink from "@/ux-components/text-link/text-link";
import buttonMain from "@/ux-components/button-main/button-main";
import textLink from '@/ux-components/text-link/text-link.vue';
import buttonMain from '@/ux-components/button-main/button-main.vue';
export default {
name: "navbar",
emits: ["BackClicked", "ForwardClicked"], // <--- should remove oodles of warnings in dev tools
name: 'navbar',
components: {
textLink,
buttonMain
},
props: {
isForwardActionDisabled: Boolean,
isBackButtonHidden: { type: Boolean, default: false },
cmsWidgetName: String,
buttonSize: { type: Boolean, default: false },
isSubmitHidden: { type: Boolean, default: false },
},
components: {
textLink,
buttonMain,
isSubmitHidden: { type: Boolean, default: false }
},
emits: ['BackClicked', 'ForwardClicked'], // <--- should remove oodles of warnings in dev tools
data() {
return {
customButtontext: "",
customButtontext: ''
};
},
unmounted() {
document.onkeydown = null;
},
computed: {
backLink() {
return this.getCmsContent(this.cmsWidgetName, "BackButtonText");
return this.getCmsContent(this.cmsWidgetName, 'BackButtonText');
},
buttonText() {
return this.customButtontext
? this.customButtontext
: this.getCmsContent(this.cmsWidgetName, "ForwardButtonText");
},
: this.getCmsContent(this.cmsWidgetName, 'ForwardButtonText');
}
},
unmounted() {
document.onkeydown = null;
},
methods: {
updateButtonText(newText) {
@ -90,16 +89,16 @@ export default {
};
},
buttonClick() {
//prevent keyboard input after button click
// prevent keyboard input after button click
document.onkeydown = function (e) {
return false;
};
this.$emit("ForwardClicked");
this.$emit('ForwardClicked');
},
linkClick() {
this.$emit("BackClicked");
},
},
this.$emit('BackClicked');
}
}
};
</script>

View file

@ -1,87 +1,34 @@
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { shallowMount } from '@vue/test-utils';
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import paymentMethodListButton from "@/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button";
// eslint-disable-next-line max-len
import paymentMethodListButton from '@/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button.vue';
const testConstants = {
images: {
A: "imageA",
B: "imageB",
NONE: null,
A: 'imageA',
B: 'imageB',
NONE: null
},
names: {
A: "nameA",
B: "nameB",
A: 'nameA',
B: 'nameB'
},
content: {
withInline: "Button text with {custom:inlineImage} inline.",
noInline: "Button text with no inline",
withInline: 'Button text with {custom:inlineImage} inline.',
noInline: 'Button text with no inline'
},
};
let cmsContent;
describe("Payment Method Question", () => {
beforeEach(() => {
cmsContent = {};
});
describe("Side image", () => {
it("Renders side image if image is present and not inline", () => {
// Arrange
const props = generateDefaultProps();
const { wrapper } = setupMocks({
propsData: props,
});
// Act
const showSideImage = wrapper.vm.shouldDisplaySideImage;
expect(showSideImage).toBe(true);
});
it("Does not render side image if no image is present", () => {
// Arrange
let props = generateDefaultProps();
props.buttonImage = testConstants.images.NONE;
const { wrapper } = setupMocks({
propsData: props,
});
// Act
const showSideImage = wrapper.vm.shouldDisplaySideImage;
expect(showSideImage).toBe(false);
});
it("Does not render side image if inline", () => {
// Arrange
let props = generateDefaultProps();
props.buttonLabel = testConstants.content.withInline;
props.altText = testConstants.content.withInline;
const { wrapper } = setupMocks({
propsData: props,
});
// Act
const showSideImage = wrapper.vm.shouldDisplaySideImage;
expect(showSideImage).toBe(false);
});
});
});
function generateDefaultProps() {
return {
buttonLabel: testConstants.noInline,
altText: testConstants.noInline,
groupName: "payment-method",
groupName: 'payment-method',
value: testConstants.names.A,
buttonImage: testConstants.images.A,
buttonImage: testConstants.images.A
};
}
@ -91,9 +38,9 @@ function setupMocks(customMountOptions) {
const mockMixin = {
methods: {
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
}),
},
return cmsContent?.[widgetName]?.[cmsFieldName] ?? '';
})
}
};
mountOptions.global.mixins = [mockMixin];
@ -102,3 +49,57 @@ function setupMocks(customMountOptions) {
wrapper.vm.setCmsContent = jest.fn();
return { wrapper };
}
describe('Payment Method Question', () => {
beforeEach(() => {
cmsContent = {};
});
describe('Side image', () => {
it('Renders side image if image is present and not inline', () => {
// Arrange
const props = generateDefaultProps();
const { wrapper } = setupMocks({
propsData: props
});
// Act
const showSideImage = wrapper.vm.shouldDisplaySideImage;
expect(showSideImage).toBe(true);
});
it('Does not render side image if no image is present', () => {
// Arrange
const props = generateDefaultProps();
props.buttonImage = testConstants.images.NONE;
const { wrapper } = setupMocks({
propsData: props
});
// Act
const showSideImage = wrapper.vm.shouldDisplaySideImage;
expect(showSideImage).toBe(false);
});
it('Does not render side image if inline', () => {
// Arrange
const props = generateDefaultProps();
props.buttonLabel = testConstants.content.withInline;
props.altText = testConstants.content.withInline;
const { wrapper } = setupMocks({
propsData: props
});
// Act
const showSideImage = wrapper.vm.shouldDisplaySideImage;
expect(showSideImage).toBe(false);
});
});
});

View file

@ -1,8 +1,8 @@
<template>
<baseInputButton
v-bind="$props"
buttonWrapperClasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2"
v-model="selectedValue">
v-model="selectedValue"
buttonWrapperClasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2">
<div class="button-content list-button-content d-flex flex-row py-3 px-4">
<img
v-if="shouldDisplaySideImage"
@ -12,7 +12,9 @@
:alt="altText" />
<div class="order-2">
<p class="m-0">
<span v-for="token in tokens" :key="token">
<span
v-for="token in tokens"
:key="token">
<span v-if="isInlineImageToken(token)">
<img
v-if="hasImage"
@ -31,43 +33,43 @@
</template>
<script>
import baseInputButton from "@/digital-components/base-input-button/base-input-button";
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
import { splitCopyOnCMSPlaceHolder } from "@/helpers/cms-content-helper";
import baseInputButton from '@/digital-components/base-input-button/base-input-button.vue';
import inputButtonWrapperMixin from '@/mixins/input-button-wrapper-mixin.js';
import { splitCopyOnCMSPlaceHolder } from '@/helpers/cms-content-helper.js';
const INLINE_IMAGE_TOKEN = "custom:inlineImage";
const INLINE_IMAGE_TOKEN = 'custom:inlineImage';
function isInlineImageToken(token) {
return token.includes(INLINE_IMAGE_TOKEN);
}
function getInlineAltText(token) {
let innerTokens = token.split(",");
const innerTokens = token.split(',');
return innerTokens[1] ?? "";
return innerTokens[1] ?? '';
}
export default {
name: "payment-method-list-button",
mixins: [inputButtonWrapperMixin],
name: 'payment-method-list-button',
components: {
baseInputButton,
},
methods: {
isInlineImageToken,
getInlineAltText,
baseInputButton
},
mixins: [inputButtonWrapperMixin],
computed: {
tokens() {
return splitCopyOnCMSPlaceHolder(this.buttonLabel ?? "");
return splitCopyOnCMSPlaceHolder(this.buttonLabel ?? '');
},
hasImage() {
return !!this.buttonImage;
},
shouldDisplaySideImage() {
return this.hasImage && this.tokens.every((token) => !isInlineImageToken(token));
},
}
},
methods: {
isInlineImageToken,
getInlineAltText
}
};
</script>

View file

@ -1,29 +1,29 @@
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { shallowMount } from '@vue/test-utils';
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import paymentMethodQuestion from "@/layouts/payment-method/payment-method-question/payment-method-question";
import paymentMethodQuestion from '@/layouts/payment-method/payment-method-question/payment-method-question.vue';
const testConstants = {
cms: {
question: {
text: "Choose a payment option",
text: 'Choose a payment option'
},
answers: {
optionA: {
name: "NameA",
text: "TextA",
subText: "SubTextA",
imageId: "idA",
image: "imageA",
subWidget: "subWidgetA",
name: 'NameA',
text: 'TextA',
subText: 'SubTextA',
imageId: 'idA',
image: 'imageA',
subWidget: 'subWidgetA'
},
optionB: {
name: "NameB",
text: "TextB",
subText: "SubTextB",
imageId: "idB",
image: "imageB",
subWidget: "subWidgetB",
name: 'NameB',
text: 'TextB',
subText: 'SubTextB',
imageId: 'idB',
image: 'imageB',
subWidget: 'subWidgetB'
},
},
},
@ -31,7 +31,30 @@ const testConstants = {
let cmsContent;
describe("Payment Method Question", () => {
function generateDefaultProps() {
return {
modelValue: 'modelValue'
};
}
function setupMocks(customMountOptions) {
const mountOptions = getMountOptions(customMountOptions);
const mockMixin = {
methods: {
getCmsContent: jest.fn((widgetName, cmsFieldName) => cmsContent?.[widgetName]?.[cmsFieldName] ?? '')
}
};
mountOptions.global.mixins = [mockMixin];
const wrapper = shallowMount(paymentMethodQuestion, mountOptions);
wrapper.vm.setCmsContent = jest.fn();
return { wrapper };
}
describe('Payment Method Question', () => {
beforeEach(() => {
cmsContent = {
PaymentMethodWidget: {
@ -43,7 +66,7 @@ describe("Payment Method Question", () => {
SubText: testConstants.cms.answers.optionA.subText,
ImageId: testConstants.cms.answers.optionA.imageId,
AnswerImageUrl: testConstants.cms.answers.optionA.image,
SubWidgetName: testConstants.cms.answers.optionA.subWidget,
SubWidgetName: testConstants.cms.answers.optionA.subWidget
},
{
Name: testConstants.cms.answers.optionB.name,
@ -51,19 +74,19 @@ describe("Payment Method Question", () => {
SubText: testConstants.cms.answers.optionB.subText,
ImageId: testConstants.cms.answers.optionB.imageId,
AnswerImageUrl: testConstants.cms.answers.optionB.image,
SubWidgetName: testConstants.cms.answers.optionB.subWidget,
},
],
},
SubWidgetName: testConstants.cms.answers.optionB.subWidget
}
]
}
};
});
it("Should map cms content correctly", () => {
it('Should map cms content correctly', () => {
// Arrange
const props = generateDefaultProps();
const { wrapper } = setupMocks({
propsData: props,
propsData: props
});
// Act
@ -74,21 +97,21 @@ describe("Payment Method Question", () => {
{
buttonLabel: testConstants.cms.answers.optionA.text,
altText: testConstants.cms.answers.optionA.text,
groupName: "payment-method",
groupName: 'payment-method',
value: testConstants.cms.answers.optionA.name,
buttonImage: testConstants.cms.answers.optionA.image,
},
{
buttonLabel: testConstants.cms.answers.optionB.text,
altText: testConstants.cms.answers.optionB.text,
groupName: "payment-method",
groupName: 'payment-method',
value: testConstants.cms.answers.optionB.name,
buttonImage: testConstants.cms.answers.optionB.image,
},
]);
});
it("Handles null cms content gracefully", () => {
it('Handles null cms content gracefully', () => {
// Arrange
cmsContent = {};
const props = generateDefaultProps();
@ -104,27 +127,3 @@ describe("Payment Method Question", () => {
expect(mappedContent).toEqual([]);
});
});
function generateDefaultProps() {
return {
modelValue: "modelValue",
};
}
function setupMocks(customMountOptions) {
const mountOptions = getMountOptions(customMountOptions);
const mockMixin = {
methods: {
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
}),
},
};
mountOptions.global.mixins = [mockMixin];
const wrapper = shallowMount(paymentMethodQuestion, mountOptions);
wrapper.vm.setCmsContent = jest.fn();
return { wrapper };
}

View file

@ -1,6 +1,7 @@
<template>
<div class="payment-method-question">
<buttonQuestion
v-model="selectedMethod"
groupName="payment-method"
buttonTypeString="payment-method-list-button"
:buttonTypeObject="paymentMethodListButton"
@ -9,36 +10,27 @@
:answers="paymentMethodAnswerData"
isRequired
:validationRules="validationRules"
v-model="selectedMethod"
textPosition="text-start" />
</div>
</template>
<script>
import buttonQuestion from "@/digital-components/button-question/button-question";
import paymentMethodListButton from "./payment-method-list-button/payment-method-list-button";
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
import paymentMethodListButton from './payment-method-list-button/payment-method-list-button.vue';
export default {
name: "payment-method-question",
data() {
return {
paymentMethodListButton: paymentMethodListButton,
};
name: 'payment-method-question',
components: {
buttonQuestion
},
props: {
modelValue: String,
validationRules: String,
validationRules: String
},
methods: {
getAnswersNullSafe(widgetName) {
const rawData = this.getCmsContent(widgetName, "Answers");
if (!rawData) {
return [];
} else {
return rawData;
}
},
data() {
return {
paymentMethodListButton
};
},
computed: {
selectedMethod: {
@ -46,29 +38,37 @@ export default {
return this.modelValue;
},
set: function (selectedMethod) {
this.$emit("update:modelValue", selectedMethod);
this.$emit('update:modelValue', selectedMethod);
},
},
paymentMethodQuestionText() {
return this.getCmsContent("PaymentMethodWidget", "QuestionText");
return this.getCmsContent('PaymentMethodWidget', 'QuestionText');
},
paymentMethodAnswerData() {
const cmsData = this.getAnswersNullSafe("PaymentMethodWidget");
const cmsData = this.getAnswersNullSafe('PaymentMethodWidget');
return cmsData.map((answer) => {
return {
buttonLabel: answer.Text,
altText: answer.Text,
groupName: "payment-method",
groupName: 'payment-method',
value: answer.Name,
buttonImage: answer.AnswerImageUrl,
buttonImage: answer.AnswerImageUrl
};
});
},
},
components: {
buttonQuestion,
}
},
methods: {
getAnswersNullSafe(widgetName) {
const rawData = this.getCmsContent(widgetName, 'Answers');
if (!rawData) {
return [];
}
return rawData;
}
}
};
</script>

View file

@ -4,7 +4,9 @@
v-slot="{ meta }"
@submit="onSubmit"
@invalidSubmit="onInvalidSubmit">
<loadingModal notFullScreen ref="loadingModal" />
<loadingModal
ref="loadingModal"
notFullScreen />
<div class="page-container-grouped-styles">
<siteHeader
ref="siteHeader"
@ -43,17 +45,17 @@
<script>
// Components
import siteHeader from '@/iss-components/site-header/site-header.vue';
import navbar from "@/iss-components/nav-bar/nav-bar.vue";
import navbar from '@/iss-components/nav-bar/nav-bar.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 paymentMethodQuestion from "@/layouts/payment-method/payment-method-question/payment-method-question.vue";
import paymentMethodQuestion from '@/layouts/payment-method/payment-method-question/payment-method-question.vue';
import loadingModal from '@/iss-components/loading-modal/loading-modal.vue';
// Supporting Items
import settleAllPromises from '@/helpers/layout-helper';
import { useMainStore } from '@/store';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import { paymentMethods } from "@/constants/payment-method-constants";
import { paymentMethods } from '@/constants/payment-method-constants';
import { Form, defineRule } from 'vee-validate';
@ -73,7 +75,7 @@ export default {
navbar,
reviewDropdown,
paymentMethodQuestion,
loadingModal,
loadingModal
},
async beforeRouteEnter(to, from, next) {
// Call APIs
@ -102,8 +104,8 @@ export default {
});
},
data() {
return {
paymentMethodInternalModel: this.getPaymentMethodFromStore(),
return {
paymentMethodInternalModel: this.getPaymentMethodFromStore()
};
},
computed: {
@ -113,11 +115,11 @@ export default {
customCtaCopy() {
switch (this.paymentMethod) {
case paymentMethods.CREDIT_CARD:
return "Continue to checkout";
return 'Continue to checkout';
case paymentMethods.PAYPAL:
return "Continue to Paypal";
return 'Continue to Paypal';
case paymentMethods.AFTERPAY:
return "Continue to Afterpay";
return 'Continue to Afterpay';
default:
return null;
}
@ -140,7 +142,12 @@ export default {
}
return this.paymentMethodInternalModel;
},
}
},
watch: {
customCtaCopy(newValue) {
this.updateFooterButtonText(newValue);
}
},
methods: {
arePagePrerequisitesValid() {
@ -212,7 +219,7 @@ export default {
);
},
getPaymentMethodFromStore() {
const piaType = useMainStore().order.payment.piaType;
const { piaType } = useMainStore().order.payment;
const isPia = useMainStore().order.payment.isPia && !!piaType;
return isPia ? piaType : paymentMethods.LATER;
@ -226,7 +233,7 @@ export default {
async forwardButtonAction() {
await useMainStore().savePaymentMethodChoice(this.paymentMethod);
if (this.paymentMethod == paymentMethods.LATER) {
if (this.paymentMethod === paymentMethods.LATER) {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.$route
@ -240,32 +247,13 @@ export default {
// if we don't have a work order in delete substatus, set the flag and submit.
// we need a work order number for pia so we can pass it to safeliteHop.
if (!store.getters.order.workOrderNumber) {
try {
await submitWorkOrder({
pageNameToLog: "payment-method",
submitAfterSave: false,
createDeleteStatusWorkOrderForPia: true,
});
} catch (error) {
console.log("error: response from pia submit work order:" + error.message);
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
this.$route.params[routerParams.DISPLAY_PIA_ALERT] = true;
return;
}
}
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_PAY_NOW,
this.$route
);
},
},
watch: {
customCtaCopy(newValue) {
this.updateFooterButtonText(newValue);
},
},
}
}
};
</script>

View file

@ -13,7 +13,7 @@ import damageLocationsSelected from '@/constants/damage-locations-selected';
import coverageStatuses from '@/constants/coverage-statuses';
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from '@/constants/schedule-constants';
import { convertDateStringToDate, getDateDifferenceInDays, militaryToTwelveHourTime } from '@/helpers/date-helper';
import { paymentMethods } from "@/constants/payment-method-constants";
import { paymentMethods } from '@/constants/payment-method-constants';
const storeId = 'main';
@ -150,7 +150,7 @@ const getDefaultState = () => ({
},
parentAccountNumber: 0,
isPia: null,
piaType: null,
piaType: null
},
contactInfo: {
firstName: null,