diff --git a/jest.config.js b/jest.config.js index c5401c28f..146264edd 100644 --- a/jest.config.js +++ b/jest.config.js @@ -17,10 +17,8 @@ module.exports = { "!src/layouts/capability-questions/**/*.vue", "!src/layouts/part-questions/**/*.vue", "!src/layouts/reveal/**/*.vue", - "!src/layouts/quote/**/*.vue", "!src/ux-components/text-link/**/*.vue", "!src/common-components/question-chain/**/*.vue", - "!src/layouts/quote/**/*.vue", // Temporary "!src/layouts/vin-lookup/**/*.vue", //Temporary for Quote page testing "!src/common-components/funnel-header/menu-modal/**/*.vue", // END diff --git a/src/common-components/button-question/button-question.spec.js b/src/common-components/button-question/button-question.spec.js index 006cbcf2c..132e5edb9 100644 --- a/src/common-components/button-question/button-question.spec.js +++ b/src/common-components/button-question/button-question.spec.js @@ -1,4 +1,4 @@ -import { shallowMount } from "@vue/test-utils"; +import { shallowMount, mount } from "@vue/test-utils"; import buttonQuestion from "@/common-components/button-question/button-question"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; @@ -115,6 +115,38 @@ describe("buttonQuestion.vue", () => { "2020", ]); }); + test("should accept an imported component for buttonTypeObject and successfully add it to components", async () => { + // Arrange + const mockComponent = { + name: "mockComponent", + methods: { + mockComponentMethod() { + return "mockComponentMethod return value"; + }, + }, + }; + + const wrapper = await shallowMount( + buttonQuestion, + setupMocks({ + propsData: { + buttonTypeString: "mockComponent", + buttonTypeObject: mockComponent, + }, + }) + ); + + // Act + const componentList = wrapper.vm.$options.components; + const componentExists = !!componentList.mockComponent; + const componentNameMatches = componentList.mockComponent.name === mockComponent.name; + const componentMethodMatches = + componentList.mockComponent.methods.mockComponentMethod() === + mockComponent.methods.mockComponentMethod(); + + // Assert + expect(componentExists && componentNameMatches && componentMethodMatches).toBe(true); + }); }); describe("buttonsInfo", () => { diff --git a/src/layouts/quote/service-package-question/service-package-question-test-helper.js b/src/layouts/quote/service-package-question/service-package-question-test-helper.js new file mode 100644 index 000000000..36f938a7e --- /dev/null +++ b/src/layouts/quote/service-package-question/service-package-question-test-helper.js @@ -0,0 +1,580 @@ +export const mockProcessedCmsContent = { + "05_01_CSR_Quote_Standard_Repair": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + "05_01_CSR_Quote_Recal": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + "05_01_CSR_Quote_RearGlass": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + "05_01_CSR_Quote_RearGlass+NonWindshield": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + "05_01_CSR_Quote_RearGlass+Windshield": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + "05_01_CSR_Quote_RearGlassNoFrontFit": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + "05_01_CSR_Quote_Windshield+SideGlass": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + "05_01_CSR_Quote_SideGlass": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + "05_01_CSR_Quote_NoWiperFit": { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, + badCustomValue: { + EconomyServicePackage: { + HeaderText: "Economy service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: + "{if:custom:frontWipersApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{else}{if:custom:rearWiperApplicableForTierTwo}New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.{end}{end}", + }, + StandardServicePackage: { + HeaderText: "Standard service", + SubheaderText: "MOST POPULAR", + BodyText: + "", + Image: "", + FooterText: "", + }, + PremiumServicePackage: { + HeaderText: "Premium service", + SubheaderText: "", + BodyText: + "", + Image: "", + FooterText: "", + }, + }, +}; + +export const inputQuestionWidgetAnswers = { + CashServicePackageQuestionWidget: { + Answers: [ + { + Name: "TierOne", + SubWidgetName: "EconomyServicePackage", + }, + { + Name: "TierTwo", + SubWidgetName: "StandardServicePackage", + }, + { + Name: "TierThree", + SubWidgetName: "PremiumServicePackage", + }, + ], + }, + InsuranceServicePackageQuestionWidget: { + Answers: [ + { + Name: "TierOne", + SubWidgetName: "EconomyServicePackage", + }, + { + Name: "TierTwo", + SubWidgetName: "StandardServicePackage", + }, + { + Name: "TierThree", + SubWidgetName: "PremiumServicePackage", + }, + ], + }, +}; + +export const expectedModifiedAnswers = { + "05_01_CSR_Quote_Standard_Repair": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$500.22", + buttonFooterCopy: + "New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.", + }, + tierTwo: { + value: "TierTwo", + buttonLabel: "Standard service", + buttonLabelSubCopy: "MOST POPULAR", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$585.90", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$621.40", + buttonFooterCopy: "", + }, + }, + "05_01_CSR_Quote_Recal": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$500.22", + buttonFooterCopy: + "New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.", + }, + tierTwo: { + value: "TierTwo", + buttonLabel: "Standard service", + buttonLabelSubCopy: "MOST POPULAR", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$585.90", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$621.40", + buttonFooterCopy: "", + }, + }, + "05_01_CSR_Quote_RearGlass": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$350.22", + buttonFooterCopy: + "New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.", + }, + tierTwo: { + value: "TierTwo", + buttonLabel: "Standard service", + buttonLabelSubCopy: "MOST POPULAR", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$374.70", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$460.38", + buttonFooterCopy: "", + }, + }, + "05_01_CSR_Quote_RearGlass+NonWindshield": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$350.22", + buttonFooterCopy: + "New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.", + }, + tierTwo: { + value: "TierTwo", + buttonLabel: "Standard service", + buttonLabelSubCopy: "MOST POPULAR", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$374.70", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$460.38", + buttonFooterCopy: "", + }, + }, + "05_01_CSR_Quote_RearGlass+Windshield": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$350.22", + buttonFooterCopy: + "New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.", + }, + tierTwo: { + value: "TierTwo", + buttonLabel: "Standard service", + buttonLabelSubCopy: "MOST POPULAR", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$460.38", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$495.88", + buttonFooterCopy: "", + }, + }, + "05_01_CSR_Quote_RearGlassNoFrontFit": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$350.22", + buttonFooterCopy: + "New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.", + }, + tierTwo: { + value: "TierTwo", + buttonLabel: "Standard service", + buttonLabelSubCopy: "MOST POPULAR", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$374.70", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$410.20", + buttonFooterCopy: "", + }, + }, + "05_01_CSR_Quote_Windshield+SideGlass": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$350.22", + buttonFooterCopy: + "New wiper blades are not included with Economy service. Because chips can disrupt the glass surface, we recommend new wipers after a repair.", + }, + tierTwo: { + value: "TierTwo", + buttonLabel: "Standard service", + buttonLabelSubCopy: "MOST POPULAR", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$435.90", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$471.40", + buttonFooterCopy: "", + }, + }, + "05_01_CSR_Quote_SideGlass": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$350.22", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$471.40", + buttonFooterCopy: "", + }, + }, + "05_01_CSR_Quote_NoWiperFit": { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$350.22", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$385.72", + buttonFooterCopy: "", + }, + }, + badCustomValue: { + tierOne: { + value: "TierOne", + buttonLabel: "Economy service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$350.22", + buttonFooterCopy: "", + }, + tierThree: { + value: "TierThree", + buttonLabel: "Premium service", + buttonLabelSubCopy: "", + buttonBodyCopy: + "", + buttonAuxillaryCopy: "$385.72", + buttonFooterCopy: "", + }, + }, +}; diff --git a/src/layouts/quote/service-package-question/service-package-question.spec.js b/src/layouts/quote/service-package-question/service-package-question.spec.js new file mode 100644 index 000000000..043037995 --- /dev/null +++ b/src/layouts/quote/service-package-question/service-package-question.spec.js @@ -0,0 +1,595 @@ +import { shallowMount, mount } from "@vue/test-utils"; +import servicePackageQuestion from "./service-package-question"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { + expectedModifiedAnswers, + mockProcessedCmsContent, + inputQuestionWidgetAnswers, +} from "./service-package-question-test-helper"; + +jest.mock("@/store", () => ({ + commit: jest.fn(), + dispatch: jest.fn(), +})); + +describe("service-package-question.vue", () => { + beforeEach(async () => { + processedCmsContent = inputQuestionWidgetAnswers; + mockMixin = { + methods: { + getCmsContent: jest.fn((widgetName, cmsFieldName) => { + return processedCmsContent[widgetName][cmsFieldName]; + }), + }, + }; + mockProps = { + modelValue: "initialValue", + isInsuranceSelected: false, + insuranceCmsWidgetName: "InsuranceServicePackageQuestionWidget", + cashCmsWidgetName: "CashServicePackageQuestionWidget", + availableLineItems: [ + { + partNumber: "001", + Description: "Windshield with Recal", + partType: "Windshield", + Quantity: "1", + BasePartNumber: "001", + Color: "Green", + CanSafeliteRecalibrate: true, + price: 350.22, + }, + { + partNumber: "RAIN DEFENSE", + description: null, + partType: "RAIN DEFENSE", + price: 35.5, + }, + ], + }; + const packageNameKey = "05_01_CSR_Quote_Standard_Repair"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + }); + it("should emit captured value", () => { + // Arrange + const wrapper = setupMocks({}); + // Act + wrapper.componentVM.selectedValues = "newValue"; + + // Assert + expect(wrapper.emitted()["update:modelValue"][0][0]).toEqual("newValue"); + }); + it("should have the correct insurance pricing text when insurance is selected", () => { + // Arrange + mockProps.isInsuranceSelected = true; + const wrapper = setupMocks({}); + // Act + + // Assert + expect( + wrapper.vm.servicePackageAnswers[0].buttonAuxillaryCopy.includes("As little as") + ).toBe(true); + }); + it("should return [] from nullSafeAvailableLineItems and not error out if availableLineItems is null", () => { + // Arrange + mockProps.availableLineItems = null; + const wrapper = setupMocks({}); + // Act + + // Assert + expect(wrapper.vm.nullSafeAvailableLineItems).toEqual([]); + }); + it("should return a null servicePackageAnswers if the cmsContent is falsy", () => { + // Arrange + mockMixin = { + methods: { + getCmsContent: jest.fn((widgetName, cmsFieldName) => { + return null; + }), + }, + }; + const wrapper = setupMocks({}); + + // Assert + expect(wrapper.vm.servicePackageAnswers).toBe(null); + }); + it("should treat an undefined 'getCustomValueFromString' as a false value and not error out", () => { + // Arrange + const packageNameKey = "badCustomValue"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Windshield" }], + }, + }, + hasAnyNonWindshieldGlassParts: false, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer should not be created + expect(wrapper.vm.servicePackageAnswers.length).toBe(2); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); +}); +describe("service-package-question.vue, matching business rules for package display", () => { + // mock scenarios in figma: + // https://www.figma.com/file/Spt9hBtGj8r8PFFGNIN3G5/New-Funnel?node-id=100%3A11383 + beforeEach(async () => { + processedCmsContent = inputQuestionWidgetAnswers; + mockMixin = { + methods: { + getCmsContent: jest.fn((widgetName, cmsFieldName) => { + return processedCmsContent[widgetName][cmsFieldName]; + }), + }, + }; + mockProps = { + modelValue: "initialValue", + isInsuranceSelected: false, + insuranceCmsWidgetName: "InsuranceServicePackageQuestionWidget", + cashCmsWidgetName: "CashServicePackageQuestionWidget", + availableLineItems: [ + { + partNumber: "001", + Description: "Windshield with Recal", + partType: "Windshield", + Quantity: "1", + BasePartNumber: "001", + Color: "Green", + CanSafeliteRecalibrate: true, + price: 350.22, + }, + { + partNumber: "RAIN DEFENSE", + description: null, + partType: "RAIN DEFENSE", + price: 35.5, + }, + ], + }; + }); + it("should match the 05_01_CSR_Quote_Standard_Repair mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_Standard_Repair"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + mockProps.availableLineItems.push(driverFrontWiperLineItem); + mockProps.availableLineItems.push(passengerFrontWiperLineItem); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: true, + glassToReplace: [], + }, + }, + hasAnyNonWindshieldGlassParts: false, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierTwo + ); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[2], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); + it("should match the 05_01_CSR_Quote_Recal mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_Recal"; + mockProps.availableLineItems.push(recalLineItem); + mockProps.availableLineItems.push(driverFrontWiperLineItem); + mockProps.availableLineItems.push(passengerFrontWiperLineItem); + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Windshield" }], + }, + }, + hasAnyNonWindshieldGlassParts: false, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierTwo + ); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[2], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); + it("should match the 05_01_CSR_Quote_RearGlass mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_RearGlass"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + mockProps.availableLineItems.push(driverFrontWiperLineItem); + mockProps.availableLineItems.push(passengerFrontWiperLineItem); + mockProps.availableLineItems.push(rearWiperLineItem); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Rear" }], + }, + }, + hasAnyNonWindshieldGlassParts: true, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierTwo + ); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[2], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); + it("should match the 05_01_CSR_Quote_RearGlass+NonWindshield mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_RearGlass+NonWindshield"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + mockProps.availableLineItems.push(driverFrontWiperLineItem); + mockProps.availableLineItems.push(passengerFrontWiperLineItem); + mockProps.availableLineItems.push(rearWiperLineItem); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [ + { glassLocation: "Rear" }, + { glassLocation: "Driver" }, + ], + }, + }, + hasAnyNonWindshieldGlassParts: true, + }, + }, + }, + }); + //console.log(wrapper.vm.servicePackageAnswers); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierTwo + ); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[2], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); + it("should match the 05_01_CSR_Quote_RearGlass+Windshield mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_RearGlass+Windshield"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + mockProps.availableLineItems.push(driverFrontWiperLineItem); + mockProps.availableLineItems.push(passengerFrontWiperLineItem); + mockProps.availableLineItems.push(rearWiperLineItem); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [ + { glassLocation: "Rear" }, + { glassLocation: "Windshield" }, + ], + }, + }, + hasAnyNonWindshieldGlassParts: true, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierTwo + ); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[2], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); + it("should match the 05_01_CSR_Quote_RearGlassNoFrontFit mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_RearGlassNoFrontFit"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + mockProps.availableLineItems.push(rearWiperLineItem); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Rear" }], + }, + }, + hasAnyNonWindshieldGlassParts: true, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierTwo + ); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[2], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); + it("should match the 05_01_CSR_Quote_Windshield+SideGlass mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_Windshield+SideGlass"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + mockProps.availableLineItems.push(driverFrontWiperLineItem); + mockProps.availableLineItems.push(passengerFrontWiperLineItem); + mockProps.availableLineItems.push(rearWiperLineItem); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [ + { glassLocation: "Driver" }, + { glassLocation: "Windshield" }, + ], + }, + }, + hasAnyNonWindshieldGlassParts: true, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierTwo + ); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[2], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); + it("should match the 05_01_CSR_Quote_SideGlass mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_SideGlass"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + mockProps.availableLineItems.push(driverFrontWiperLineItem); + mockProps.availableLineItems.push(passengerFrontWiperLineItem); + mockProps.availableLineItems.push(rearWiperLineItem); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Driver" }], + }, + }, + hasAnyNonWindshieldGlassParts: true, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer should not be created + expect(wrapper.vm.servicePackageAnswers.length).toBe(2); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); + it("should match the 05_01_CSR_Quote_NoWiperFit mock", () => { + // Arrange + const packageNameKey = "05_01_CSR_Quote_NoWiperFit"; + Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]); + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Windshield" }], + }, + }, + hasAnyNonWindshieldGlassParts: false, + }, + }, + }, + }); + + // Assert + // economy answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[0], + expectedModifiedAnswers[packageNameKey].tierOne + ); + // standard answer should not be created + expect(wrapper.vm.servicePackageAnswers.length).toBe(2); + // premium answer + runPackageAnswerExpectStatements( + wrapper.vm.servicePackageAnswers[1], + expectedModifiedAnswers[packageNameKey].tierThree + ); + }); +}); + +function runPackageAnswerExpectStatements(servicePackageAnswer, expectedOutput) { + expect(servicePackageAnswer.buttonLabel).toBe(expectedOutput.buttonLabel); + expect(servicePackageAnswer.buttonLabelSubCopy).toBe(expectedOutput.buttonLabelSubCopy); + expect(servicePackageAnswer.buttonBodyCopy).toBe(expectedOutput.buttonBodyCopy); + expect(servicePackageAnswer.buttonFooterCopy).toBe(expectedOutput.buttonFooterCopy); +} + +function setupMocks({ mountOptionsMockData, props = mockProps }) { + var mountOptionsMockDataDefault = { + store: { + getters: { + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Windshield" }], + }, + }, + hasAnyNonWindshieldGlassParts: false, + }, + }, + }; + mountOptionsMockData = Object.assign(mountOptionsMockDataDefault, mountOptionsMockData); + const mountOptions = getMountOptions(mountOptionsMockData); + + // Modify/augment default mount options + mountOptions.global.mixins = [mockMixin]; + mountOptions.propsData = props; + const wrapper = shallowMount(servicePackageQuestion, mountOptions); + + return wrapper; +} +/////////////// +// Constants // +/////////////// + +let processedCmsContent; + +let mockMixin; + +let mockProps; + +let recalLineItem = { + partNumber: "RECAL STATIC", + Description: "Recalibration", + partType: "recalibration", + Quantity: "1", + price: 150.0, +}; + +let driverFrontWiperLineItem = { + partNumber: "SBB16", + description: "SAFELITE BEAM BLADE 16", + partType: "FRONT WIPER", + price: 32.64, +}; + +let passengerFrontWiperLineItem = { + partNumber: "SBB26", + description: "SAFELITE BEAM BLADE 26", + partType: "FRONT WIPER", + price: 53.04, +}; + +let rearWiperLineItem = { + partNumber: "SBBR12A", + description: "SAFELITE REAR BLADE 12A", + partType: "REAR WIPER", + price: 24.48, +}; diff --git a/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.spec.js b/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.spec.js new file mode 100644 index 000000000..fefef4044 --- /dev/null +++ b/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.spec.js @@ -0,0 +1,134 @@ +import { mount } from "@vue/test-utils"; +import servicePackageRadio from "./service-package-radio"; +import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin"; + +describe("service-package-radio.vue", () => { + it("Should include buttonLabel in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabel"])); + }); + + it("Should include buttonLabelAuxillaryCopy in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabelAuxillaryCopy"])); + }); + + it("Should include buttonLabelSubCopy in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabelSubCopy"])); + }); + it("Should include buttonFooterCopy in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonFooterCopy"])); + }); + it("Should get 5 strings from getArrayOfListItemsFromRawCmsCopy when provided with a buttonBodyCopy", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + // Act + const results = wrapper.vm.getArrayOfListItemsFromRawCmsCopy(wrapper.vm.buttonBodyCopy); + + // Assert + expect(results.length).toBe(5); + }); + it("Should get strings from getArrayOfListItemsFromRawCmsCopy without