Merge pull request #2482 from Safelite/rlsmerge/2025.05.08-to-develop
Rlsmerge/2025.05.08 to develop
This commit is contained in:
commit
5bdf91117c
28 changed files with 2980 additions and 3522 deletions
|
|
@ -18,9 +18,11 @@ pr:
|
||||||
resources:
|
resources:
|
||||||
containers:
|
containers:
|
||||||
- container: node
|
- container: node
|
||||||
image: packagerepository.sagaws.net:8082/safelite/node-build:18
|
image: ghcr.io/safelite/node-build:18
|
||||||
|
endpoint: GitHub Docker
|
||||||
- container: awscli
|
- container: awscli
|
||||||
image: packagerepository.sagaws.net:8082/safelite/awscli2-build:3.9
|
image: ghcr.io/safelite/awscli2-build:3.9
|
||||||
|
endpoint: GitHub Docker
|
||||||
- container: prettier-node
|
- container: prettier-node
|
||||||
image: ghcr.io/safelite/prettier-node-build:23
|
image: ghcr.io/safelite/prettier-node-build:23
|
||||||
endpoint: GitHub Docker
|
endpoint: GitHub Docker
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ module.exports = {
|
||||||
coverageReporters: ["html", "text", "jest-junit", "cobertura"],
|
coverageReporters: ["html", "text", "jest-junit", "cobertura"],
|
||||||
testResultsProcessor: "jest-junit",
|
testResultsProcessor: "jest-junit",
|
||||||
preset: "@vue/cli-plugin-unit-jest",
|
preset: "@vue/cli-plugin-unit-jest",
|
||||||
transform: { "^.+\\.vue$": "@vue/vue3-jest" },
|
transform: { "^.+\\.vue$": "@vue/vue3-jest",
|
||||||
transformIgnorePatterns: [
|
"^.+\\.mjs$": "babel-jest",
|
||||||
'/node_modules/(?!.*\\.mjs$)',
|
},
|
||||||
],
|
transformIgnorePatterns: ["'/node_modules/(?!vee-validate)"],
|
||||||
moduleFileExtensions: ["js", "vue"],
|
moduleFileExtensions: ["js", "vue"],
|
||||||
modulePathIgnorePatterns: ["vin-lookup"],
|
modulePathIgnorePatterns: ["vin-lookup"],
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
|
|
|
||||||
5773
package-lock.json
generated
5773
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -853,7 +853,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.calendar-grid-container {
|
.calendar-grid-container {
|
||||||
margin: 0 auto 2rem auto;
|
margin: 0 auto 1rem auto;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition:
|
transition:
|
||||||
|
|
@ -1075,12 +1075,16 @@ export default {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: $black;
|
background-color: $black;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 28px;
|
top: 1.875rem;
|
||||||
}
|
}
|
||||||
.first-day {
|
.first-day {
|
||||||
color: $blue;
|
color: $blue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
input[type="radio"]:checked + label:after {
|
||||||
|
background-color: $black;
|
||||||
|
top: 2rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1206,6 +1210,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
|
color: $gray-500;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -1228,10 +1233,11 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.current-day {
|
&.current-day {
|
||||||
label:after {
|
label {
|
||||||
margin-top: -0.25rem;
|
font-weight: 600;
|
||||||
position: relative;
|
font-family: "AvertaSemibold";
|
||||||
top: 0.5rem;
|
color: $black;
|
||||||
|
font-size-adjust: 0.5; // needed for Averta fonts baseline alignment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1242,6 +1248,7 @@ export default {
|
||||||
color: $black;
|
color: $black;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-family: "AvertaSemibold";
|
font-family: "AvertaSemibold";
|
||||||
|
font-size-adjust: 0.5; // needed for Averta fonts baseline alignment
|
||||||
|
|
||||||
&.price {
|
&.price {
|
||||||
font-family: "AvertaRegular";
|
font-family: "AvertaRegular";
|
||||||
|
|
@ -1274,7 +1281,6 @@ export default {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 0 0.5rem;
|
gap: 0 0.5rem;
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
flex: 0 0 calc(50% - 0.25rem);
|
flex: 0 0 calc(50% - 0.25rem);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
The code below is generated from salesforce but modified in the following ways:
|
||||||
|
* Only the javascript inside the second <script> tag in the provided salesforce code is copy pasted
|
||||||
|
* CSS is not copied in
|
||||||
|
* First <script> tag loading in the file from the CDN is not copied in
|
||||||
|
* The only custom code added here is `let embedded_svc = window.embedded_svc` in the first line of the `initESW` function
|
||||||
|
and the wrapper exported function `initializeSalesforceWebChatForDev`
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function initializeSalesforceWebchatForDev() {
|
||||||
|
var initESW = function (gslbBaseURL) {
|
||||||
|
let embedded_svc = window.embedded_svc;
|
||||||
|
embedded_svc.settings.displayHelpButton = true; //Or false
|
||||||
|
embedded_svc.settings.language = ""; //For example, enter 'en' or 'en-US'
|
||||||
|
|
||||||
|
//embedded_svc.settings.defaultMinimizedText = '...'; //(Defaults to Chat with an Expert)
|
||||||
|
//embedded_svc.settings.disabledMinimizedText = '...'; //(Defaults to Agent Offline)
|
||||||
|
|
||||||
|
//embedded_svc.settings.loadingText = ''; //(Defaults to Loading)
|
||||||
|
//embedded_svc.settings.storageDomain = 'yourdomain.com'; //(Sets the domain for your deployment so that visitors can navigate subdomains during a chat session)
|
||||||
|
|
||||||
|
// Settings for Chat
|
||||||
|
//embedded_svc.settings.directToButtonRouting = function(prechatFormData) {
|
||||||
|
// Dynamically changes the button ID based on what the visitor enters in the pre-chat form.
|
||||||
|
// Returns a valid button ID.
|
||||||
|
//};
|
||||||
|
//embedded_svc.settings.prepopulatedPrechatFields = {}; //Sets the auto-population of pre-chat form fields
|
||||||
|
//embedded_svc.settings.fallbackRouting = []; //An array of button IDs, user IDs, or userId_buttonId
|
||||||
|
//embedded_svc.settings.offlineSupportMinimizedText = '...'; //(Defaults to Contact Us)
|
||||||
|
|
||||||
|
embedded_svc.settings.enabledFeatures = ["LiveAgent"];
|
||||||
|
embedded_svc.settings.entryFeature = "LiveAgent";
|
||||||
|
|
||||||
|
embedded_svc.init(
|
||||||
|
"https://safelite2--dev.sandbox.my.salesforce.com",
|
||||||
|
"https://safelite2--dev.sandbox.my.salesforce-sites.com/chat",
|
||||||
|
gslbBaseURL,
|
||||||
|
"00D6s0000008r6A",
|
||||||
|
"Sales_Central_Snap_in",
|
||||||
|
{
|
||||||
|
baseLiveAgentContentURL:
|
||||||
|
"https://c.la12s-core1.sfdc-8tgtt5.salesforceliveagent.com/content",
|
||||||
|
deploymentId: "572Wr0000017xKX",
|
||||||
|
buttonId: "573Wr000000CpgH",
|
||||||
|
baseLiveAgentURL: "https://d.la12s-core1.sfdc-8tgtt5.salesforceliveagent.com/chat",
|
||||||
|
eswLiveAgentDevName:
|
||||||
|
"EmbeddedServiceLiveAgent_Parent04IWr000003yKq9MAE_1961681659a",
|
||||||
|
isOfflineSupportEnabled: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.embedded_svc) {
|
||||||
|
var s = document.createElement("script");
|
||||||
|
s.setAttribute(
|
||||||
|
"src",
|
||||||
|
"https://safelite2--dev.sandbox.my.salesforce.com/embeddedservice/5.0/esw.min.js"
|
||||||
|
);
|
||||||
|
s.onload = function () {
|
||||||
|
initESW(null);
|
||||||
|
};
|
||||||
|
document.body.appendChild(s);
|
||||||
|
} else {
|
||||||
|
initESW("https://service.force.com");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
The code below is generated from salesforce but modified in the following ways:
|
||||||
|
* Only the javascript inside the second <script> tag in the provided salesforce code is copy pasted
|
||||||
|
* CSS is not copied in
|
||||||
|
* First <script> tag loading in the file from the CDN is not copied in
|
||||||
|
* The only custom code added here is `let embedded_svc = window.embedded_svc` in the first line of the `initESW` function
|
||||||
|
and the wrapper exported function `initializeSalesforceWebChatForProd`
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function initializeSalesforceWebchatForProd(embedded_svc) {
|
||||||
|
var initESW = function (gslbBaseURL) {
|
||||||
|
let embedded_svc = window.embedded_svc;
|
||||||
|
embedded_svc.settings.displayHelpButton = true; //Or false
|
||||||
|
embedded_svc.settings.language = ""; //For example, enter 'en' or 'en-US'
|
||||||
|
|
||||||
|
//embedded_svc.settings.defaultMinimizedText = '...'; //(Defaults to Chat with an Expert)
|
||||||
|
//embedded_svc.settings.disabledMinimizedText = '...'; //(Defaults to Agent Offline)
|
||||||
|
|
||||||
|
//embedded_svc.settings.loadingText = ''; //(Defaults to Loading)
|
||||||
|
//embedded_svc.settings.storageDomain = 'yourdomain.com'; //(Sets the domain for your deployment so that visitors can navigate subdomains during a chat session)
|
||||||
|
|
||||||
|
// Settings for Chat
|
||||||
|
//embedded_svc.settings.directToButtonRouting = function(prechatFormData) {
|
||||||
|
// Dynamically changes the button ID based on what the visitor enters in the pre-chat form.
|
||||||
|
// Returns a valid button ID.
|
||||||
|
//};
|
||||||
|
//embedded_svc.settings.prepopulatedPrechatFields = {}; //Sets the auto-population of pre-chat form fields
|
||||||
|
//embedded_svc.settings.fallbackRouting = []; //An array of button IDs, user IDs, or userId_buttonId
|
||||||
|
//embedded_svc.settings.offlineSupportMinimizedText = '...'; //(Defaults to Contact Us)
|
||||||
|
|
||||||
|
embedded_svc.settings.enabledFeatures = ["LiveAgent"];
|
||||||
|
embedded_svc.settings.entryFeature = "LiveAgent";
|
||||||
|
|
||||||
|
embedded_svc.init(
|
||||||
|
"https://safelite2.my.salesforce.com",
|
||||||
|
"https://safelite2.my.salesforce-sites.com/chat",
|
||||||
|
gslbBaseURL,
|
||||||
|
"00D3t000004nvsT",
|
||||||
|
"Sales_Central_Snap_in",
|
||||||
|
{
|
||||||
|
baseLiveAgentContentURL:
|
||||||
|
"https://c.la13-core2.sfdc-lywfpd.salesforceliveagent.com/content",
|
||||||
|
deploymentId: "5723t0000008wWB",
|
||||||
|
buttonId: "5733t000000D90z",
|
||||||
|
baseLiveAgentURL: "https://d.la13-core2.sfdc-lywfpd.salesforceliveagent.com/chat",
|
||||||
|
eswLiveAgentDevName:
|
||||||
|
"EmbeddedServiceLiveAgent_Parent04I3t000000Cq0SEAS_188de1871ea",
|
||||||
|
isOfflineSupportEnabled: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.embedded_svc) {
|
||||||
|
var s = document.createElement("script");
|
||||||
|
s.setAttribute("src", "https://safelite2.my.salesforce.com/embeddedservice/5.0/esw.min.js");
|
||||||
|
s.onload = function () {
|
||||||
|
initESW(null);
|
||||||
|
};
|
||||||
|
document.body.appendChild(s);
|
||||||
|
} else {
|
||||||
|
initESW("https://service.force.com");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
The code below is generated from salesforce but modified in the following ways:
|
||||||
|
* Only the javascript inside the second <script> tag in the provided salesforce code is copy pasted
|
||||||
|
* CSS is not copied in
|
||||||
|
* First <script> tag loading in the file from the CDN is not copied in
|
||||||
|
* The only custom code added here is `let embedded_svc = window.embedded_svc` in the first line of the `initESW` function
|
||||||
|
and the wrapper exported function `initializeSalesforceWebChatForQa`
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function initializeSalesforceWebchatForQa() {
|
||||||
|
var initESW = function (gslbBaseURL) {
|
||||||
|
let embedded_svc = window.embedded_svc;
|
||||||
|
|
||||||
|
embedded_svc.settings.displayHelpButton = true; //Or false
|
||||||
|
embedded_svc.settings.language = ""; //For example, enter 'en' or 'en-US'
|
||||||
|
|
||||||
|
//embedded_svc.settings.defaultMinimizedText = '...'; //(Defaults to Chat with an Expert)
|
||||||
|
//embedded_svc.settings.disabledMinimizedText = '...'; //(Defaults to Agent Offline)
|
||||||
|
|
||||||
|
//embedded_svc.settings.loadingText = ''; //(Defaults to Loading)
|
||||||
|
//embedded_svc.settings.storageDomain = 'yourdomain.com'; //(Sets the domain for your deployment so that visitors can navigate subdomains during a chat session)
|
||||||
|
|
||||||
|
// Settings for Chat
|
||||||
|
//embedded_svc.settings.directToButtonRouting = function(prechatFormData) {
|
||||||
|
// Dynamically changes the button ID based on what the visitor enters in the pre-chat form.
|
||||||
|
// Returns a valid button ID.
|
||||||
|
//};
|
||||||
|
//embedded_svc.settings.prepopulatedPrechatFields = {}; //Sets the auto-population of pre-chat form fields
|
||||||
|
//embedded_svc.settings.fallbackRouting = []; //An array of button IDs, user IDs, or userId_buttonId
|
||||||
|
//embedded_svc.settings.offlineSupportMinimizedText = '...'; //(Defaults to Contact Us)
|
||||||
|
|
||||||
|
embedded_svc.settings.enabledFeatures = ["LiveAgent"];
|
||||||
|
embedded_svc.settings.entryFeature = "LiveAgent";
|
||||||
|
|
||||||
|
embedded_svc.init(
|
||||||
|
"https://safelite2--safeliteua.sandbox.my.salesforce.com",
|
||||||
|
"https://safelite2--safeliteua.sandbox.my.salesforce-sites.com/chat",
|
||||||
|
gslbBaseURL,
|
||||||
|
"00DDJ000000HRqO",
|
||||||
|
"Sales_Central_Snap_in",
|
||||||
|
{
|
||||||
|
baseLiveAgentContentURL:
|
||||||
|
"https://c.la12s-core1.sfdc-8tgtt5.salesforceliveagent.com/content",
|
||||||
|
deploymentId: "572DJ00000001j3",
|
||||||
|
buttonId: "573DJ00000001ur",
|
||||||
|
baseLiveAgentURL: "https://d.la12s-core1.sfdc-8tgtt5.salesforceliveagent.com/chat",
|
||||||
|
eswLiveAgentDevName:
|
||||||
|
"EmbeddedServiceLiveAgent_Parent04IDJ0000008OZk2AM_1883057c9a6",
|
||||||
|
isOfflineSupportEnabled: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.embedded_svc) {
|
||||||
|
var s = document.createElement("script");
|
||||||
|
s.setAttribute(
|
||||||
|
"src",
|
||||||
|
"https://safelite2--safeliteua.sandbox.my.salesforce.com/embeddedservice/5.0/esw.min.js"
|
||||||
|
);
|
||||||
|
s.onload = function () {
|
||||||
|
initESW(null);
|
||||||
|
};
|
||||||
|
document.body.appendChild(s);
|
||||||
|
} else {
|
||||||
|
initESW("https://service.force.com");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import * as salesforceWebchatHelperdev from "./salesforce-helper-dev";
|
||||||
|
import * as salesforceWebchatHelperqa from "./salesforce-helper-qa";
|
||||||
|
import * as salesforceWebchatHelperprod from "./salesforce-helper-prod";
|
||||||
|
|
||||||
|
const mockEmbeddedSvc = {
|
||||||
|
settings: {},
|
||||||
|
init: jest.fn(),
|
||||||
|
testFlag: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("Salesforce Webchat Helper Tests", () => {
|
||||||
|
describe("Files and exposed methods exist", () => {
|
||||||
|
it("exposes initialization methods", () => {
|
||||||
|
expect(typeof salesforceWebchatHelperdev.initializeSalesforceWebchatForDev).toBe(
|
||||||
|
"function"
|
||||||
|
);
|
||||||
|
expect(typeof salesforceWebchatHelperqa.initializeSalesforceWebchatForQa).toBe(
|
||||||
|
"function"
|
||||||
|
);
|
||||||
|
expect(typeof salesforceWebchatHelperprod.initializeSalesforceWebchatForProd).toBe(
|
||||||
|
"function"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
describe("Custom code added correctly", () => {
|
||||||
|
it("defines a local variable 'embedded_svc' in the initESW method", () => {
|
||||||
|
mockEmbeddedSvc.testFlag = "dev";
|
||||||
|
window.embedded_svc = mockEmbeddedSvc;
|
||||||
|
salesforceWebchatHelperdev.initializeSalesforceWebchatForDev();
|
||||||
|
expect(embedded_svc.testFlag).toBe("dev");
|
||||||
|
|
||||||
|
mockEmbeddedSvc.testFlag = "qa";
|
||||||
|
window.embedded_svc = mockEmbeddedSvc;
|
||||||
|
salesforceWebchatHelperqa.initializeSalesforceWebchatForQa();
|
||||||
|
expect(embedded_svc.testFlag).toBe("qa");
|
||||||
|
|
||||||
|
mockEmbeddedSvc.testFlag = "prod";
|
||||||
|
window.embedded_svc = mockEmbeddedSvc;
|
||||||
|
salesforceWebchatHelperprod.initializeSalesforceWebchatForProd();
|
||||||
|
expect(embedded_svc.testFlag).toBe("prod");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import salesforceWebchat from "./salesforce-webchat.vue";
|
||||||
|
import * as devHelper from "./salesforce-helper-dev";
|
||||||
|
import * as qaHelper from "./salesforce-helper-qa";
|
||||||
|
import * as prodHelper from "./salesforce-helper-prod";
|
||||||
|
import { applicationConfig } from "../../constants/application-config";
|
||||||
|
|
||||||
|
describe("salesforceWebchat.vue", () => {
|
||||||
|
it("renders correctly", () => {
|
||||||
|
const wrapper = shallowMount(salesforceWebchat);
|
||||||
|
expect(wrapper.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("has the correct default data", () => {
|
||||||
|
const wrapper = shallowMount(salesforceWebchat);
|
||||||
|
expect(wrapper.vm.$data).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("has the correct default props", () => {
|
||||||
|
const wrapper = shallowMount(salesforceWebchat);
|
||||||
|
expect(wrapper.props().hideSalesforceWebchatLaunchButton).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls the correct initialization function based on environment", () => {
|
||||||
|
applicationConfig.CURRENT_ENVIRONMENT = "Prod";
|
||||||
|
let wrapper = shallowMount(salesforceWebchat);
|
||||||
|
const mockProd = jest.spyOn(prodHelper, "initializeSalesforceWebchatForProd");
|
||||||
|
wrapper.vm.initializeSalesforceWebchat();
|
||||||
|
expect(mockProd).toHaveBeenCalled();
|
||||||
|
|
||||||
|
applicationConfig.CURRENT_ENVIRONMENT = "QA";
|
||||||
|
wrapper = shallowMount(salesforceWebchat);
|
||||||
|
const mockQa = jest.spyOn(qaHelper, "initializeSalesforceWebchatForQa");
|
||||||
|
wrapper.vm.initializeSalesforceWebchat();
|
||||||
|
expect(mockQa).toHaveBeenCalled();
|
||||||
|
|
||||||
|
applicationConfig.CURRENT_ENVIRONMENT = "Dev";
|
||||||
|
wrapper = shallowMount(salesforceWebchat);
|
||||||
|
const mockDev = jest.spyOn(devHelper, "initializeSalesforceWebchatForDev");
|
||||||
|
wrapper.vm.initializeSalesforceWebchat();
|
||||||
|
expect(mockDev).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<template>
|
||||||
|
<span class="salesforce-webchat"></span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Supporting files
|
||||||
|
import { initializeSalesforceWebchatForDev } from "./salesforce-helper-dev";
|
||||||
|
import { initializeSalesforceWebchatForQa } from "./salesforce-helper-qa";
|
||||||
|
import { initializeSalesforceWebchatForProd } from "./salesforce-helper-prod";
|
||||||
|
import { applicationConfig } from "@/constants/application-config";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "salesforceWebchat",
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
hideSalesforceWebchatLaunchButton: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// Load in script from salesforce CDN
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = "https://service.force.com/embeddedservice/5.0/esw.min.js";
|
||||||
|
script.onload = this.initializeSalesforceWebchat;
|
||||||
|
document.body.appendChild(script);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initializeSalesforceWebchat() {
|
||||||
|
switch (applicationConfig.CURRENT_ENVIRONMENT) {
|
||||||
|
case "Prod":
|
||||||
|
initializeSalesforceWebchatForProd();
|
||||||
|
break;
|
||||||
|
case "QA":
|
||||||
|
case "SysTest":
|
||||||
|
initializeSalesforceWebchatForQa();
|
||||||
|
break;
|
||||||
|
case "Dev":
|
||||||
|
case "Localhost":
|
||||||
|
initializeSalesforceWebchatForDev();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
components: {},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
.embeddedServiceHelpButton .helpButton .uiButton {
|
||||||
|
background-color: #167cac;
|
||||||
|
font-family: "Arial", sans-serif;
|
||||||
|
}
|
||||||
|
.embeddedServiceHelpButton .helpButton .uiButton:focus {
|
||||||
|
outline: 1px solid #167cac;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
<div
|
<div
|
||||||
class="funnel-header d-flex justify-content-center align-items-center flex-column"
|
class="funnel-header d-flex justify-content-center align-items-center flex-column"
|
||||||
v-if="imageSrc">
|
v-if="imageSrc">
|
||||||
|
<!-- HIDDEN FOR 05.08 <salesforceWebchat hideSalesforceWebchatLaunchButton />-->
|
||||||
<img class="logo-image img-fluid" :src="imageSrc" alt="Safelite logo" />
|
<img class="logo-image img-fluid" :src="imageSrc" alt="Safelite logo" />
|
||||||
<!-- // menu-modal temporarily not in use until the hamburger menu is re-implemented for use with the progress bar. See display: none below. -->
|
<!-- // menu-modal temporarily not in use until the hamburger menu is re-implemented for use with the progress bar. See display: none below. -->
|
||||||
<menuModal />
|
<menuModal />
|
||||||
|
|
@ -27,6 +28,7 @@ import alert from "@/ux-components/alert/alert";
|
||||||
import eventBus from "@/helpers/event-bus/event-bus";
|
import eventBus from "@/helpers/event-bus/event-bus";
|
||||||
import { globalEvents } from "@/constants/events";
|
import { globalEvents } from "@/constants/events";
|
||||||
import menuModal from "@/fmg-components/funnel-header/menu-modal/menu-modal";
|
import menuModal from "@/fmg-components/funnel-header/menu-modal/menu-modal";
|
||||||
|
import salesforceWebchat from "../../digital-components/salesforce-webchat/salesforce-webchat.vue";
|
||||||
import progressBar from "@/fmg-components/funnel-header/progress-bar/progress-bar";
|
import progressBar from "@/fmg-components/funnel-header/progress-bar/progress-bar";
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
|
@ -41,6 +43,10 @@ export default {
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
cmsWidgetName: String,
|
cmsWidgetName: String,
|
||||||
|
hideSalesforceWebchatLaunchButton: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
imageSrc() {
|
imageSrc() {
|
||||||
|
|
@ -64,6 +70,7 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
alert,
|
alert,
|
||||||
menuModal,
|
menuModal,
|
||||||
|
salesforceWebchat,
|
||||||
progressBar,
|
progressBar,
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -98,7 +105,7 @@ export default {
|
||||||
}
|
}
|
||||||
.funnel-header {
|
.funnel-header {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0.97rem 0;
|
padding-top: 0.97rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-image {
|
.logo-image {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
#progress-bar-container {
|
#progress-bar-container {
|
||||||
padding: 0.75rem 0;
|
padding-top: 0.75rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
progress {
|
progress {
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,23 @@ describe("address-lookup.vue", () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.findComponent({ ref: "alertVinNotFound" }).isVisible()).toBe(true);
|
expect(wrapper.findComponent({ ref: "alertVinNotFound" }).isVisible()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should hide the AlertNoService when displayNoServiceAlert is false", async () => {
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
isZipServiceable: true,
|
||||||
|
displayNoServiceAlert: false,
|
||||||
|
lookupVinbyAddressResponse: {
|
||||||
|
isStatePermissible: true,
|
||||||
|
vinVehicles: [], // Return no vehicles
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Ensure displayNoServiceAlert is false
|
||||||
|
await wrapper.setData({ displayNoServiceAlert: false });
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
// Check if the AlertNoService component is not rendered
|
||||||
|
const alertNoService = wrapper.findComponent({ ref: "AlertNoService" });
|
||||||
|
expect(alertNoService.exists()).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("navigation", () => {
|
describe("navigation", () => {
|
||||||
|
|
@ -741,6 +758,17 @@ function setupMocks({
|
||||||
wrapper.vm.setCmsContent = jest.fn();
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||||
|
const closestShops = {
|
||||||
|
data: {
|
||||||
|
providers: [
|
||||||
|
{ id: 1, name: "Shop 1" },
|
||||||
|
{ id: 2, name: "Shop 2" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapper.vm.findClosestApplicableShops = jest.fn().mockImplementation(() => {
|
||||||
|
return new Promise((resolve) => resolve(closestShops));
|
||||||
|
});
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,13 +81,20 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
<alert
|
||||||
|
ref="AlertNoService"
|
||||||
|
v-if="displayNoServiceAlert"
|
||||||
|
class="my-4"
|
||||||
|
cmsWidgetName="AlertNoServiceWidget"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isDisabled="!meta.valid"
|
:isDisabled="!meta.valid"
|
||||||
@ForwardClicked="forwardButtonAction"
|
@ForwardClicked="forwardButtonAction"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
:isForwardActionDisabled="!meta.valid" />
|
:isForwardActionDisabled="!meta.valid || displayNoServiceAlert" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -177,6 +184,7 @@ export default {
|
||||||
displayInvalidZipAlert: false,
|
displayInvalidZipAlert: false,
|
||||||
showServiceZipField: this.getServiceZipFromStore(),
|
showServiceZipField: this.getServiceZipFromStore(),
|
||||||
isZipServiceable: false,
|
isZipServiceable: false,
|
||||||
|
displayNoServiceAlert: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -293,6 +301,17 @@ export default {
|
||||||
return this.$refs.navbar.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
this.displayInvalidZipAlert = false;
|
this.displayInvalidZipAlert = false;
|
||||||
|
|
||||||
|
if (this.serviceZipCode != null && this.isHeavyTruck) {
|
||||||
|
const closestShops = await this.findClosestApplicableShops(
|
||||||
|
this.serviceZipCode,
|
||||||
|
this.carId
|
||||||
|
);
|
||||||
|
this.displayNoServiceAlert = !closestShops?.data?.providers?.length;
|
||||||
|
if (this.displayNoServiceAlert) {
|
||||||
|
return this.$refs.navbar.removeLoader();
|
||||||
|
}
|
||||||
|
}
|
||||||
const carsFound = resultMap.vinLookupResponse.vinVehicles;
|
const carsFound = resultMap.vinLookupResponse.vinVehicles;
|
||||||
|
|
||||||
// Handle cases for different amounts of VINS found for the address.
|
// Handle cases for different amounts of VINS found for the address.
|
||||||
|
|
@ -444,6 +463,7 @@ export default {
|
||||||
this.displayNonServiceableZipAlert = false;
|
this.displayNonServiceableZipAlert = false;
|
||||||
this.displayMatchedDifferentVehicleAlert = false;
|
this.displayMatchedDifferentVehicleAlert = false;
|
||||||
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
|
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
|
||||||
|
this.displayNoServiceAlert = false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -495,12 +515,13 @@ export default {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
// If they modify the service zip code, then hide the error message.
|
// If they modify the service zip code, then hide the error message.
|
||||||
this.displayNonServiceableZipAlert = false;
|
this.displayNonServiceableZipAlert = false;
|
||||||
|
this.displayNoServiceAlert = false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
showServiceZipField: {
|
showServiceZipField: {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
// If the Service Zip Code field is ever hidden, clear out it's value
|
// If the Service Zip Code field is ever hidden and not a heavy truck, clear out it's value
|
||||||
if (!newValue) {
|
if (!newValue && !this.isHeavyTruck) {
|
||||||
this.serviceZipCode = null;
|
this.serviceZipCode = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@
|
||||||
<div class="container-fluid pb-2">
|
<div class="container-fluid pb-2">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
<funnelHeader
|
||||||
|
cmsWidgetName="FunnelHeaderWidget"
|
||||||
|
ref="funnelHeader"
|
||||||
|
hideSalesforceWebchatLaunchButton />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
|
|
|
||||||
|
|
@ -620,6 +620,8 @@ function setupMocks({
|
||||||
validateZipResponse = { zipCodeCtu: null, isServiceable: false, isValid: true, state: null },
|
validateZipResponse = { zipCodeCtu: null, isServiceable: false, isValid: true, state: null },
|
||||||
//Values to set in the state store
|
//Values to set in the state store
|
||||||
carId = null,
|
carId = null,
|
||||||
|
isHeavyTruck = true,
|
||||||
|
displayNoServiceAlert = true,
|
||||||
serviceLocationZipCode = null,
|
serviceLocationZipCode = null,
|
||||||
registrationZipCode = null,
|
registrationZipCode = null,
|
||||||
licensePlate = null, //"TESTPLATE",
|
licensePlate = null, //"TESTPLATE",
|
||||||
|
|
@ -672,6 +674,8 @@ function setupMocks({
|
||||||
zipCode: registrationZipCode,
|
zipCode: registrationZipCode,
|
||||||
},
|
},
|
||||||
carId: carId,
|
carId: carId,
|
||||||
|
isBigTruck: isHeavyTruck,
|
||||||
|
canSafeliteService: true,
|
||||||
},
|
},
|
||||||
order: {
|
order: {
|
||||||
customer: {
|
customer: {
|
||||||
|
|
@ -716,5 +720,17 @@ function setupMocks({
|
||||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
|
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
|
||||||
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||||
|
const closestShops = {
|
||||||
|
data: {
|
||||||
|
providers: [
|
||||||
|
{ id: 1, name: "Shop 1" },
|
||||||
|
{ id: 2, name: "Shop 2" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapper.vm.findClosestApplicableShops = jest.fn().mockImplementation(() => {
|
||||||
|
return new Promise((resolve) => resolve(closestShops));
|
||||||
|
});
|
||||||
return { wrapper, apiPromise };
|
return { wrapper, apiPromise };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@
|
||||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||||
alertClass="alert-warning"
|
alertClass="alert-warning"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<alert
|
<alert
|
||||||
ref="AlertNoService"
|
ref="AlertNoService"
|
||||||
v-if="displayNoServiceAlert"
|
v-if="displayNoServiceAlert"
|
||||||
|
|
@ -87,9 +88,9 @@
|
||||||
<navbar
|
<navbar
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid || displayNoServiceAlert"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction || displayNoServiceAlert" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -177,6 +178,7 @@ export default {
|
||||||
displayInvalidZipAlert: false,
|
displayInvalidZipAlert: false,
|
||||||
showServiceZipField: this.getServiceZipFromStore(),
|
showServiceZipField: this.getServiceZipFromStore(),
|
||||||
isZipServiceable: false,
|
isZipServiceable: false,
|
||||||
|
displayNoServiceAlert: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -279,6 +281,17 @@ export default {
|
||||||
this.displayInvalidZipAlert = true;
|
this.displayInvalidZipAlert = true;
|
||||||
return this.$refs.navbar.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isHeavyTruck) {
|
||||||
|
const closestShops = await this.findClosestApplicableShops(
|
||||||
|
this.serviceZipCode,
|
||||||
|
this.carId
|
||||||
|
);
|
||||||
|
this.displayNoServiceAlert = !closestShops?.data?.providers?.length;
|
||||||
|
if (this.displayNoServiceAlert) {
|
||||||
|
return this.$refs.navbar.removeLoader();
|
||||||
|
}
|
||||||
|
}
|
||||||
// Check if the CarId has changed.
|
// Check if the CarId has changed.
|
||||||
this.isCarIdDifferent =
|
this.isCarIdDifferent =
|
||||||
vinLookup.data.vehicle.carId !== this.$store.getters.vehicle.carId;
|
vinLookup.data.vehicle.carId !== this.$store.getters.vehicle.carId;
|
||||||
|
|
@ -393,6 +406,7 @@ export default {
|
||||||
this.displayMatchedDifferentVehicleAlert = false;
|
this.displayMatchedDifferentVehicleAlert = false;
|
||||||
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
|
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
|
||||||
this.displayInvalidZipAlert = false;
|
this.displayInvalidZipAlert = false;
|
||||||
|
this.displayNoServiceAlert = false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -437,6 +451,7 @@ export default {
|
||||||
serviceZipCode() {
|
serviceZipCode() {
|
||||||
// If they modify the service zip code, then hide the error message.
|
// If they modify the service zip code, then hide the error message.
|
||||||
this.displayNonServiceableZipAlert = false;
|
this.displayNonServiceableZipAlert = false;
|
||||||
|
this.displayNoServiceAlert = false;
|
||||||
this.$refs.navbar.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,16 @@
|
||||||
<component :is="'script'" src="https://js.afterpay.com/afterpay-1.x.js" async></component>
|
<component :is="'script'" src="https://js.afterpay.com/afterpay-1.x.js" async></component>
|
||||||
<div class="my-4 alert-heading text-center">
|
<div class="my-4 alert-heading text-center">
|
||||||
<span v-html="afterpayHeaderCopy" />
|
<span v-html="afterpayHeaderCopy" />
|
||||||
|
|
||||||
<span class="afterpay-amount">{{ this.afterpayPrice }}</span>
|
<span class="afterpay-amount">{{ this.afterpayPrice }}</span>
|
||||||
<br />
|
<br />
|
||||||
<span class="alert-sub-heading" v-html="afterpayHeaderSubHeaderCopy" />
|
<span class="alert-sub-heading" v-html="afterpayHeaderSubHeaderCopy" />
|
||||||
|
<img :src="afterPayImageUrl" class="afterpay-image" />
|
||||||
<img :src="afterPayImageUrl" />
|
|
||||||
|
|
||||||
<a
|
<a
|
||||||
id="afterpay-learnmore"
|
id="afterpay-learnmore"
|
||||||
href="#"
|
href="#"
|
||||||
data-afterpay-modal="en_US-safelite"
|
data-afterpay-modal="en_US-safelite"
|
||||||
data-bind="click:afterpayLearnMore">
|
data-bind="click:afterpayLearnMore"
|
||||||
|
class="afterpay-learn-more">
|
||||||
<img :src="infoIcon" alt="Info Icon" class="info-icon" />
|
<img :src="infoIcon" alt="Info Icon" class="info-icon" />
|
||||||
</a>
|
</a>
|
||||||
<div class="after-pay">
|
<div class="after-pay">
|
||||||
|
|
@ -148,11 +146,12 @@ export default {
|
||||||
.alert {
|
.alert {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
|
||||||
&.alert-info {
|
&.alert-info {
|
||||||
.alert-heading {
|
.alert-heading {
|
||||||
color: #000000;
|
color: $black;
|
||||||
font-weight: 600;
|
font-weight: $font-weight-600;
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
|
|
@ -162,13 +161,15 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.afterpay-amount {
|
.afterpay-amount {
|
||||||
color: #0c7e47;
|
color: $green;
|
||||||
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
.alert-sub-heading {
|
.alert-sub-heading {
|
||||||
color: #4b4c4e;
|
color: $gray-1100;
|
||||||
font-weight: 400;
|
font-weight: $font-weight-normal;
|
||||||
}
|
}
|
||||||
.after-pay {
|
.after-pay {
|
||||||
|
margin-top: 1rem;
|
||||||
.after-pay-toggle {
|
.after-pay-toggle {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
|
@ -180,7 +181,7 @@ export default {
|
||||||
background-position: right center;
|
background-position: right center;
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 9px;
|
height: 0.5625rem;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
&.expanded:after {
|
&.expanded:after {
|
||||||
|
|
@ -194,8 +195,8 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.after-pay-toggle a {
|
.after-pay-toggle a {
|
||||||
font-weight: 600;
|
font-weight: $font-weight-600;
|
||||||
color: #0070d1;
|
color: $blue;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.after-pay-details {
|
.after-pay-details {
|
||||||
|
|
@ -211,6 +212,7 @@ export default {
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
gap: 0rem;
|
gap: 0rem;
|
||||||
}
|
}
|
||||||
|
|
@ -218,42 +220,52 @@ export default {
|
||||||
.payment-card {
|
.payment-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-radius: 6px;
|
border-radius: 0.375rem;
|
||||||
border: 0.25px #b3b4b5;
|
border: 0.25px $gray-1000;
|
||||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
background: linear-gradient(to bottom, $white 50%, $green-600 50%);
|
||||||
|
box-shadow: 0px 4px 8px -4px rgba(0, 0, 0, 0.15);
|
||||||
|
width: 4.375rem;
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
width: 5rem;
|
||||||
|
}
|
||||||
|
font-weight: $font-weight-700;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
.calendar-section {
|
.calendar-section {
|
||||||
background-color: #fff; /* White background for calendar area */
|
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
text-align: center;
|
gap: 0.125rem;
|
||||||
gap: 2px;
|
|
||||||
font-weight: 700;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
color: $black-100;
|
||||||
}
|
}
|
||||||
.payment-amount-section {
|
.payment-amount-section {
|
||||||
background-color: #e0f7e9; /* Light green background for payment area */
|
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
text-align: center;
|
}
|
||||||
font-weight: 700;
|
.afterpay-learn-more {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
}
|
||||||
|
.afterpay-image {
|
||||||
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.amount-due {
|
.amount-due {
|
||||||
color: #00723e; /* Green text */
|
color: $green-1000; /* Green text */
|
||||||
}
|
}
|
||||||
.legend {
|
.legend {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
color: $gray-1100;
|
||||||
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
.legend-item {
|
.legend-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 2px;
|
gap: 0.125rem;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.legend-item span {
|
.legend-item span {
|
||||||
font-weight: 400;
|
font-weight: $font-weight-normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@
|
||||||
v-model="selectedRouteCode"
|
v-model="selectedRouteCode"
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="time-slot-required" />
|
validationRules="time-slot-required" />
|
||||||
|
<div
|
||||||
|
class="supplemental-information"
|
||||||
|
v-if="supplementalInformationBlock"
|
||||||
|
v-html="supplementalInformationBlock" />
|
||||||
<div
|
<div
|
||||||
v-if="hasWaitListExperiment && displayWaitListFeature"
|
v-if="hasWaitListExperiment && displayWaitListFeature"
|
||||||
class="mt-5 bg-light rounded waitlist">
|
class="mt-5 bg-light rounded waitlist">
|
||||||
|
|
@ -36,23 +40,16 @@
|
||||||
v-model="waitListRequested"
|
v-model="waitListRequested"
|
||||||
@click="waitListChecked" />
|
@click="waitListChecked" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="waitListRequested" class="rounded waitlist-success" ref="waitlistSuccessMessage">
|
||||||
v-if="waitListRequested"
|
|
||||||
class="mt-5 rounded waitlist-success"
|
|
||||||
ref="waitlistSuccessMessage">
|
|
||||||
<img :src="waitListSuccessImage" class="success-image" />
|
<img :src="waitListSuccessImage" class="success-image" />
|
||||||
<span v-html="waitListSuccessText" class="success-text"></span>
|
<span v-html="waitListSuccessText" class="success-text"></span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="mt-5 mb-2 supplemental-information"
|
|
||||||
v-if="supplementalInformationBlock"
|
|
||||||
v-html="supplementalInformationBlock" />
|
|
||||||
<textBlock
|
<textBlock
|
||||||
v-show="disclaimerTextBlockCopy"
|
v-show="disclaimerTextBlockCopy"
|
||||||
:customText="disclaimerTextBlockCopy"
|
:customText="disclaimerTextBlockCopy"
|
||||||
justifyText="left"
|
justifyText="left"
|
||||||
typeStyle="caption"
|
typeStyle="caption"
|
||||||
class="mb-2" />
|
class="disclaimer" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -574,6 +571,7 @@ export default {
|
||||||
line-height: 1.5rem;
|
line-height: 1.5rem;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
margin: 1rem 0 1.5rem;
|
||||||
li strong {
|
li strong {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
@ -586,6 +584,7 @@ export default {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
.ui-checkbox {
|
.ui-checkbox {
|
||||||
padding-left: 0px;
|
padding-left: 0px;
|
||||||
|
|
@ -599,6 +598,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.waitlist-success {
|
.waitlist-success {
|
||||||
|
margin: 1rem 0 0;
|
||||||
background-color: #ecf5e9;
|
background-color: #ecf5e9;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
@ -606,9 +606,11 @@ export default {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 1.125rem;
|
font-size: 1.125rem;
|
||||||
padding: 0.75rem 1rem;
|
padding: 0.75rem 1rem;
|
||||||
margin-bottom: -0.5rem;
|
|
||||||
.success-text {
|
.success-text {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
|
p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.success-image {
|
.success-image {
|
||||||
margin-top: 4.5px;
|
margin-top: 4.5px;
|
||||||
|
|
@ -617,5 +619,9 @@ export default {
|
||||||
color: #0c7e47;
|
color: #0c7e47;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.disclaimer {
|
||||||
|
text-align: left;
|
||||||
|
margin: 1.5rem 0 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ describe("appointment-type-question.vue", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should display only the In-Shop and Drop-Off answers when only in-shop service is available", async () => {
|
it("Should display only the In-Shop answer when only in-shop service is available", async () => {
|
||||||
// Arrange/Act
|
// Arrange/Act
|
||||||
const { wrapper } = setupMocks({
|
const { wrapper } = setupMocks({
|
||||||
mixins: [mockMixin],
|
mixins: [mockMixin],
|
||||||
|
|
@ -108,6 +108,34 @@ describe("appointment-type-question.vue", () => {
|
||||||
cmsWidgetName: cmsWidgetName,
|
cmsWidgetName: cmsWidgetName,
|
||||||
isServiceableInshop: true,
|
isServiceableInshop: true,
|
||||||
isServiceableMobile: false,
|
isServiceableMobile: false,
|
||||||
|
isServiceableDropoff: false,
|
||||||
|
},
|
||||||
|
mountOptions: {
|
||||||
|
attachTo: document.body,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.answersToDisplay).toEqual([
|
||||||
|
{
|
||||||
|
AnswerImageUrl: "",
|
||||||
|
Name: "Inshop",
|
||||||
|
SubText: "",
|
||||||
|
SubWidgetName: "",
|
||||||
|
Text: "In-shop",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should display only the In-Shop and Drop-Off answers when mobile service is not available", async () => {
|
||||||
|
// Arrange/Act
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
mixins: [mockMixin],
|
||||||
|
props: {
|
||||||
|
cmsWidgetName: cmsWidgetName,
|
||||||
|
isServiceableInshop: true,
|
||||||
|
isServiceableMobile: false,
|
||||||
|
isServiceableDropoff: true,
|
||||||
},
|
},
|
||||||
mountOptions: {
|
mountOptions: {
|
||||||
attachTo: document.body,
|
attachTo: document.body,
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ export default {
|
||||||
cmsWidgetName: String,
|
cmsWidgetName: String,
|
||||||
isServiceableMobile: Boolean,
|
isServiceableMobile: Boolean,
|
||||||
isServiceableInshop: Boolean,
|
isServiceableInshop: Boolean,
|
||||||
|
isServiceableDropoff: Boolean,
|
||||||
mobileFeeApplies: Boolean,
|
mobileFeeApplies: Boolean,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -45,7 +46,7 @@ export default {
|
||||||
const shouldShowMobile = this.isServiceableMobile;
|
const shouldShowMobile = this.isServiceableMobile;
|
||||||
const shouldShowInshop = this.isServiceableInshop;
|
const shouldShowInshop = this.isServiceableInshop;
|
||||||
const shouldShowDropoff =
|
const shouldShowDropoff =
|
||||||
this.isServiceableInshop && !this.$store.getters.damage.isRepair;
|
this.isServiceableDropoff && !this.$store.getters.damage.isRepair;
|
||||||
|
|
||||||
var answers = this.answersFromCms
|
var answers = this.answersFromCms
|
||||||
? this.answersFromCms.filter((answer) => {
|
? this.answersFromCms.filter((answer) => {
|
||||||
|
|
@ -77,6 +78,11 @@ export default {
|
||||||
isMobileOnly() {
|
isMobileOnly() {
|
||||||
return this.isServiceableMobile && !this.isServiceableInshop;
|
return this.isServiceableMobile && !this.isServiceableInshop;
|
||||||
},
|
},
|
||||||
|
isInshopOnly() {
|
||||||
|
return (
|
||||||
|
this.isServiceableInshop && !this.isServiceableMobile && !this.isServiceableDropoff
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
answersToDisplay: {
|
answersToDisplay: {
|
||||||
|
|
@ -86,7 +92,7 @@ export default {
|
||||||
newValue.length == 1 &&
|
newValue.length == 1 &&
|
||||||
newValue.findIndex((answer) => answer.Name == "Mobile") != -1
|
newValue.findIndex((answer) => answer.Name == "Mobile") != -1
|
||||||
) {
|
) {
|
||||||
this.selectedValues = "Mobile";
|
this.selectedValue = "Mobile";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true,
|
immediate: true,
|
||||||
|
|
@ -94,7 +100,14 @@ export default {
|
||||||
isMobileOnly: {
|
isMobileOnly: {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
this.selectedValues = "Mobile";
|
this.selectedValue = "Mobile";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isInshopOnly: {
|
||||||
|
handler(newValue) {
|
||||||
|
if (newValue) {
|
||||||
|
this.selectedValue = "Inshop";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@
|
||||||
v-show="isAppointmentTypeDisplayed"
|
v-show="isAppointmentTypeDisplayed"
|
||||||
:isServiceableMobile="isServiceableMobile"
|
:isServiceableMobile="isServiceableMobile"
|
||||||
:isServiceableInshop="isServiceableInshop"
|
:isServiceableInshop="isServiceableInshop"
|
||||||
|
:isServiceableDropoff="isServiceableDropoff"
|
||||||
:isDisplayed="isAppointmentTypeDisplayed"
|
:isDisplayed="isAppointmentTypeDisplayed"
|
||||||
:mobileFeeApplies="mobileFeeApplies"
|
:mobileFeeApplies="mobileFeeApplies"
|
||||||
ref="appointmentTypeQuestion"
|
ref="appointmentTypeQuestion"
|
||||||
|
|
@ -197,6 +198,8 @@ export default {
|
||||||
isVehicleProtected: this.getIsVehicleProtectedFromStore(),
|
isVehicleProtected: this.getIsVehicleProtectedFromStore(),
|
||||||
isGlassServiceableInshop: null,
|
isGlassServiceableInshop: null,
|
||||||
isRecalibrationServiceableInshop: null,
|
isRecalibrationServiceableInshop: null,
|
||||||
|
isGlassServiceableDropoff: null,
|
||||||
|
isRecalibrationServiceableDropoff: null,
|
||||||
isGlassServiceableMobile: null,
|
isGlassServiceableMobile: null,
|
||||||
isRecalibrationServiceableMobile: null,
|
isRecalibrationServiceableMobile: null,
|
||||||
selectedAppointmentType: this.getSelectedAppointmentType(),
|
selectedAppointmentType: this.getSelectedAppointmentType(),
|
||||||
|
|
@ -356,6 +359,13 @@ export default {
|
||||||
return this.isGlassServiceableInshop;
|
return this.isGlassServiceableInshop;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
isServiceableDropoff() {
|
||||||
|
if (this.isRecalibrationServiceableDropoff !== null) {
|
||||||
|
return this.isGlassServiceableDropoff && this.isRecalibrationServiceableDropoff;
|
||||||
|
} else {
|
||||||
|
return this.isGlassServiceableDropoff;
|
||||||
|
}
|
||||||
|
},
|
||||||
isShopQuestionDisplayed() {
|
isShopQuestionDisplayed() {
|
||||||
return (
|
return (
|
||||||
this.selectedAppointmentType === "Inshop" ||
|
this.selectedAppointmentType === "Inshop" ||
|
||||||
|
|
@ -561,6 +571,9 @@ export default {
|
||||||
this.isGlassServiceableInshop = serviceabilityDetails.isGlassServiceableInshop;
|
this.isGlassServiceableInshop = serviceabilityDetails.isGlassServiceableInshop;
|
||||||
this.isRecalibrationServiceableInshop =
|
this.isRecalibrationServiceableInshop =
|
||||||
serviceabilityDetails.isRecalibrationServiceableInshop;
|
serviceabilityDetails.isRecalibrationServiceableInshop;
|
||||||
|
this.isGlassServiceableDropoff = serviceabilityDetails.isGlassServiceableDropoff;
|
||||||
|
this.isRecalibrationServiceableDropoff =
|
||||||
|
serviceabilityDetails.isRecalibrationServiceableDropoff;
|
||||||
this.isGlassServiceableMobile = serviceabilityDetails.isGlassServiceableMobile;
|
this.isGlassServiceableMobile = serviceabilityDetails.isGlassServiceableMobile;
|
||||||
this.isRecalibrationServiceableMobile =
|
this.isRecalibrationServiceableMobile =
|
||||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||||
|
|
|
||||||
|
|
@ -415,6 +415,21 @@ describe("service-zip.vue", () => {
|
||||||
expect(wrapper.vm.displayInvalidZipAlert).toBe(false);
|
expect(wrapper.vm.displayInvalidZipAlert).toBe(false);
|
||||||
expect(wrapper.vm.displayNonServiceableZipAlert).toBe(false);
|
expect(wrapper.vm.displayNonServiceableZipAlert).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should hide the AlertNoService when displayNoServiceAlert is false", async () => {
|
||||||
|
// Arrange
|
||||||
|
// no changes to store
|
||||||
|
applyMockStoreDataToGetters();
|
||||||
|
|
||||||
|
const wrapper = setupMocks({});
|
||||||
|
wrapper.vm.serviceZipCode = "12345";
|
||||||
|
|
||||||
|
wrapper.vm.displayNoServiceAlert = false;
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Check if the AlertNoService component is rendered
|
||||||
|
expect(wrapper.vm.displayNoServiceAlert).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -511,5 +526,15 @@ function setupMocks({ customMountOptions, customZipQuery, customZipDataResponse
|
||||||
];
|
];
|
||||||
|
|
||||||
const wrapper = shallowMount(serviceZip, mountOptions);
|
const wrapper = shallowMount(serviceZip, mountOptions);
|
||||||
|
wrapper.vm.findClosestApplicableShops = jest.fn().mockImplementation(() => {
|
||||||
|
return Promise.resolve({
|
||||||
|
data: {
|
||||||
|
providers: [
|
||||||
|
{ id: 1, name: "Shop 1" },
|
||||||
|
{ id: 2, name: "Shop 2" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,18 @@
|
||||||
v-model="customAlertData"
|
v-model="customAlertData"
|
||||||
v-if="displayNonServiceableZipAlert"
|
v-if="displayNonServiceableZipAlert"
|
||||||
alertClass="alert-danger" />
|
alertClass="alert-danger" />
|
||||||
|
<alert
|
||||||
|
ref="AlertNoService"
|
||||||
|
v-if="displayNoServiceAlert"
|
||||||
|
class="my-4"
|
||||||
|
cmsWidgetName="AlertNoServiceWidget"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid || displayNoServiceAlert"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -114,6 +121,7 @@ export default {
|
||||||
isHeavyTruck: this.getIsVehicleHeavyTruckServiceableFromStore(),
|
isHeavyTruck: this.getIsVehicleHeavyTruckServiceableFromStore(),
|
||||||
displayInvalidZipAlert: false,
|
displayInvalidZipAlert: false,
|
||||||
displayNonServiceableZipAlert: false,
|
displayNonServiceableZipAlert: false,
|
||||||
|
displayNoServiceAlert: false, // Initialize the property
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -278,17 +286,6 @@ export default {
|
||||||
return this.$refs.navbar.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.isHeavyTruck) {
|
|
||||||
const closestShops = await this.findClosestApplicableShops(
|
|
||||||
this.serviceZipCode,
|
|
||||||
this.carId
|
|
||||||
);
|
|
||||||
this.displayNoServiceAlert = !closestShops?.data?.providers?.length;
|
|
||||||
if (this.displayNoServiceAlert) {
|
|
||||||
return this.$refs.navbar.removeLoader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const payment = this.$store.getters.payment;
|
const payment = this.$store.getters.payment;
|
||||||
const policy = this.$store.getters.policy;
|
const policy = this.$store.getters.policy;
|
||||||
|
|
||||||
|
|
@ -346,7 +343,6 @@ export default {
|
||||||
serviceZipCode() {
|
serviceZipCode() {
|
||||||
this.displayNonServiceableZipAlert = false;
|
this.displayNonServiceableZipAlert = false;
|
||||||
this.displayNoServiceAlert = false;
|
this.displayNoServiceAlert = false;
|
||||||
this.displayNoServiceAlert = false;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
||||||
|
|
@ -95,12 +95,11 @@ describe("glass-part-question.vue", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
await wrapper.vm.$nextTick();
|
|
||||||
const listCard = await wrapper.findComponent({
|
const listCard = await wrapper.findComponent({
|
||||||
name: "buttonQuestion",
|
name: "buttonQuestion",
|
||||||
});
|
});
|
||||||
|
|
||||||
await wrapper.setData({ selectedTint: "Green Tint" });
|
wrapper.setData({ selectedTint: "Green Tint" });
|
||||||
// to trigger the computed setter
|
// to trigger the computed setter
|
||||||
wrapper.vm.selectedPartNumber = "DB12209GTYN";
|
wrapper.vm.selectedPartNumber = "DB12209GTYN";
|
||||||
|
|
||||||
|
|
@ -253,8 +252,7 @@ describe("glass-part-question.vue", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await wrapper.setData({ selectedTint: selectedTint });
|
wrapper.setData({ selectedTint: selectedTint });
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(expectedResults).toEqual(wrapper.vm.partsForSelectedTint);
|
expect(expectedResults).toEqual(wrapper.vm.partsForSelectedTint);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,23 @@ describe("vin-lookup.vue", () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.findAllComponents({ name: "alert" }).length).toBe(1);
|
expect(wrapper.findAllComponents({ name: "alert" }).length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should hide the AlertNoService when displayNoServiceAlert is false", async () => {
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
isZipServiceable: true,
|
||||||
|
displayNoServiceAlert: false,
|
||||||
|
lookupVinbyAddressResponse: {
|
||||||
|
isStatePermissible: true,
|
||||||
|
vinVehicles: [], // Return no vehicles
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Ensure displayNoServiceAlert is false
|
||||||
|
await wrapper.setData({ displayNoServiceAlert: false });
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
// Check if the AlertNoService component is not rendered
|
||||||
|
const alertNoService = wrapper.findComponent({ ref: "AlertNoService" });
|
||||||
|
expect(alertNoService.exists()).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getVinFromImage", () => {
|
describe("getVinFromImage", () => {
|
||||||
|
|
|
||||||
|
|
@ -111,10 +111,18 @@
|
||||||
"
|
"
|
||||||
alertClass="alert-success" />
|
alertClass="alert-success" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
ref="AlertNoService"
|
||||||
|
v-if="displayNoServiceAlert"
|
||||||
|
class="my-4"
|
||||||
|
cmsWidgetName="AlertNoServiceWidget"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="navbar"
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid || displayNoServiceAlert"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -209,6 +217,7 @@ export default {
|
||||||
displayVinNotFoundAlert: false,
|
displayVinNotFoundAlert: false,
|
||||||
displayMatchedDifferentVehicleAlert: false,
|
displayMatchedDifferentVehicleAlert: false,
|
||||||
displayVinScanFailedAlert: false,
|
displayVinScanFailedAlert: false,
|
||||||
|
displayNoServiceAlert: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -247,6 +256,9 @@ export default {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getCarIdfromStore() {
|
||||||
|
return this.$store.getters.vehicle.carId;
|
||||||
|
},
|
||||||
getIsVehicleHeavyTruckServiceableFromStore() {
|
getIsVehicleHeavyTruckServiceableFromStore() {
|
||||||
return store.getters.vehicle.isBigTruck && store.getters.vehicle.canSafeliteService;
|
return store.getters.vehicle.isBigTruck && store.getters.vehicle.canSafeliteService;
|
||||||
},
|
},
|
||||||
|
|
@ -341,7 +353,7 @@ export default {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
if (this.isHeavyTruck) {
|
if (this.isHeavyTruck) {
|
||||||
closestShops = await this.findClosestApplicableShops(
|
const closestShops = await this.findClosestApplicableShops(
|
||||||
this.serviceZipCode,
|
this.serviceZipCode,
|
||||||
this.carId
|
this.carId
|
||||||
);
|
);
|
||||||
|
|
@ -499,7 +511,6 @@ export default {
|
||||||
this.displayVinNotFoundAlert = false;
|
this.displayVinNotFoundAlert = false;
|
||||||
this.displayVinScanFailedAlert = false;
|
this.displayVinScanFailedAlert = false;
|
||||||
this.displayNoServiceAlert = false;
|
this.displayNoServiceAlert = false;
|
||||||
this.displayNoServiceAlert = false;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -576,6 +587,7 @@ export default {
|
||||||
},
|
},
|
||||||
serviceZipCode() {
|
serviceZipCode() {
|
||||||
this.displayNonServiceableZipAlert = false;
|
this.displayNonServiceableZipAlert = false;
|
||||||
|
this.displayNoServiceAlert = false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
// White/black
|
// White/black
|
||||||
$white: #ffffff;
|
$white: #ffffff;
|
||||||
$black: #000000;
|
$black: #000000;
|
||||||
|
$black-100: #0a0a0a;
|
||||||
|
|
||||||
// Blues
|
// Blues
|
||||||
$blue-100: #e4f1f7; // Used in theme
|
$blue-100: #e4f1f7; // Used in theme
|
||||||
|
|
@ -33,9 +34,11 @@ $green-300: #94d7b6;
|
||||||
$green-400: #5abc8c; // Used in theme
|
$green-400: #5abc8c; // Used in theme
|
||||||
$green-500: #2ca168;
|
$green-500: #2ca168;
|
||||||
$green: #0c7e47; // Default Green
|
$green: #0c7e47; // Default Green
|
||||||
|
$green-600: #e7f2ed;
|
||||||
$green-700: #006a36;
|
$green-700: #006a36;
|
||||||
$green-800: #004f28;
|
$green-800: #004f28;
|
||||||
$green-900: #00331a;
|
$green-900: #00331a;
|
||||||
|
$green-1000: #00723e;
|
||||||
|
|
||||||
// Yellows
|
// Yellows
|
||||||
$yellow-100: #fff5eb;
|
$yellow-100: #fff5eb;
|
||||||
|
|
@ -59,6 +62,8 @@ $gray-600: #4d5151; // Used in theme
|
||||||
$gray-700: #303333; // Used in theme
|
$gray-700: #303333; // Used in theme
|
||||||
$gray-800: #222424; // Used in theme
|
$gray-800: #222424; // Used in theme
|
||||||
$gray-900: #181a1a; // Used in theme
|
$gray-900: #181a1a; // Used in theme
|
||||||
|
$gray-1000: #b3b4b5;
|
||||||
|
$gray-1100: #4b4c4e;
|
||||||
|
|
||||||
//orange
|
//orange
|
||||||
$orange-600: #e86421;
|
$orange-600: #e86421;
|
||||||
|
|
@ -134,6 +139,8 @@ $font-weight-lighter: lighter;
|
||||||
$font-weight-light: 300;
|
$font-weight-light: 300;
|
||||||
$font-weight-normal: 400;
|
$font-weight-normal: 400;
|
||||||
$font-weight-bold: 500;
|
$font-weight-bold: 500;
|
||||||
|
$font-weight-600: 600;
|
||||||
|
$font-weight-700: 700;
|
||||||
$font-weight-bolder: bolder;
|
$font-weight-bolder: bolder;
|
||||||
|
|
||||||
//Headings
|
//Headings
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue