diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f11da4951..c8184f93f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -127,4 +127,45 @@ stages: indexDeployVariables: __VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__) __VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__) + cfDistributionId: $(cfDistributionId) + + # Prod Build/Deploy + - stage: Prod + condition: eq(variables['Build.SourceBranch'], variables['prod-branch'] ) + variables: + - group: FixMyGlassProd + jobs: + - deployment: prodBuildDeployment + displayName: Build and Deploy FMG - Prod + environment: digitalCloud-prod + container: node + workspace: + clean: all + strategy: + runOnce: + deploy: + steps: + - checkout: self + clean: true + - template: templates/digital/step-build-vue.yml@AzureDevOps + parameters: + buildOutputDir: dist + - template: templates/digital/step-deploy-vue.yml@AzureDevOps + parameters: + artifactName: vueDist + awsProfile: $(prodDeploymentProfile) + outputPath: /fmg/ + deployBuckets: + safelite-prod-fmg-us-east-1: + clearFolder: true + deployFolder: '' + region: us-east-1 + appDeployVariables: + __VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__) + __VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__) + __VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__) + __VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__) + indexDeployVariables: + __VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__) + __VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__) cfDistributionId: $(cfDistributionId) \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 82b2b587e..839db4378 100644 --- a/jest.config.js +++ b/jest.config.js @@ -27,13 +27,14 @@ module.exports = { "!src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue", "!src/common-components/dropdown-question/dropdown-question.vue", "!src/common-components/textbox-question/textbox-question.vue", + "!src/ux-components/alert\alert.vue", "!src/helpers/validation-rules.js", // END ], // ! means exclude from coverage. testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"], coverageThreshold: { global: { - statements: 85, + statements: 84, // Got the go ahead from Mark to temporarily lower this. Taking out initialize component made the year,make,model and style coverage drop a bit. Once unit tests for license plate lookup, vin lookup and address lookup are in the coverage should go back up to 90 }, }, diff --git a/src/App.vue b/src/App.vue index f161d937e..71b56feaf 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,6 +1,7 @@ @@ -52,7 +52,6 @@ import listButtonHorizontal from "@/ux-components/list-button-horizontal/list-bu import listCard from "@/ux-components/list-card/list-card"; import { ErrorMessage } from 'vee-validate'; import radio from "@/ux-components/radio/radio"; -import { queryStrings } from "@/constants/query-strings"; export default { name: "buttonQuestion", @@ -134,8 +133,6 @@ export default { return answer.Name ? answer.Name : answer; }, handleCheckedChanged(val) { - - this.pushEventToGA(this.$route.query[queryStrings.FMG_PAGE], this.GaActions.CLICKED, val.value, true); if(this.isMultiSelect && this.selectedValues) { // Add or remove item to array of data to emit diff --git a/src/common-components/dropdown-question/dropdown-question.vue b/src/common-components/dropdown-question/dropdown-question.vue index a64d873f9..8e6ae0faa 100644 --- a/src/common-components/dropdown-question/dropdown-question.vue +++ b/src/common-components/dropdown-question/dropdown-question.vue @@ -1,5 +1,5 @@ @@ -159,6 +166,7 @@ export default { border: 1px solid $gray-500; border-radius: .5rem; min-height: 3rem; + padding: 12px 16px; &::placeholder { color: $gray-500; } @@ -182,4 +190,4 @@ export default { display: none; } } - \ No newline at end of file + diff --git a/src/constants/analytics.js b/src/constants/analytics.js index f6f6ff82e..a3f057150 100644 --- a/src/constants/analytics.js +++ b/src/constants/analytics.js @@ -26,6 +26,7 @@ const GaLabels = { ERROR: 'Error', LICENSE_PLATE_LOOKUP: 'License_Plate_Look_Up', VIN_LOOKUP: 'Vin_Look_Up', + ADDRESS_LOOKUP: 'Address_Look_up', }; diff --git a/src/constants/error-messages.js b/src/constants/error-messages.js index a064cfecb..b4d073496 100644 --- a/src/constants/error-messages.js +++ b/src/constants/error-messages.js @@ -18,8 +18,8 @@ const errorMessages = { LAST_NAME_REQUIRED: "Please enter your last name", EMAIL_ADDRESS_REQUIRED: "Please enter your email address", EMAIL_ADDRESS_FORMAT: "Please enter a valid email address", - SERVICE_ZIP_REQUIRED: "Please enter your Service ZIP", - SERVICE_ZIP_FORMAT: "Please enter a valid Service ZIP", + SERVICE_ZIP_REQUIRED: "Please enter your service ZIP", + SERVICE_ZIP_FORMAT: "Please enter a valid service ZIP", VIN_REQUIRED: "Please enter your VIN", VIN_FORMAT: "Invalid VIN. Please make sure that you entered the correct 17-digit, alpha-numeric number. VINs do not contain the letters I, O, or Q", OPTION_REQUIRED: "Please select an option", diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index 179b484ef..e8349ef40 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -23,6 +23,7 @@ const storeMutations = { UPDATE_REGISTRATION_FIRST_NAME: "updateRegistrationFirstName", UPDATE_REGISTRATION_LAST_NAME: "updateRegistrationLastName", UPDATE_SERVICE_LOCATION_ZIP_CODE: "updateServiceLocationZipCode", + UPDATE_SERVICE_LOCATION_STATE: "updateServiceLocationState", UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress", // ORDER MUTATIONS diff --git a/src/helpers/damage-helper.js b/src/helpers/damage-helper.js index a3b9a2878..55d10738d 100644 --- a/src/helpers/damage-helper.js +++ b/src/helpers/damage-helper.js @@ -3,11 +3,19 @@ import baseMixin from "@/mixins/base-mixin.js"; import { storeActions } from "@/constants/store-actions"; export function getDamageString() { + // If it's a repair it's always a windshield. + const isRepair = store.getters.damage.isRepair; + if(isRepair){ + return "windshield" + } + const damageLocations = store.getters.damage.glassToReplace; + let returnString; if (!damageLocations) { return; } + if (damageLocations.length > 1) { returnString = "match" } else { diff --git a/src/helpers/heritage-integration/cookie-helper.js b/src/helpers/heritage-integration/cookie-helper.js index e69c21419..f3b730f90 100644 --- a/src/helpers/heritage-integration/cookie-helper.js +++ b/src/helpers/heritage-integration/cookie-helper.js @@ -6,6 +6,8 @@ import { applicationConfig } from "@/constants/application-config"; Will update the cookie if present, or create a new one if not. */ export function updateOrCreateFunnelCookie() { + const wasClaimRegistrationDelayed = getFunnelCookie()?.HasDelayedClaimRegistration; + // Create the cookie document.cookie = `${cookieNames.FUNNEL_SESSION_INFO}={}; path=${applicationConfig.COOKIE_PATH}; ${getCookieDomainValue()};`; @@ -19,6 +21,7 @@ export function updateOrCreateFunnelCookie() { ReferralDate: store.getters.order.referralDate, ReferralCorrelationId: store.getters.order.referralCorrelationId, ReferralParentAccountNumber: store.getters.order.accountNumber, + HasDelayedClaimRegistration: wasClaimRegistrationDelayed }); } diff --git a/src/helpers/heritage-integration/navigation-helper.spec.js b/src/helpers/heritage-integration/navigation-helper.spec.js index 01bf5dcdc..e212284b8 100644 --- a/src/helpers/heritage-integration/navigation-helper.spec.js +++ b/src/helpers/heritage-integration/navigation-helper.spec.js @@ -305,7 +305,7 @@ describe("getPageToRouteExistingOrderTo", () => { describe("navigateToHeritageFunnel", () => { test("should save order", async () => { // Arrange - const mockReferralNumber = 2; + const mockReferralNumber = "2"; const mockCorrelationId = "55"; const mockReferralDate = "2022"; @@ -337,7 +337,7 @@ describe("navigateToHeritageFunnel", () => { test("should go to heritage funnel", async () => { // Arrange - const mockReferralNumber = 2; + const mockReferralNumber = "2"; const mockCorrelationId = "55"; const mockReferralDate = "2022"; diff --git a/src/helpers/heritage-integration/order-helper.js b/src/helpers/heritage-integration/order-helper.js index b18b64a85..d64ab865d 100644 --- a/src/helpers/heritage-integration/order-helper.js +++ b/src/helpers/heritage-integration/order-helper.js @@ -38,10 +38,10 @@ export async function saveOrder() { // Save the referral information back from the store. await baseMixin.methods.dispatchStoreAction(storeActions.SET_REFERRAL_INFORMATION, { - referralNumber: savedOrderInfo.data.referralNumber, + referralNumber: savedOrderInfo.data.referralNumber.toString(), referralCorrelationId: savedOrderInfo.data.referralCorrelationId, referralDate: savedOrderInfo.data.referralDate, - accountNumber: savedOrderInfo.data.accountNumber + accountNumber: savedOrderInfo.data.accountNumber.toString() }, false); // Update the cookie with the referral information when saved. diff --git a/src/helpers/heritage-integration/order-helper.spec.js b/src/helpers/heritage-integration/order-helper.spec.js index 803c94b6b..b66286d50 100644 --- a/src/helpers/heritage-integration/order-helper.spec.js +++ b/src/helpers/heritage-integration/order-helper.spec.js @@ -103,11 +103,12 @@ describe("saveOrder", () => { test("saveOrder => should set state order values", async () => { // Arrange - const mockReferralNumber = 2; + const mockReferralNumber = "2"; const mockCorrelationId = "55"; const mockReferralDate = "2022"; + const mockAccountNumber = "5"; - const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate); + const mockOrderInfo = getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate, mockAccountNumber); const mockData = { actionList: [ @@ -131,7 +132,8 @@ describe("saveOrder", () => { expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(storeActions.SET_REFERRAL_INFORMATION, { referralNumber: mockReferralNumber, referralDate: mockReferralDate, - referralCorrelationId: mockCorrelationId + referralCorrelationId: mockCorrelationId, + accountNumber: mockAccountNumber }, false); }); diff --git a/src/helpers/unit-test-helper.js b/src/helpers/unit-test-helper.js index 6577ed6ff..4f4214120 100644 --- a/src/helpers/unit-test-helper.js +++ b/src/helpers/unit-test-helper.js @@ -89,11 +89,12 @@ export function removeAllTestCookies() { }); } -export function getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate) { +export function getMockOrderInfo(mockReferralNumber, mockCorrelationId, mockReferralDate, accountNumber = "0") { return { referralNumber: mockReferralNumber, referralCorrelationId: mockCorrelationId, - referralDate: mockReferralDate + referralDate: mockReferralDate, + accountNumber: accountNumber } } diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index 653825016..e9578fb3b 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -12,28 +12,28 @@
- - - - { + this.pushEventToGA( + this.$route.query[this.queryStrings.FMG_PAGE], + this.GaActions.SUBMITTED, + this.GaLabels.ADDRESS_LOOKUP, + true + ); + }); + }, getRegistrationAddressFromStore() { return store.getters.vehicle.registration.address; }, @@ -180,7 +188,7 @@ export default { this.resetWarningsAndErrors(); // Lookup VIN(s) with the provided address - const vinLookup = this.lookupVin( + const vinLookupPromise = this.lookupVin( this.customerQuestions.lastName, this.customerQuestions.addressQuestions.streetAddress, this.customerQuestions.addressQuestions.zipCode, @@ -188,10 +196,10 @@ export default { ); // Verify if the service zip code or registration zip code provided is serviceable - const zipValidation = this.serviceZipCode ? this.validateZip(this.serviceZipCode) : this.validateZip(this.customerQuestions.addressQuestions.zipCode); + const serviceZipValidationPromise = this.serviceZipCode ? this.validateZip(this.serviceZipCode) : this.validateZip(this.customerQuestions.addressQuestions.zipCode); - const vinLookupResponse = await vinLookup; - const zipValidationResponse = await zipValidation; + const vinLookupResponse = await vinLookupPromise; + const serviceZipValidationResponse = await serviceZipValidationPromise; if (!vinLookupResponse.data.isStatePermissible) { // State Restrictions forbid lookup by address @@ -201,7 +209,7 @@ export default { } // if the neither the registration zip code or service zip code are not serviceable - this.isZipServicable = zipValidationResponse.data.isServiceable; + this.isZipServicable = serviceZipValidationResponse.data.isServiceable; if (!this.isZipServicable) { this.displayNonServiceableZipAlert = true; this.showServiceZipField = true; @@ -245,15 +253,24 @@ export default { // update data if the zip or service zip is servicable this.updateVehicleInfo(carsFound[0].vin, carFound); - this.updateCustomerInfo(); + this.updateCustomerInfo(serviceZipValidationResponse.data.state); } else if (carsFound.length > 1) { if (!this.isZipServicable) { return; } + // if multiple cars were found + let matchingCars = carsFound.filter(car => car.vehicle.carId === carEntered.carId); + if (matchingCars.length === 1) { + // and one and only one of them matches the carId entered, save the vehicle info + // so we can go to the Heritage Funnel directly + const matchingCar = matchingCars[0]; + this.updateVehicleInfo(matchingCar.vin, matchingCar.vehicle); + } + // update data if the zip or service zip is servicable - this.updateCustomerInfo(); + this.updateCustomerInfo(serviceZipValidationResponse.data.state); } this.navigateForward(carEntered, carsFound); @@ -285,13 +302,17 @@ export default { navigateAfterSaveToHeritageFunnel(this.$route); } } else if (carsFound.length > 1) { - // if multiple cars were found - if (carsFound.find(car => car.vehicle.carId === carEntered.carId)) { - // and one of them matches the car id entered + // if multiple cars were found + let matchingCars = carsFound.filter(car => car.vehicle.carId === carEntered.carId); + if (matchingCars.length === 1) { this.$refs.loadingModal.showModal(); + + // and one and only of them matches the car id entered + const matchingCar = matchingCars[0]; + this.updateVehicleInfo(matchingCar.vin, matchingCar.vehicle); navigateAfterSaveToHeritageFunnel(this.$route); } else { - // and there is no match, navigate to "address-vehicles" page + // if there are no matches or there are multiple matches, navigate to "address-vehicles" page this.$router.navigateAfterSave(this.navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, this.$route, {}, {}, carsFound); } } @@ -325,7 +346,7 @@ export default { store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicleInfo.imageVifNumber); store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicleInfo.imageColor); }, - updateCustomerInfo() { + updateCustomerInfo(serviceState) { store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, this.customerQuestions.addressQuestions.streetAddress); store.commit(storeMutations.UPDATE_REGISTRATION_CITY, this.customerQuestions.addressQuestions.city); store.commit(storeMutations.UPDATE_REGISTRATION_STATE, this.customerQuestions.addressQuestions.state); @@ -333,9 +354,9 @@ export default { store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, this.customerQuestions.firstName); store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, this.customerQuestions.lastName); store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZipCode); + store.commit(storeMutations.UPDATE_SERVICE_LOCATION_STATE, serviceState); store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.customerQuestions.emailAddress); - }, - + }, updateServiceLocationIfNecessary() { const serviceLocation = store.getters.order.serviceLocation; @@ -346,6 +367,9 @@ export default { } } }, + mounted() { + this.attachCustomEvents(); + }, computed: { AlertNonServiceableZipHeader(){ const zipCode = this.serviceZipCode ? this.serviceZipCode : this.customerQuestions.addressQuestions.zipCode; @@ -360,13 +384,14 @@ export default { return text; }, AlertMatchedDifferentVehicleBody(){ - let content = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText"); - content = content.replaceAll("{custom:glassText}", getDamageString()); - const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`; - const vinYmmExpected = `${store.getters.vehicle.year} ${store.getters.vehicle.make} ${store.getters.vehicle.model}`; - content = content.replaceAll("{custom:vinYmmFound}", vinYmmFound); - content = content.replaceAll("{custom:vinYmmExpected}", vinYmmExpected); + const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`; + const vinYmmExpected = `${store.getters.vehicle.year} ${store.getters.vehicle.make} ${store.getters.vehicle.model}`; + + const content = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText") + .replaceAll("{custom:glassText}", getDamageString()) + .replaceAll("{custom:vinYmmFound}", vinYmmFound) + .replaceAll("{custom:vinYmmExpected}", vinYmmExpected); return content; }, diff --git a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue index 4408a803f..f188cf214 100644 --- a/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue +++ b/src/layouts/address-lookup/customer-questions/address-questions/address-questions.vue @@ -1,32 +1,70 @@ @@ -29,7 +51,7 @@ import { errorMessages } from "@/constants/error-messages"; defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED)); defineRule("last-name-required", required(errorMessages.LAST_NAME_REQUIRED)); defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED)); -defineRule("email-address-format", regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT)); +defineRule("email-address-format", regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT)); export default ({ name: "customer-questions", diff --git a/src/layouts/address-vehicles/address-vehicles.vue b/src/layouts/address-vehicles/address-vehicles.vue index f21015061..34937bfb7 100644 --- a/src/layouts/address-vehicles/address-vehicles.vue +++ b/src/layouts/address-vehicles/address-vehicles.vue @@ -10,7 +10,7 @@ - -
+
{{ copy.split(':')[1].split(',')[1] }} @@ -240,4 +240,4 @@ export default { line-height: inherit; } } - \ No newline at end of file + diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js index 9afd7e39a..281947ae4 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js +++ b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js @@ -86,7 +86,6 @@ describe("license-plate-lookup.vue", () => { //Assert expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); - }); }); diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue index 5e7fdc2c1..38217009d 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.vue +++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue @@ -8,28 +8,73 @@
- +
- +
- +
- +
- +
- - - + + +
@@ -46,56 +91,25 @@ import alert from "@/ux-components/alert/alert"; import textboxQuestion from "@/common-components/textbox-question/textbox-question"; import loadingModal from '@/common-components/loading-modal/loading-modal.vue'; // Supporting files -import { - fetchCmsContentForPage -} from "@/helpers/cms-content-helper"; -import { - settleAllPromises -} from "@/helpers/layout-helper"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import { settleAllPromises } from "@/helpers/layout-helper"; import store from "@/store"; import baseMixin from "@/mixins/base-mixin.js"; -import { - storeActions -} from "@/constants/store-actions"; -import { - storeMutations -} from "@/constants/store-mutations"; -import { - errorMessages -} from "@/constants/error-messages"; -import { - navigateAfterSaveToHeritageFunnel -} from "@/helpers/heritage-integration/navigation-helper"; -import { - getDamageString, - isGlassAvailableForCarId, -} from "@/helpers/damage-helper"; -import { - required, - regex, -} from "@/helpers/validation-rules"; -import { - Form, - defineRule, -} from "vee-validate"; +import { storeActions } from "@/constants/store-actions"; +import { storeMutations } from "@/constants/store-mutations"; +import { errorMessages } from "@/constants/error-messages"; +import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; +import { getDamageString, isGlassAvailableForCarId, } from "@/helpers/damage-helper"; +import { required, regex, } from "@/helpers/validation-rules"; +import { Form, defineRule, } from "vee-validate"; // DEFINE VALIDATION RULES -defineRule( - "license-plate-required", - required(errorMessages.LICENSE_PLATE_REQUIRED) -); +defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIRED)); defineRule("zip-required", required(errorMessages.REGISTRATION_ZIP_REQUIRED)); -defineRule( - "email-address-required", - required(errorMessages.EMAIL_ADDRESS_REQUIRED) -); -defineRule( - "email-address-format", - regex( - /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/, - errorMessages.EMAIL_ADDRESS_FORMAT - ) -); +defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT)); +defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED)); +defineRule("email-address-format", regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT)); + export default { name: "license-plate-lookup", async beforeRouteEnter(to, from, next) { @@ -188,12 +202,12 @@ export default { }, attachCustomEvents() { this.prependActionToMethod(this, this.forwardButtonAction, () => { - this.pushEventToGA( + this.pushEventToGA( this.$route.query[this.queryStrings.FMG_PAGE], this.GaActions.SUBMITTED, this.GaLabels.LICENSE_PLATE_LOOKUP, true - ); + ); }); }, getLicensePlateFromStore() { @@ -212,20 +226,29 @@ export default { this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); }, async forwardButtonAction() { - const zipValidation = this.serviceZip ? - await this.validateZip(this.serviceZip) : - await this.validateZip(this.registrationZip); - if (!zipValidation.data.isServiceable) { + + //Call zip validation services + const registrationZipValidationPromise = this.validateZip(this.registrationZip); + const serviceZipValidationPromise = this.serviceZip ? this.validateZip(this.serviceZip) : null; + const registrationZipValidationResults = await registrationZipValidationPromise; + const serviceZipValidationResults = serviceZipValidationPromise !== null ? (await serviceZipValidationPromise) : registrationZipValidationResults; + + //Handle service zip validations + if (!serviceZipValidationResults.data.isServiceable) { this.$refs.funnelFooter.removeLoader(); this.isVinValid = true; this.isRegistrationZipServicable = false; this.isCarIdDifferent = false; this.zipToDisplay = this.serviceZip ? this.serviceZip : this.registrationZip; return; - } + } else if (!this.serviceZip) { + this.serviceZip = this.registrationZip; + } + + //Lookup vin const vinLookup = await this.lookupVin( this.licensePlate, - zipValidation.data.state + registrationZipValidationResults.data.state ).catch(() => { this.$refs.funnelFooter.removeLoader(); this.isVinValid = false; @@ -235,6 +258,7 @@ export default { this.isCarIdDifferent = vinLookup.data.vehicle.carId !== store.getters.vehicle.carId; + //Handle changing car if ( this.isCarIdDifferent && vinLookup.data.vehicle.carId !== this.previouslyEnteredCarId @@ -251,12 +275,15 @@ export default { return; } + //Save this.updateCustomerInfo( vinLookup.data.vin, vinLookup.data.vehicle, - zipValidation.data.state + registrationZipValidationResults.data.state, + serviceZipValidationResults.data.state ); - + + //Navigate this.navigateForward(); }, navigateForward() { @@ -281,12 +308,9 @@ export default { }); }, lookupVin(plate, state) { - return baseMixin.methods.dispatchStoreAction( - storeActions.LOOKUP_VIN_BY_PLATE, - { licensePlate: plate, licenseState: state } - ); + return baseMixin.methods.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_PLATE,{ licensePlate: plate, licenseState: state }, false); }, - updateCustomerInfo(vin, vehicleInfo, registrationState) { + updateCustomerInfo(vin, vehicleInfo, registrationState, serviceState) { if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) { store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); } @@ -304,6 +328,7 @@ export default { store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState); store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.registrationZip); store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZip); + store.commit(storeMutations.UPDATE_SERVICE_LOCATION_STATE, serviceState); store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email); }, }, @@ -335,4 +360,4 @@ export default { loadingModal, }, }; - \ No newline at end of file + diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js index b722fccbf..0ce0fe085 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.spec.js +++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js @@ -18,6 +18,7 @@ import store from "@/store"; import { validate } from "vee-validate"; import { damageLocationsSelected } from "@/constants/damage-locations-selected.js"; import { routerParams } from "@/router/router-constants/router-params"; +import * as cookieHelper from "@/helpers/heritage-integration/cookie-helper"; // Mock our module for promises. jest.mock("@/helpers/layout-helper.js", () => ({ @@ -29,6 +30,11 @@ jest.mock("@/helpers/cms-content-helper", () => ({ fetchCmsContentForPage: jest.fn(), })); +// Mock getFunnelCookie +jest.mock("@/helpers/heritage-integration/cookie-helper", () => ({ + getFunnelCookie: jest.fn(), +})); + // Mock Store jest.mock("@/store", () => ({ commit: jest.fn(), @@ -653,6 +659,10 @@ describe("vehicle-damage.vue", () => { }) }); +describe("vehicle-damage.vue wasDelayedClaimRegistration", () => { + test.todo("if wasDelayedClaimRegistration, should hide back button") +}); + // THE FOLLOWING TEST IS NOT NECESSARILY REQUIRED FOR COVERAGE // BUT KEEP FOR AN EXAMPLE OF A VALIDATION TEST // @@ -741,6 +751,7 @@ function setupMocks({pageHeaderWidgetHeaderText, mountOptionsMockData}) { settleAllPromises.mockImplementation(() => apiPromise); fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); + cookieHelper.getFunnelCookie = jest.spyOn(cookieHelper, "getFunnelCookie").mockReturnValue({}); //Mock damage initialize methods damageLocationQuestion.methods = { diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index ddeae5bec..d4e44feb7 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -32,7 +32,7 @@ :selectedDamageLocations="selectedDamageLocations" /> - @@ -56,10 +56,10 @@ defineRule("windshield-chip-count-required", required(errorMessages.WINDSHIELD_C defineRule("windshield-replace-options-required", required(errorMessages.WINSHIELD_REPLACE_OPTIONS_REQUIRED)); defineRule("check-for-repair-and-replace", (value, [otherFieldValue]) => { - if (value.toString().toUpperCase().includes(damageLocationsSelected.REPAIR.toUpperCase()) && - otherFieldValue.toString().toUpperCase().includes(damageLocationsSelected.WINDSHIELD.toUpperCase()) && - Array.isArray(otherFieldValue) && - otherFieldValue.length > 1) + if (value.toString().toUpperCase().includes(damageLocationsSelected.REPAIR.toUpperCase()) && + otherFieldValue.toString().toUpperCase().includes(damageLocationsSelected.WINDSHIELD.toUpperCase()) && + Array.isArray(otherFieldValue) && + otherFieldValue.length > 1) { return false; } @@ -72,8 +72,8 @@ defineRule("repair-only", (value) => { return false; }); defineRule("prevent-split-and-single-together", (value) => { - if (value.toString().toUpperCase().includes(damageLocationsSelected.SINGLE.toUpperCase()) && - (value.toString().toUpperCase().includes(damageLocationsSelected.DRIVER.toUpperCase()) || + if (value.toString().toUpperCase().includes(damageLocationsSelected.SINGLE.toUpperCase()) && + (value.toString().toUpperCase().includes(damageLocationsSelected.DRIVER.toUpperCase()) || value.toString().toUpperCase().includes(damageLocationsSelected.PASSENGER.toUpperCase()))) { return false; @@ -145,7 +145,7 @@ export default ({ } }, isWindshieldDamageLocation() { - return this.selectedDamageLocations.some(selectedDamages => + return this.selectedDamageLocations.some(selectedDamages => { return Boolean(selectedDamages.toUpperCase() === "WINDSHIELD"); }); @@ -193,4 +193,4 @@ export default ({ alert, }, }) - \ No newline at end of file + diff --git a/src/layouts/vehicle-make/vehicle-make.vue b/src/layouts/vehicle-make/vehicle-make.vue index 9e75d7036..aecd90a6f 100644 --- a/src/layouts/vehicle-make/vehicle-make.vue +++ b/src/layouts/vehicle-make/vehicle-make.vue @@ -88,6 +88,10 @@ export default { store.commit(storeMutations.UPDATE_STYLE, null); store.commit(storeMutations.UPDATE_CAR_ID, null); store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null); + store.commit(storeMutations.UPDATE_VEHICLE_VIN, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null); // Invokes store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); diff --git a/src/layouts/vehicle-model/vehicle-model.vue b/src/layouts/vehicle-model/vehicle-model.vue index 66516a729..c661c824e 100644 --- a/src/layouts/vehicle-model/vehicle-model.vue +++ b/src/layouts/vehicle-model/vehicle-model.vue @@ -88,6 +88,10 @@ export default { store.commit(storeMutations.UPDATE_STYLE, null); store.commit(storeMutations.UPDATE_CAR_ID, null); store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null); + store.commit(storeMutations.UPDATE_VEHICLE_VIN, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null); // Invokes store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue index 4f756b600..c7589d32d 100644 --- a/src/layouts/vehicle-style/vehicle-style.vue +++ b/src/layouts/vehicle-style/vehicle-style.vue @@ -101,6 +101,7 @@ export default { store.commit(storeMutations.UPDATE_IS_REPAIR, null); store.commit(storeMutations.UPDATE_NUMBER_OF_CHIPS, null); store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, []); + store.commit(storeMutations.UPDATE_VEHICLE_VIN, null); }, }, diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index ddca6b8bd..1041f82ae 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -107,8 +107,11 @@ export default { store.commit(storeMutations.UPDATE_STYLE, null); store.commit(storeMutations.UPDATE_CAR_ID, null); store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null); + store.commit(storeMutations.UPDATE_VEHICLE_VIN, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null); + store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null); - // Invokes store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); store.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES); diff --git a/src/layouts/vin-lookup/vin-information/vin-information.vue b/src/layouts/vin-lookup/vin-information/vin-information.vue index 3e5b67a91..91cee616f 100644 --- a/src/layouts/vin-lookup/vin-information/vin-information.vue +++ b/src/layouts/vin-lookup/vin-information/vin-information.vue @@ -41,6 +41,9 @@ export default { font-size: .875rem; color: $gray-600; } + li { + line-height: 26px; + } a { font-size: .875rem; } @@ -70,6 +73,7 @@ export default { overflow: hidden; opacity: 0; img { + max-width: 420px; width: 117%; height: auto; } diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index f6c3b5ecb..6c0f305b5 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -14,7 +14,7 @@ />
-
+
-
+
@@ -41,7 +42,7 @@ mask="#####" isRequired disableAutoFill - validationRules="zip-required" + validationRules="zip-required|zip-format" />
@@ -54,34 +55,35 @@ isRequired disableAutoFill validationRules="email-address-required|email-address-format" + semiAggressiveValidation />
0, }; }, + mounted() { + this.attachCustomEvents(); + }, + watch: { + vin() { + this.vinNotFound = false; + this.$refs.funnelFooter.updateButtonText( + this.getCmsContent("FunnelFooterWidget", "ForwardButtonText") + ); + } + }, computed: { perfectMatchNewVinAlert() { const isVinPerfectMatch = this.vinPopulatedOnPageLoad && this.vin === this.getVinFromStore(); - if (isVinPerfectMatch) { - this.isCarIdDifferent = false; - } + this.updateIsCarIdDifferent(isVinPerfectMatch); return isVinPerfectMatch; }, MatchedDifferentVehicleAlertHeader(){ @@ -236,7 +238,7 @@ export default { getIsWindshieldOnly()) }, isVinFieldReadOnly(){ - return this.$store.getters.payment.insuranceCoverage.isVerified; + return this.$store.getters.payment.insuranceCoverage.isVerified || getFunnelCookie().HasDelayedClaimRegistration; }, }, methods: { @@ -259,16 +261,21 @@ export default { getZipFromStore(){ return store.getters.order.serviceLocation.zipCode; }, - attachCustomEvents() { + attachCustomEvents() { this.prependActionToMethod(this, this.forwardButtonAction, () => { this.pushEventToGA( this.$route.query[this.queryStrings.FMG_PAGE], this.GaActions.SUBMITTED, - this.GaLabels.VINLOOKUP, + this.GaLabels.VIN_LOOKUP, true ); }); }, + updateIsCarIdDifferent(isVinPerfectMatch){ + if (isVinPerfectMatch) { + this.isCarIdDifferent = false; + } + }, backButtonAction() { if (store.getters.vehicle.vin) { this.$router.navigate(this.navigationScenarios.CLICKED_BACK_WITH_VIN, this.$route); @@ -307,7 +314,7 @@ export default { this.isCarIdDifferent = true; return; } - this.updateStore(vehicleLookupResponse.data); + this.updateStore(vehicleLookupResponse.data, zipValidationResponse.data); this.navigateForward(); }, navigateForward(){ @@ -331,7 +338,7 @@ export default { { vin } ); }, - updateStore(carInfo) { + updateStore(carInfo, zipInfo) { if(this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle){ store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); } @@ -346,6 +353,7 @@ export default { store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, carInfo.imageVifNumber); store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, carInfo.imageVifNumber); store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.zip); + store.commit(storeMutations.UPDATE_SERVICE_LOCATION_STATE, zipInfo.state); store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email); }, }, diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index d13e1b222..ca5a24a3e 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -9,12 +9,18 @@ import baseMixin from "@/mixins/base-mixin"; export default { methods: { logPageView(pageEvent) { + // if the user does not have a session id from the content site, do not log. + const sid = getSessionIdValue(); + if (sid === '00000000-0000-0000-0000-000000000000' || sid == null) { + return; + } + const currentPageName = getPageNameByQueryString(); var payload = { userId: getDeviceIdValue(), sessionKey: getSessionKeyValue(), pageName: currentPageName, - sessionId: getSessionIdValue(), + sessionId: sid, action: '', event: pageEvent, shouldUseSessionId: true, @@ -24,12 +30,18 @@ export default { }, logCustomEvent(category, action, label, value) { + // if the user does not have a session id from the content site, do not log. + const sid = getSessionIdValue(); + if (sid === '00000000-0000-0000-0000-000000000000' || sid == null) { + return; + } + const currentPageName = getPageNameByQueryString(); var payload = { userId: getDeviceIdValue(), sessionKey: getSessionKeyValue(), pageName: currentPageName, - sessionId: getSessionIdValue(), + sessionId: sid, category: category, action: action, label: label, @@ -97,8 +109,9 @@ export default { }, prependActionToMethod(object, method, actionToPrepend) { - const baseMethod = object[method.name]; - object[method.name] = function () { + const baseMethodName = method.name.startsWith('bound ') ? method.name.substring(6) : method.name ; + const baseMethod = object[baseMethodName]; + object[baseMethodName] = function () { actionToPrepend.apply(this, arguments); return baseMethod.apply(object, arguments); }; diff --git a/src/mixins/analytics-mixin.spec.js b/src/mixins/analytics-mixin.spec.js index e63778466..db773da56 100644 --- a/src/mixins/analytics-mixin.spec.js +++ b/src/mixins/analytics-mixin.spec.js @@ -1,5 +1,5 @@ import analyticsMixin from "@/mixins/analytics-mixin"; -import { setupMocksForJsFiles } from "@/helpers/unit-test-helper.js"; +import { setupMocksForJsFiles, setupCookies } from "@/helpers/unit-test-helper.js"; import { storeActions } from "@/constants/store-actions"; describe("analyticsMixin.js", () => { @@ -14,6 +14,12 @@ describe("analyticsMixin.js", () => { } const mocks = setupMocksForJsFiles(mockData); + const testCookieValue = { + sid: '10000000-0000-0000-0000-000000000001' + } + + setupCookies({ funnelCookieValue: JSON.stringify(testCookieValue) }); + analyticsMixin.methods.logPageView(type, payload); expect(mocks.baseMixin.methods.dispatchStoreAction).toBeCalled(); @@ -107,4 +113,17 @@ describe("analyticsMixin.js", () => { }]); }); + + test("Obj is not null after action prepended", () => { + //Arrange + const obj = {baseMethodName:"testMethodName", data:"testData"}; + const method = {name:"testMethodName", data:"testData" } + const action = "testAction"; + + //Act + analyticsMixin.methods.prependActionToMethod(obj, method, action); + + //Assert + expect(obj!=null); + }); }); \ No newline at end of file diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js index d8df53281..d0474d67b 100644 --- a/src/mixins/base-mixin.js +++ b/src/mixins/base-mixin.js @@ -42,6 +42,10 @@ export default { el && el.focus(); } }, + getFooterInfoBoxHeight() { + const footerInfoBox = document.querySelector(".footer #infoBox"); + return footerInfoBox ? footerInfoBox.offsetHeight : 0; + } }, computed: { storeActions() { diff --git a/src/router/index.js b/src/router/index.js index f11bd4228..c8d614d48 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -21,6 +21,7 @@ import analyticsMixin from "@/mixins/analytics-mixin"; // Components import ComponentTest from "@/layouts/component-test/component-test.vue"; import FormTest from "@/layouts/form-test/form-test.vue"; +import Modal from "@/common-components/loading-modal/loading-modal.vue"; const routes = [ @@ -34,6 +35,11 @@ const routes = [ name: "FormTest", component: FormTest, }, + { + path: "/loading-modal", // This is a temporary route for testing. + name: "Modal", + component: Modal, + }, { path: "/", name: "root", @@ -126,7 +132,7 @@ const router = createRouter({ router.afterEach(async (to, from) => { // Push page view to GA analyticsMixin.methods.pushPageViewToGA(to.query[queryStrings.FMG_PAGE]); - + baseMixin.methods.dispatchStoreAction(storeActions.GET_EXPERIMENTS_BY_USER, { userId: getDeviceIdValue() }) .then( (response) => { analyticsMixin.methods.pushExperimentsToDataLayer(response.data); @@ -214,13 +220,6 @@ function navigateToUrl(url, optionalQuery = {}) { externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]); } - ///////////////////////////////////////////////////// - // TEMP CODE FOR TESTING WITH SPECIFIC EXPERIMENTS // - ///////////////////////////////////////////////////// - if (externalUrl.search.indexOf("corid=") != -1) - externalUrl.search = externalUrl.search + '&experiments=CollectEmailOnQuote=CollectEmailOnQuote_V1=YesCollectEmail_TEST1=true,RemoveServiceAreaPage=ServAreaRemoval_V7=ServAreaNoRemove_V7_TEST=true,VINeducationV2=VINeducation_V2=NoShowVINmodalV2_CONTROL=true,ServicePackages=ServicePackages_V1=NoShowPackages_CONTROL=true,PhotoUploadRedesign=PhotoUploadRedesign_V1=CurrentPhotoUpload_CONTROL=true,ScheduleDetailsServiceType=ScheduleBeforeServiceType_V1=ServTypeThenSched_CONTROL=true'; - ///////////// END TEMP CODE ///////////////////////// - window.location.assign(externalUrl); } @@ -278,4 +277,4 @@ function resetDependentState(component) { return component.default.methods.resetDependentState(); } -export default router; \ No newline at end of file +export default router; diff --git a/src/store/index.js b/src/store/index.js index 69f6c2ba0..814ca2d5b 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -153,6 +153,9 @@ export const mutations = { updateServiceLocationZipCode(state, serviceLocationZip){ state.order.serviceLocation.zipCode = serviceLocationZip; }, + updateServiceLocationState(state, serviceLocationState){ + state.order.serviceLocation.state = serviceLocationState; + }, updateRegistrationFirstName(state, firstName){ state.order.vehicle.registration.firstName = firstName; }, @@ -190,6 +193,10 @@ export const mutations = { state.order.vehicle.style = null; state.order.vehicle.carId = null; state.order.vehicle.category = null; + state.order.vehicle.vin = null; + state.order.vehicle.imageUrl = null; + state.order.vehicle.imageVifNumber = null; + state.order.vehicle.imageColor = null; }, resetDamageState(state) { state.order.damage.isRepair = null; @@ -566,9 +573,9 @@ export const actions = { state: order.serviceLocation.state, zipCode: order.serviceLocation.zipCode }, - referralNumber: order.referralNumber, + referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place referralDate: order.referralDate, - accountNumber: order.accountNumber + accountNumber: order.accountNumber?.toString() }, }); }, @@ -578,10 +585,10 @@ export const actions = { method: endpoints.LoadOrder.method, endpoint: endpoints.LoadOrder.url, payload: { - referralNumber: referralNumber, + referralNumber: referralNumber?.toString(), referralDate: referralDate, referralCorrelationId: referralCorrelationId, - accountNumber: accountNumber + accountNumber: accountNumber?.toString() }, }).then((response) => { context.commit(storeMutations.RESET_STATE); diff --git a/src/styles/common-animations.scss b/src/styles/common-animations.scss index e247f3ded..c03c267ab 100644 --- a/src/styles/common-animations.scss +++ b/src/styles/common-animations.scss @@ -12,11 +12,11 @@ } .route-fade-enter-active .fade-on-route-transition { - transition: opacity 0.8s ease; + transition: opacity 0.2s ease-out; //This duration should be kept in sync with the app.vue element attribute } .route-fade-leave-active .fade-on-route-transition { - transition: opacity 0.3s ease; + transition: opacity 0.2s ease-in; //This duration should be kept in sync with the app.vue element attribute } .route-fade-enter-from .fade-on-route-transition, diff --git a/src/styles/common-error-styles.scss b/src/styles/common-error-styles.scss index 369c39a0e..95985f7c4 100644 --- a/src/styles/common-error-styles.scss +++ b/src/styles/common-error-styles.scss @@ -1,8 +1,9 @@ html { .has-error { &.list-button, - &.list-card, + &.list-card, &.list-card.list-button { + border: none; color: $red; input[type=checkbox]:focus + label, input[type=radio]:focus + label { @@ -13,15 +14,16 @@ html { } &:hover { box-shadow: 0px 0px 0px 4px $red-200; - border-radius: 10px; + border-radius: .5rem; } label { - border: 1px solid $red; + border: 1px solid $red; + border-radius: .5rem; } label:hover { box-shadow: 0px 0px 0px 4px $red-200; border-radius: 10px; - border: 1px solid $red; + border: 1px solid $red; } } &.list-button-horizontal { @@ -51,12 +53,21 @@ html { } &.textbox-question, &.dropdown-question { + input:hover { + box-shadow: 0px 0px 0px 4px $red-200; + border-radius: .5rem; + border: 1px solid $red; + } + input:focus { + box-shadow: 0 0 0 2.5px $red; + } p { color: $red; } input, select { - border: 1px solid $red; + border: 1px solid transparent; + box-shadow: 0 0 0 1px $red; &:focus { border: 1px solid transparent; } @@ -77,12 +88,14 @@ html { border: 1px solid $gray-500; input:not(:focus) { + label { + border: none; box-shadow: 0 0 0 1px $gray-500; border-radius: .5rem; } } input:checked:focus { + label { + border: none; box-shadow: 0 0 0 2.5px $blue; border-radius: .5rem; } @@ -114,8 +127,6 @@ html { color: $red; font-size: .875rem; font-weight: 500; - height: 1.5rem; - margin-top: .25rem !important; } .form-test-invalid { @@ -129,7 +140,6 @@ html { &.btn.btn-primary:hover, &.btn.btn-primary:focus, &.btn.btn-primary:focus-visible { - color: $gray !important; background: $gray-200; box-shadow: none; } diff --git a/src/ux-components/alert/alert.spec.js b/src/ux-components/alert/alert.spec.js index 6f4bb9822..59becf922 100644 --- a/src/ux-components/alert/alert.spec.js +++ b/src/ux-components/alert/alert.spec.js @@ -66,6 +66,7 @@ describe("alert.vue", () => { const mockMixin = { methods: { - getCmsContent: jest.fn() + getCmsContent: jest.fn(), + getFooterInfoBoxHeight: jest.fn(()=> 80), } } \ No newline at end of file diff --git a/src/ux-components/alert/alert.vue b/src/ux-components/alert/alert.vue index 8170a69a6..5c0d7a270 100644 --- a/src/ux-components/alert/alert.vue +++ b/src/ux-components/alert/alert.vue @@ -5,15 +5,17 @@ :class="[isDismissible ? 'alert-dismissible' : '', this.alertClass]" >

{{ alertHeadline }}

-

- -

-

+