@@ -23,6 +20,9 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
+import { storeMutations } from "@/constants/store-mutations";
+import { storeActions } from "@/constants/store-actions";
+import store from "@/store";
export default {
name: "vehicle-year",
@@ -33,11 +33,11 @@ export default {
},
computed: {},
- beforeRouteEnter(to, from, next) {
-
+ async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
- const yearQuestionInitialDataPromise = yearQuestion.methods.loadInitialData();
+ const yearQuestionInitialDataPromise =
+ yearQuestion.methods.loadInitialData();
// Settle promises and get results
const promiseResultMap = [
@@ -50,24 +50,55 @@ export default {
promise: yearQuestionInitialDataPromise,
},
];
- settleAllPromises(promiseResultMap).then((resultMap) => {
- // Call the "next" function to complete the transition to this page.
- next((vm) => {
- vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget[0]);
- vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget[0]);
- vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget[0]);
- vm.$refs.yearQuestion.initializeComponent(resultMap.cmsContent.RadioQuestionWidget[0], resultMap.yearQuestionInitialData);
- });
+
+ let resultMap = await settleAllPromises(promiseResultMap);
+
+ // Call the "next" function to complete the transition to this page.
+ next((vm) => {
+ vm.$refs.funnelSubHeader.initializeComponent(
+ resultMap.cmsContent.FunnelSubHeaderWidget
+ );
+ vm.$refs.funnelHeader.initializeComponent(
+ resultMap.cmsContent.FunnelHeaderWidget
+ );
+ vm.$refs.vehicleBanner.initializeComponent(
+ resultMap.cmsContent.VehicleBannerWidget
+ );
+ vm.$refs.yearQuestion.initializeComponent(
+ resultMap.cmsContent.VehicleYearQuestion,
+ resultMap.yearQuestionInitialData
+ );
});
},
watch: {
selectedYear(year) {
+
this.$store.commit(this.storeMutations.UPDATE_YEAR, year);
- this.$router.navigate(this.navigationScenarios.SELECTED_YEAR, this.$route);
+ this.$router.navigateAfterSave(
+ this.navigationScenarios.SELECTED_YEAR,
+ this.$route
+ );
+ },
+ },
+ methods: {
+ arePagePrerequisitesValid() {
+ return true;
+ },
+ resetDependentState() {
+
+ // Set
+ store.commit(storeMutations.UPDATE_MAKE, null);
+ store.commit(storeMutations.UPDATE_MODEL, null);
+ store.commit(storeMutations.UPDATE_STYLE, null);
+ store.commit(storeMutations.UPDATE_CAR_ID, null);
+ store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
+
+ // Invokes
+ store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
+ store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
}
},
-
components: {
yearQuestion,
funnelHeader,
diff --git a/src/layouts/vehicle-year/year-question/year-question.spec.js b/src/layouts/vehicle-year/year-question/year-question.spec.js
index 3c00dcd9d..3555e6126 100644
--- a/src/layouts/vehicle-year/year-question/year-question.spec.js
+++ b/src/layouts/vehicle-year/year-question/year-question.spec.js
@@ -2,52 +2,73 @@ import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import store from "@/store";
-jest.mock("@/store", () => { return {}; }, {virtual: true});
+jest.mock(
+ "@/store",
+ () => {
+ return {};
+ },
+ { virtual: true }
+);
describe("year-question.vue", () => {
test("Selected year is emitted upon selection.", async () => {
-
//Arrange
const { wrapper } = setupMocks({ modelValueProp: "2020" });
const yearToSelect = "2021";
//Act
- wrapper.setData({ selectedYear: yearToSelect });
+ wrapper.setValue({ modelValue: yearToSelect });
await wrapper.vm.$nextTick();
//Assert
- expect(wrapper.emitted()["update:modelValue"][0]).toEqual(["2021"]);
+ expect(wrapper.emitted()["update:modelValue"][0]).toEqual([
+ { modelValue: "2021" },
+ ]);
});
});
describe("year-question.vue", () => {
test("CMS question text is used as radio question text.", async () => {
-
//Arrange
- const { wrapper, cmsContent } = setupMocks({ cmsQuestionText: "What year is your vehicle?" });
+ const { wrapper, cmsContent } = setupMocks({
+ cmsQuestionText: "What year is your vehicle?",
+ });
//Act
yearQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, null);
//Assert
- const buttonQuestionComponent = await wrapper.findComponent({ name: "buttonQuestion" });
- expect(buttonQuestionComponent.attributes("questiontext")).toBe("What year is your vehicle?");
+ const buttonQuestionComponent = await wrapper.findComponent({
+ name: "buttonQuestion",
+ });
+ expect(buttonQuestionComponent.attributes("questiontext")).toBe(
+ "What year is your vehicle?"
+ );
});
});
describe("year-question.vue", () => {
test("Data from store api are used as radio question answers.", async () => {
-
//Arrange
- const { wrapper, cmsContent } = setupMocks({ dataFromStoreApi: ["2023", "2022", "2021"] });
+ const { wrapper, cmsContent } = setupMocks({
+ dataFromStoreApi: ["2023", "2022", "2021"],
+ });
//Act
const initialData = yearQuestion.methods.loadInitialData.call(wrapper.vm);
- yearQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, initialData);
+ yearQuestion.methods.initializeComponent.call(
+ wrapper.vm,
+ cmsContent,
+ initialData
+ );
//Assert
- const buttonQuestionComponent = await wrapper.findComponent({ name: "buttonQuestion" });
- expect(buttonQuestionComponent.attributes("answers")).toBe("2023,2022,2021");
+ const buttonQuestionComponent = await wrapper.findComponent({
+ name: "buttonQuestion",
+ });
+ expect(buttonQuestionComponent.attributes("answers")).toBe(
+ "2023,2022,2021"
+ );
});
});
@@ -57,7 +78,6 @@ function setupMocks({
cmsQuestionText = "CMS text goes here",
dataFromStoreApi = [],
}) {
-
//Mock store
store.dispatch = jest.fn(() => dataFromStoreApi);
const mountOptions = getMountOptions({
@@ -70,11 +90,12 @@ function setupMocks({
mountOptions.propsData = {
modelValue: modelValueProp,
};
+
const wrapper = shallowMount(yearQuestion, mountOptions);
//Mock CMS content
const cmsContent = {
- QuestionText: cmsQuestionText
- };
+ QuestionText: cmsQuestionText,
+ };
return { wrapper, cmsContent };
-}
\ No newline at end of file
+}
diff --git a/src/layouts/vehicle-year/year-question/year-question.vue b/src/layouts/vehicle-year/year-question/year-question.vue
index 1a4a80279..96d047244 100644
--- a/src/layouts/vehicle-year/year-question/year-question.vue
+++ b/src/layouts/vehicle-year/year-question/year-question.vue
@@ -1,9 +1,14 @@
-
@@ -12,35 +17,44 @@ import buttonQuestion from "@/common-components/button-question/button-question"
// Supporting files
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
-
export default {
name: "year-question",
data() {
return {
questionText: null,
- selectedYear: null,
years: Array,
- }
+ };
},
props: {
modelValue: String,
},
+ emits: ['update:modelValue'],
components: {
buttonQuestion,
},
+ computed: {
+ selectedValueAsArray: {
+ get: function() {
+ const modelValueAsArray = this.modelValue ? [this.modelValue] : [];
+ return modelValueAsArray;
+ },
+ set: function(newValue) {
+ const newValueAsScalar = newValue && newValue.length > 0 ? newValue[0] : null;
+ this.$emit("update:modelValue", newValueAsScalar);
+ }
+ }
+ },
methods: {
loadInitialData() {
- return baseMixin.methods.dispatchNonBlockingStoreAction(storeActions.GET_VEHICLE_YEARS, {});
+ return baseMixin.methods.dispatchNonBlockingStoreAction(
+ storeActions.GET_VEHICLE_YEARS,
+ {}
+ );
},
initializeComponent(cmsContent, initialData) {
this.questionText = cmsContent.QuestionText;
this.years = initialData;
- }
- },
- watch: {
- selectedYear(val) {
- this.$emit("update:modelValue", val);
- }
+ },
},
};
diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js
index a31a5368f..d37ba38d7 100644
--- a/src/mixins/base-mixin.js
+++ b/src/mixins/base-mixin.js
@@ -1,13 +1,13 @@
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import { storeMutations } from "@/constants/store-mutations.js";
-import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
+import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import { widgetNames } from "@/constants/widget-names.js";
+import { vehicleCategories } from "@/constants/vehicle-categories.js";
export default {
data() {
- return {
- };
+ return {};
},
methods: {
dispatchNonBlockingStoreAction(type, payload, encodePayload = true) {
@@ -32,6 +32,9 @@ export default {
widgetNames() {
return widgetNames;
},
+ vehicleCategories() {
+ return vehicleCategories;
+ },
},
};
diff --git a/src/mixins/base-mixin.spec.js b/src/mixins/base-mixin.spec.js
index e9ccbdc5b..bdc083399 100644
--- a/src/mixins/base-mixin.spec.js
+++ b/src/mixins/base-mixin.spec.js
@@ -1,12 +1,14 @@
import baseMixin from "@/mixins/base-mixin";
import { storeActions } from "@/constants/store-actions.js";
import { widgetNames } from "@/constants/widget-names.js";
+import { storeMutations } from "@/constants/store-mutations.js";
+import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import store from "@/store";
describe("baseMixin.js", () => {
test("dispatchNonblockingStoreAction: calls dispatch with type and payload", () => {
const mixIn = getMixInInstance({});
- const type = '';
+ const type = "";
const payload = {};
mixIn.methods.dispatchNonBlockingStoreAction(type, payload);
@@ -16,14 +18,59 @@ describe("baseMixin.js", () => {
test("dispatchNonblockingStoreAction: calls dispatch with type and payload, handles Uri encode", () => {
const mixIn = getMixInInstance({});
- const type = '';
+ const type = "";
const payload = { make: "Alfa Romeo/Chrysler" };
mixIn.methods.dispatchNonBlockingStoreAction(type, payload, true);
expect(store.dispatch).toBeCalledWith(type, payload);
});
+
+ test("computed: storeActions should be equal to import object", () => {
+ // Arrange
+ const mixIn = getMixInInstance({});
+
+ // Act
+ let storeActionsForTest = mixIn.computed.storeActions();
+
+ // Assert
+ expect(storeActionsForTest).toEqual(storeActions);
+ });
+
+ test("computed: storeMutations should be equal to import object", () => {
+ // Arrange
+ const mixIn = getMixInInstance({});
+
+ // Act
+ let storeMutationsForTest = mixIn.computed.storeMutations();
+
+ // Assert
+ expect(storeMutationsForTest).toEqual(storeMutations);
+ });
+
+ test("computed: navigationScenarios should be equal to import object", () => {
+ // Arrange
+ const mixIn = getMixInInstance({});
+
+ // Act
+ let navigationScenariosForTest = mixIn.computed.navigationScenarios();
+
+ // Assert
+ expect(navigationScenariosForTest).toEqual(navigationScenarios);
+ });
+
+ test("computed: widgetNames should be equal to import object", () => {
+ // Arrange
+ const mixIn = getMixInInstance({});
+
+ // Act
+ let widgetNamesForTest = mixIn.computed.widgetNames();
+
+ // Assert
+ expect(widgetNamesForTest).toEqual(widgetNames);
+ });
});
+
function getMixInInstance({ isDispatchSuccess = true }) {
// Mock Store
const storeDispatch = jest.fn();
diff --git a/src/router/index.js b/src/router/index.js
index b1aa88493..133a4106e 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,68 +1,95 @@
+// Supporting files
import { createWebHistory, createRouter } from "vue-router";
-import { storeActions } from "@/constants/store-actions.js";
+import { storeActions } from "@/constants/store-actions";
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
import { routingTable } from "@/router/router-constants/routing-table.js";
-import ComponentTest from "@/layouts/component-test/component-test.vue";
-
-import AddressPOC from "@/layouts/address-poc/address-poc.vue";
-
-import NotFound from "@/layouts/not-found/not-found.vue";
+import { globalEvents, globalEventTypes } from "@/constants/events";
+import eventBus from "@/helpers/event-bus/event-bus";
import store from "@/store";
+// Components
+import ComponentTest from "@/layouts/component-test/component-test.vue";
+import AddressPOC from "@/layouts/address-poc/address-poc.vue";
+import FormTest from "@/layouts/form-test/form-test.vue";
+
const routes = [
- {
- path: "/:pathMatch(.*)*",
- component: NotFound,
- name: "NotFound",
- },
{
path: "/component-test", // This is a temporary route for testing.
name: "ComponentTest",
component: ComponentTest,
},
+ {
+ path: "/form-test", // This is a temporary route for testing.
+ name: "FormTest",
+ component: FormTest,
+ },
{
path: "/address-poc", // This is a temporary route for testing.
name: "AddressPOC",
component: AddressPOC,
},
+ {
+ path: "/form-test", // This is a temporary route for testing.
+ name: "FormTest",
+ component: FormTest,
+ },
{
path: "/",
- beforeEnter(to, from, next) {
+ name: "root",
+ async beforeEnter(to, from, next) {
// If we have no query string, or we don't have the FmgPage query string.
if (to.query.fmgPage === undefined) {
- RetainStructureAndGoTo404(to, next);
+ await GoToFunnelStartOn404(next);
} else {
- // If we already have our route, go to it.
- if (router.hasRoute(to.query.fmgPage)) {
- return next({
- name: to.query.fmgPage,
- query: to.query,
+ try {
+ // If we already have our route, go to it.
+ if (router.hasRoute(to.query.fmgPage)) {
+ // Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function.
+ const component = router
+ .getRoutes()
+ .filter((x) => x.name === to.query.fmgPage)[0].components;
+
+ if (!arePagePrerequisitesValid(component)) {
+ await GoToFunnelStartOn404(next);
+ }
+
+
+ return next({ name: to.query.fmgPage, query: to.query, params: to.params });
+ }
+
+ // Get route info for the given url. Names will have a 1:1 relationship with names in the Cms.
+ const routeData = await GetRouteInfoFromPageName(to.query.fmgPage);
+
+ // Add our dynamic route.
+ router.addRoute({
+ path: routeData[0].path, // Always the same path, because we control it with query strings.
+ name: routeData[0].name,
+ component: routeData[0].component,
});
+
+ // Call the next components arePagePrerequisitesValid method before load.
+ // If it returns false, use the 404 logic.
+ const nextComponent = await router
+ .getRoutes()
+ .filter((x) => x.name === routeData[0].name)[0]
+ .components.default();
+
+ if (!arePagePrerequisitesValid(nextComponent)) {
+ await GoToFunnelStartOn404(next);
+ }
+
+ // Assign current query string parameters, as well as our fmgPage one.
+ next({
+ name: routeData[0].name,
+ query: Object.assign(to.query, { fmgPage: routeData[0].name }),
+ params: to.params
+ });
+ } catch (error) {
+ console.log(error);
+
+ // If we don't have a route, go to our 404 page.
+ await GoToFunnelStartOn404(next);
}
-
- // Get route info for the given url. Names will have a 1:1 relationship with names in the Cms.
- GetRouteInfoFromPageName(to.query.fmgPage)
- .then((routeData) => {
- // Add our dynamic route.
- router.addRoute({
- path: routeData[0].path, // Always the same path, because we control it with query strings.
- name: routeData[0].name,
- component: routeData[0].component,
- });
-
- // Assign current query string parameters, as well as our fmgPage one.
- next({
- name: routeData[0].name,
- query: Object.assign(to.query, { fmgPage: routeData[0].name }),
- });
- })
- .catch((error) => {
- // If we can't find the route, go to the 404 page.
- RetainStructureAndGoTo404(to, next);
-
- console.log("error:");
- console.log(error);
- });
}
},
},
@@ -75,25 +102,38 @@ const router = createRouter({
//---------------------------------------------------------- Router Functions ----------------------------------------------------------
+router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => {
+ navigate(scenario, currentRoute, false, optionalQuery, optionalParams);
+}
+
+router.navigateAfterSave = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => {
+ navigate(scenario, currentRoute, true, optionalQuery, optionalParams);
+}
+
+// PRIVATE FUNCTIONS
+
// Navigate to the next route, depending on the scenario.
-router.navigate = (
- scenario,
- currentRoute,
- optionalQuery = {},
- optionalParams = {}
-) => {
+function navigate(scenario, currentRoute, invalidateOnSave, optionalQuery = {}, optionalParams = {}) {
if (!scenario) {
console.error("No scenario provided. Please review the routing table.");
return;
}
// Match our maps up and navigate if we have a destination.
- const matchingScenarioMap = router.getNavigationMap(scenario, currentRoute);
+ const matchingScenarioMap = getNavigationMap(scenario, currentRoute);
if (matchingScenarioMap.destinationFmgPageValue !== undefined) {
// We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one.
+
+ // If we need to do invalidation
+ const currentComponent = currentRoute.matched[0].components;
+
+ if (invalidateOnSave) {
+ resetDependentState(currentComponent);
+ }
+
router.push({
- path: "/",
+ name: "root",
query: Object.assign(optionalQuery, {
fmgPage: matchingScenarioMap.destinationFmgPageValue,
}),
@@ -102,10 +142,10 @@ router.navigate = (
} else if (matchingScenarioMap.destinationUrl !== undefined) {
navigateToUrl(matchingScenarioMap.destinationUrl);
}
-};
+}
-// Get navigation map depeding on the scenario and the current 'page' you're on.
-router.getNavigationMap = (scenario, currentRoute) => {
+// Get navigation map depending on the scenario and the current 'page' you're on.
+function getNavigationMap(scenario, currentRoute) {
const fmgPageValue = currentRoute.query.fmgPage;
const matchedQueryValue = routingTable
.filter(
@@ -116,7 +156,7 @@ router.getNavigationMap = (scenario, currentRoute) => {
.map((m) => m.maps.filter((map) => map.scenario === scenario));
return matchedQueryValue[0][0];
-};
+}
//---------------------------------------------------------- Private Functions ----------------------------------------------------------
@@ -128,39 +168,56 @@ function navigateToUrl(url) {
// Get route information by page name.
// This will reach out to the Cms and there is a 1:1 relationship between page names and route names.
-function GetRouteInfoFromPageName(pageName) {
- return new Promise((resolve, reject) => {
- store
- .dispatch(storeActions.GET_ROUTE_INFO_ACTION, { pageName: pageName })
- .then((response) => {
- // Add our route data and return our array.
- let jsonFromResponse = JSON.parse(response.data.Result);
- let routeData = [];
+async function GetRouteInfoFromPageName(pageName) {
+ const response = await store.dispatch(storeActions.GET_ROUTE_INFO_ACTION, {
+ pageName: pageName,
+ });
+ const jsonFromResponse = JSON.parse(response.data.Result);
+ let routeData = [];
- Object.keys(jsonFromResponse).forEach((key) => {
- routeData.push({
- path: "/",
- name: `${key}`,
- component: lazyLoadComponent(jsonFromResponse[key].LayoutName),
- });
- });
+ // Add our route data and return our array.
+ Object.keys(jsonFromResponse).forEach((key) => {
+ routeData.push({
+ path: "/",
+ name: `${key}`,
+ component: lazyLoadComponent(jsonFromResponse[key].LayoutName),
+ });
+ });
- resolve(routeData);
- })
- .catch((error) => {
- reject(error);
- });
+ return routeData;
+}
+
+// Go to our start page on a 404.
+async function GoToFunnelStartOn404(next) {
+ const apiResponse = await store.dispatch(storeActions.GET_HOMEPAGE_NAME);
+ const homepageName = apiResponse.data.Result;
+
+ // Put item on the bus
+ eventBus.addEventToBus(
+ globalEvents.Categories.GLOBAL_ALERT,
+ globalEvents.SubCategories.PAGE_NOT_FOUND,
+ {
+ isDismissible: true,
+ messageCopy: "You can get a quote by starting on this page.",
+ messageHeadline: "We're sorry, something went wrong.",
+ type: globalEventTypes.Danger,
+ }
+ );
+
+ next({
+ path: "/",
+ query: { fmgPage: homepageName },
});
}
-// Go to our 404 page but retain our structure when we go there (path, queryString, hash).
-function RetainStructureAndGoTo404(to, next) {
- next({
- name: "NotFound",
- params: { pathMatch: to.path.split("/").slice(1) },
- query: to.query,
- hash: to.hash,
- });
+// Checks arePagePrerequisitesValid on the component passed in.
+function arePagePrerequisitesValid(component) {
+ return component.default.methods.arePagePrerequisitesValid();
+}
+
+// Reset dependant state on route change.
+function resetDependentState(component) {
+ return component.default.methods.resetDependentState();
}
export default router;
diff --git a/src/router/router-constants/fmgPage-values.js b/src/router/router-constants/fmgPage-values.js
index 38486e111..9b82cdf7e 100644
--- a/src/router/router-constants/fmgPage-values.js
+++ b/src/router/router-constants/fmgPage-values.js
@@ -3,6 +3,7 @@ const fmgPageValues = {
VEHICLE_MAKE: "vehicle-make",
VEHICLE_MODEL: "vehicle-model",
VEHICLE_STYLE: "vehicle-style",
+ VEHICLE_DAMAGE: "vehicle-damage",
};
export { fmgPageValues };
diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js
index 21dc6ca65..17f05b304 100644
--- a/src/router/router-constants/routing-table.js
+++ b/src/router/router-constants/routing-table.js
@@ -21,7 +21,7 @@ const routingTable = [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.VEHICLE_YEAR,
- }
+ },
],
},
{
@@ -34,7 +34,7 @@ const routingTable = [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE,
- }
+ },
],
},
{
@@ -42,14 +42,14 @@ const routingTable = [
maps: [
{
scenario: navigationScenarios.SELECTED_STYLE,
- destinationFmgPageValue: fmgPageValues.VEHICLE_STYLE,
+ destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.VEHICLE_MODEL,
- }
+ },
],
},
];
-export { routingTable };
\ No newline at end of file
+export { routingTable };
diff --git a/src/store/index.js b/src/store/index.js
index daf34e38c..c7227de47 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,152 +1,255 @@
import { createStore } from "vuex";
import { endpoints } from "@/constants/endpoints.js";
+import { storeMutations } from "@/constants/store-mutations";
import createPersistedState from "vuex-persistedstate";
import globalMethods from "@/global-methods";
+
+
+// Export State
+export const state = {
+ order: {
+ vehicle: {
+ year: null,
+ make: null,
+ model: null,
+ style: null,
+ carId: null,
+ category: null,
+ imageUrl: null,
+ imageVifNumber: null,
+ imageColor: null,
+ },
+ damage: {
+ isRepair: null,
+ numberOfChips: null,
+ glassToReplace: null,
+ },
+ },
+ applicationUser: {
+ eventBus: [],
+ },
+}
+
+// Export Mutations
+export const mutations = {
+ // VEHICLE MUTATIONS
+ updateYear(state, year) {
+ state.order.vehicle.year = year;
+ },
+ updateMake(state, make) {
+ state.order.vehicle.make = make;
+ },
+ updateModel(state, model) {
+ state.order.vehicle.model = model;
+ },
+ updateStyle(state, style) {
+ state.order.vehicle.style = style;
+ },
+ updateCarId(state, carId) {
+ state.order.vehicle.carId = carId;
+ },
+ updateVehicleCategory(state, category) {
+ state.order.vehicle.category = category;
+ },
+ updateVehicleImageUrl(state, imageUrl) {
+ state.order.vehicle.imageUrl = imageUrl;
+ },
+ updateVehicleImageVifNumber(state, imageVifNumber) {
+ state.order.vehicle.imageVifNumber = imageVifNumber;
+ },
+ updateVehicleImageColor(state, imageColor) {
+ state.order.vehicle.imageColor = imageColor;
+ },
+
+ // EVENT BUS MUTATIONS
+ addEventToBus(state, event) {
+ state.applicationUser.eventBus.push(event);
+ },
+ removeEventFromBus(state, eventData) {
+ const matchedEvent = state.applicationUser.eventBus.find(
+ ({ category, subCategory }) =>
+ category === eventData.category &&
+ subCategory === eventData.subCategory
+ );
+ const itemIndex = state.applicationUser.eventBus.indexOf(matchedEvent);
+
+ // If the item exists, remove it.
+ if (itemIndex > -1) {
+ state.applicationUser.eventBus.splice(itemIndex, 1);
+ }
+ },
+
+ // DEPENDENCY MUTATIONS
+ resetVehicleAndDependencies(state) {
+ state.order.vehicle.year = null;
+ state.order.vehicle.make = null;
+ state.order.vehicle.model = null;
+ state.order.vehicle.style = null;
+ state.order.vehicle.carId = null;
+ state.order.vehicle.category = null;
+ },
+ resetDamageAndDependencies(state) {
+ state.order.damage.isRepair = null;
+ state.order.damage.numberOfChips = null;
+ state.order.damage.windshieldGlassToReplace = null;
+ state.order.damage.driverSideGlassToReplace = null;
+ state.order.damage.passengerSideGlassToReplace = null;
+ state.order.damage.rearGlassToReplace = null;
+
+ },
+ resetRegistrationAndDependencies(state) {
+
+ },
+ resetPartsAndDependencies(state) {
+
+ }
+}
+
+// Export Getters
+export const getters = {
+ vehicle: (state) => state.order.vehicle,
+ eventBusItem: (state) => (eventCategory, eventSubCategory) => {
+ const matchedEvent = state.applicationUser.eventBus.find(
+ ({ category, subCategory }) =>
+ category === eventCategory && subCategory === eventSubCategory
+ );
+
+ return matchedEvent !== undefined ? matchedEvent.eventValue : undefined;
+ },
+ eventBus: (state) => state.applicationUser.eventBus,
+}
+
+// Export Actions
+export const actions = {
+ // Vehicle API Actions
+ getVehicleYears(context) {
+ return globalMethods.callHttpClient({
+ method: endpoints.GetVehicleYears.method,
+ endpoint: endpoints.GetVehicleYears.url,
+ payload: {},
+ });
+ },
+ lookupVehicleByYmms(context, { year, make, model, style }) {
+ return globalMethods.callHttpClient({
+ method: endpoints.LookupVehicleByYmms.method,
+ endpoint: `${endpoints.LookupVehicleByYmms.url}/${year}/${make}/${model}/${style}`,
+ payload: {},
+ });
+ },
+ lookupVehicleByVin(context, { vin }) {
+ return globalMethods.callHttpClient({
+ method: endpoints.LookupVehicleByVin.method,
+ endpoint: endpoints.LookupVehicleByVin.url,
+ payload: {
+ vin: vin, // EX "1J4GW58S4XC541166"
+ },
+ });
+ },
+ getVehicleMakes(context, { year }) {
+ return globalMethods.callHttpClient({
+ method: endpoints.GetVehicleMakes.method,
+ endpoint: `${endpoints.GetVehicleMakes.url}/${year}`,
+ payload: {},
+ });
+ },
+ getVehicleModels(context, { year, make }) {
+ return globalMethods.callHttpClient({
+ method: endpoints.GetVehicleModels.method,
+ endpoint: `${endpoints.GetVehicleModels.url}/${year}/${make}`,
+ payload: {},
+ });
+ },
+ getVehicleStyles(context, { year, make, model }) {
+ return globalMethods.callHttpClient({
+ method: endpoints.GetVehicleStyles.method,
+ endpoint: `${endpoints.GetVehicleStyles.url}/${year}/${make}/${model}`,
+ payload: {},
+ });
+ },
+ setVehicle(context, { year, make, model, style }) {
+ return globalMethods
+ .callHttpClient({
+ methods: endpoints.GetVehicle.method,
+ endpoint: `${endpoints.GetVehicle.url}/${year}/${make}/${model}/${style}`,
+ payload: {},
+ })
+ .then((response) => {
+ context.commit(storeMutations.UPDATE_CAR_ID, response.data.carId);
+ context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, response.data.category);
+ context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, response.data.imageUrl);
+ context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, response.data.imageVifNumber);
+ context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, response.data.imageVifColor);
+ return response;
+ });
+ },
+ getDamageOptions(context, { carId }) {
+ return globalMethods.callHttpClient({
+ methods: endpoints.GetDamageOptions.method,
+ endpoint: `${endpoints.GetDamageOptions.url}/${carId}`,
+ payload: {},
+ });
+ },
+
+ // DEPENDENCY ACTIONS
+ resetVehicleAndDependencies(context) {
+ context.commit(storeMutations.RESET_VEHICLE_AND_DEPS);
+ context.commit(storeMutations.RESET_DAMAGE_AND_DEPS);
+ context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS);
+ },
+ resetDamageAndDependencies(context) {
+ context.commit(storeMutations.RESET_DAMAGE_AND_DEPS);
+ context.commit(storeMutations.RESET_PARTS_AND_DEPS);
+ },
+ resetRegistrationAndDependencies(context) {
+ context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS);
+ context.commit(storeMutations.RESET_PARTS_AND_DEPS)
+ },
+ resetPartsAndDependencies(context) {
+ context.commit(storeMutations.RESET_PARTS_AND_DEPS);
+ },
+
+ // Content API Actions
+ getRouteInfo(context, { pageName }) {
+ return globalMethods.callHttpClient({
+ method: endpoints.GetRouteInfo.method,
+ endpoint: endpoints.GetRouteInfo.url,
+ payload: {
+ pageName: pageName,
+ },
+ });
+ },
+ getHomepageName(context) {
+ return globalMethods.callHttpClient({
+ method: endpoints.GetHomepageInfo.method,
+ endpoint: endpoints.GetHomepageInfo.url,
+ });
+ },
+ getPageData(context, { pageName }) {
+ return globalMethods.callHttpClient({
+ method: endpoints.GetPageData.method,
+ endpoint: `${endpoints.GetPageData.url}/${pageName}`,
+ payload: {},
+ });
+ },
+ getEvoxImage(context, { relativeUrl }) {
+ return globalMethods.callHttpClient({
+ method: endpoints.GetPageData.method,
+ endpoint: relativeUrl,
+ payload: {},
+ });
+ },
+}
+
export default createStore({
- plugins: [
- createPersistedState({
- storage: window.sessionStorage,
- }),
- ],
+ plugins: [createPersistedState()],
// IMPORTANT: Be VERY careful when modifying these fields for at least a few reasons:
// * The CMS can reference the fields by name
// * Return users may have a previous "version" of the model, and we don't want
// them to have a breaking experience, because the model might have changed.
- state: {
- order: {
- vehicle: {
- year: null,
- make: null,
- model: null,
- style: null,
- vin: null,
- licensePlate: null,
- carId: null,
- evoxImageId: null,
- hasSplitWindshieldOption: null,
- hasBackglassSliderOption: null,
- registration: {
- rawAddress: null,
- zipCode: null,
- firstName: null,
- lastName: null,
- licensePlate: null,
- },
- damage: {
- isRepair: null,
- isReplacement: null,
- numberOfChips: null,
- glassToReplace: null,
- problemGlassQuestionAnswers: null,
- problemMoldingQuestionAnswers: null,
- problemPropertyQuestionAnswers: null,
- },
- lineItems: null,
- customer: {
- emailAddress: null,
- },
- payment: {
- isInsurance: null,
- isCash: null,
- },
- referralSeqNum: null,
- },
- },
- applicationUser: {
- experiments: null,
- },
- },
- // See IMPORTANT note at top of "state" declaration.
-
- mutations: {
- updateYear(state, year) {
- state.order.vehicle.year = year;
- },
- updateMake(state, make) {
- state.order.vehicle.make = make;
- },
- updateModel(state, model) {
- state.order.vehicle.model = model;
- },
- updateStyle(state, style) {
- state.order.vehicle.style = style;
- },
- },
- getters: {
- vehicle: state => state.order.vehicle
- },
- actions: {
- // Vehicle API Actions
- getVehicleYears(context) {
- return globalMethods.callHttpClient({
- method: endpoints.GetVehicleYears.method,
- endpoint: endpoints.GetVehicleYears.url,
- payload: {},
- });
- },
- lookupVehicleByYmms(context, { year, make, model, style }) {
- return globalMethods.callHttpClient({
- method: endpoints.LookupVehicleByYmms.method,
- endpoint: `${endpoints.LookupVehicleByYmms.url}/${year}/${make}/${model}/${style}`,
- payload: {},
- });
- },
- lookupVehicleByVin(context, { vin }) {
- return globalMethods.callHttpClient({
- method: endpoints.LookupVehicleByVin.method,
- endpoint: endpoints.LookupVehicleByVin.url,
- payload: {
- vin: vin, // EX "1J4GW58S4XC541166"
- },
- });
- },
- getVehicleMakes(context, { year }) {
- return globalMethods.callHttpClient({
- method: endpoints.GetVehicleMakes.method,
- endpoint: `${endpoints.GetVehicleMakes.url}/${year}`,
- payload: {},
- });
- },
- getVehicleModels(context, { year, make }) {
- return globalMethods.callHttpClient({
- method: endpoints.GetVehicleModels.method,
- endpoint: `${endpoints.GetVehicleModels.url}/${year}/${make}`,
- payload: {},
- });
- },
- getVehicleStyles(context, { year, make, model }) {
- return globalMethods.callHttpClient({
- method: endpoints.GetVehicleStyles.method,
- endpoint: `${endpoints.GetVehicleStyles.url}/${year}/${make}/${model}`,
- payload: {},
- });
- },
-
- // Content API Actions
- getRouteInfo(context, { pageName }) {
- return globalMethods.callHttpClient({
- method: endpoints.GetRouteInfo.method,
- endpoint: endpoints.GetRouteInfo.url,
- payload: {
- pageName: pageName,
- },
- });
- },
- getPageData(context, { pageName }) {
- return globalMethods.callHttpClient({
- method: endpoints.GetPageData.method,
- endpoint: `${endpoints.GetPageData.url}/${pageName}`,
- payload: {},
- });
- },
- getEvoxImage(context, { relativeUrl }) {
- return globalMethods.callMockHttpClient({
- method: endpoints.GetPageData.method,
- endpoint: relativeUrl,
- payload: {},
- });
- },
- },
+ state,
+ mutations,
+ getters,
+ actions,
});
diff --git a/src/store/store.spec.js b/src/store/store.spec.js
index fcfca4576..f33595e58 100644
--- a/src/store/store.spec.js
+++ b/src/store/store.spec.js
@@ -1,228 +1,483 @@
-import store from "./index";
import globalMethods from "@/global-methods";
+import { mutations, state, actions, getters } from "@/store";
+import { storeMutations } from "@/constants/store-mutations";
-describe("Actions", () => {
- it("Should return list of years retrieved", async () => {
+// Mock global method
+globalMethods.callHttpClient = jest.fn();
+
+
+describe("Mutations", () => {
+
+ it("Updates vehicle year in state", () => {
// Arrange
- let years = [];
+ const storeState = state;
+
+ // Act
+ mutations.updateYear(storeState, "2019");
+
+ // Assert
+ expect(storeState.order.vehicle.year).toEqual("2019");
+ });
+
+ it("Updates vehicle make in state", () => {
+ // Arrange
+ const storeState = state;
+
+ // Act
+ mutations.updateMake(storeState, "Acura");
+
+ // Assert
+ expect(storeState.order.vehicle.make).toEqual("Acura");
+ });
+
+ it("Updates vehicle model in state", () => {
+ // Arrange
+ const storeState = state;
+
+ // Act
+ mutations.updateModel(storeState, "ILX");
+
+ // Assert
+ expect(storeState.order.vehicle.model).toEqual("ILX");
+ });
+
+ it("Updates vehicle style in state", () => {
+ // Arrange
+ const storeState = state;
+
+ // Act
+ mutations.updateStyle(storeState, "4 DOOR SEDAN");
+
+ // Assert
+ expect(storeState.order.vehicle.style).toEqual("4 DOOR SEDAN");
+ });
+
+ it("Updates vehicle carId in state", () => {
+ // Arrange
+ const storeState = state;
+
+ // Act
+ mutations.updateCarId(storeState, "C0000001");
+
+ // Assert
+ expect(storeState.order.vehicle.carId).toEqual("C0000001");
+ });
+
+ it("Updates vehicle vehicle category in state", () => {
+ // Arrange
+ const storeState = state;
+
+ // Act
+ mutations.updateVehicleCategory(storeState, "CAR");
+
+ // Assert
+ expect(storeState.order.vehicle.category).toEqual("CAR");
+ });
+
+ it("Remove item to eventBus in state", () => {
+ // Arrange
+ const storeState = state;
+ const event = { category: "CategoryOne", subCategory: "SubCategoryOne" }
+
+ // Act / Assert
+ mutations.addEventToBus(storeState, event);
+ expect(storeState.applicationUser.eventBus).toEqual([event]);
+
+ // Act / Assert
+ mutations.removeEventFromBus(storeState, event);
+ expect(storeState.applicationUser.eventBus).toEqual([]);
+
+ });
+
+ it("Adds item to eventBus in state", () => {
+ // Arrange
+ const storeState = state;
+
+ // Act
+ mutations.addEventToBus(storeState, { EventOne: "ValueOne" });
+
+ // Assert
+ expect(storeState.applicationUser.eventBus).toEqual([{ EventOne: "ValueOne" }]);
+ });
+
+ it("resetVehicleAndDependencies, should set fields to null", () => {
+ // Arrange
+ const storeState = state;
+
+ mutations.updateYear(storeState, "2019");
+ mutations.updateMake(storeState, "Acura");
+ mutations.updateModel(storeState, "ILX");
+ mutations.updateStyle(storeState, "4 DOOR SEDAN");
+ mutations.updateCarId(storeState, "C0000001");
+ mutations.updateVehicleCategory(storeState, "CAR");
+
+ // Expect
+ expect(storeState.order.vehicle.year).toEqual("2019");
+ expect(storeState.order.vehicle.make).toEqual("Acura");
+ expect(storeState.order.vehicle.model).toEqual("ILX");
+ expect(storeState.order.vehicle.style).toEqual("4 DOOR SEDAN");
+ expect(storeState.order.vehicle.carId).toEqual("C0000001");
+ expect(storeState.order.vehicle.category).toEqual("CAR");
+
+ // Act
+ mutations.resetVehicleAndDependencies(storeState);
+
+ // Expect
+ expect(storeState.order.vehicle.year).toEqual(null);
+ expect(storeState.order.vehicle.make).toEqual(null);
+ expect(storeState.order.vehicle.model).toEqual(null);
+ expect(storeState.order.vehicle.style).toEqual(null);
+ expect(storeState.order.vehicle.carId).toEqual(null);
+ expect(storeState.order.vehicle.category).toEqual(null);
+
+ });
+
+ it("resetDamageAndDependencies, should set fields to null", () => {
+ // Arrange
+ const storeState = state;
+
+ storeState.order.damage = {
+ isRepair: true,
+ numberOfChips: 2,
+ windshieldGlassToReplace: "Front",
+ driverSideGlassToReplace: "Rear",
+ passengerSideGlassToReplace: "Rear",
+ rearGlassToReplace: "Slider"
+ }
+
+ // Expect
+ expect(storeState.order.damage.isRepair).toEqual(true);
+ expect(storeState.order.damage.numberOfChips).toEqual(2);
+ expect(storeState.order.damage.windshieldGlassToReplace).toEqual("Front");
+ expect(storeState.order.damage.driverSideGlassToReplace).toEqual("Rear");
+ expect(storeState.order.damage.passengerSideGlassToReplace).toEqual("Rear");
+ expect(storeState.order.damage.rearGlassToReplace).toEqual("Slider");
+
+ // Act
+ mutations.resetDamageAndDependencies(storeState);
+
+ // Expect
+ expect(storeState.order.damage.isRepair).toEqual(null);
+ expect(storeState.order.damage.numberOfChips).toEqual(null);
+ expect(storeState.order.damage.windshieldGlassToReplace).toEqual(null);
+ expect(storeState.order.damage.driverSideGlassToReplace).toEqual(null);
+ expect(storeState.order.damage.passengerSideGlassToReplace).toEqual(null);
+ expect(storeState.order.damage.rearGlassToReplace).toEqual(null);
+
+ });
+
+});
+
+describe("Actions", () => {
+ it("getVehicleYears action, should return years array", async () => {
+
+ // Arrange
+ const context = state;
// Act
- globalMethods.callHttpClient = jest.fn();
globalMethods.callHttpClient.mockImplementation(() => {
return Promise.resolve({ data: [2023, 2022, 2021] });
});
- await store.dispatch("getVehicleYears").then((response) => {
- years = response.data;
- });
// Assert
- expect(years[0]).toBe(2023);
+ const response = await actions.getVehicleYears(context)
+
+ expect(response.data).toEqual([2023, 2022, 2021]);
});
- it("Should return list of makes retrieved", async () => {
+ it("lookupVehicleByYmms action, should return car data", async () => {
+
// Arrange
- let makes = [];
+ const context = state;
// Act
globalMethods.callHttpClient.mockImplementation(() => {
- return Promise.resolve({ data: ["Baic", "Honda", "Ford"] });
- });
- await store.dispatch("getVehicleMakes", { year: 2023 }).then((response) => {
- makes = response.data;
+ return Promise.resolve({ data: { carId: "C00000001" } });
});
// Assert
- expect(makes[0]).toBe("Baic");
+ const response = await actions.lookupVehicleByYmms(context, "2019", "Acura", "ILX", "4 DOOR SEDAN")
+
+ expect(response.data).toEqual({ carId: "C00000001" });
});
- it("Should return list of models retrieved", async () => {
+ it("lookupVehicleByVin action, should return car data", async () => {
+
// Arrange
- let models = [];
+ const context = state;
// Act
globalMethods.callHttpClient.mockImplementation(() => {
- return Promise.resolve({ data: ["BJ40 (MEX)", "Civic", "Accord"] });
+ return Promise.resolve({ data: { carId: "C00000001" } });
});
- await store
- .dispatch("getVehicleModels", { year: 2023, make: "Baic" })
- .then((response) => {
- models = response.data;
- });
// Assert
- expect(models[0]).toBe("BJ40 (MEX)");
+ const response = await actions.lookupVehicleByVin(context, "12345678901234567")
+
+ expect(response.data).toEqual({ carId: "C00000001" });
});
- it("Should return list of styles retrieved", async () => {
+ it("getVehicleMakes action, should return makes list", async () => {
+
// Arrange
- let styles = [];
+ const context = state;
// Act
globalMethods.callHttpClient.mockImplementation(() => {
- return Promise.resolve({ data: ["4 DOOR UTILITY", "2 DOOR"] });
+ return Promise.resolve({ data: ["Acura", "Honda"] });
});
- await store
- .dispatch("getVehicleStyles", {
- year: 2023,
- make: "Baic",
- model: "BJ40 (MEX)",
- })
- .then((response) => {
- styles = response.data;
- });
// Assert
- expect(styles[0]).toBe("4 DOOR UTILITY");
+ const response = await actions.getVehicleMakes(context, "2019")
+
+ expect(response.data).toEqual(["Acura", "Honda"]);
});
- it("Should return data from url retrieved", async () => {
+ it("getVehicleModels action, should return models list", async () => {
+
// Arrange
- let routeInfo = [];
+ const context = state;
// Act
globalMethods.callHttpClient.mockImplementation(() => {
- return Promise.resolve({
- data: {
- Result: "Route Info Data",
- },
- });
+ return Promise.resolve({ data: ["ILX", "RDX"] });
});
- await store
- .dispatch("getRouteInfo", { pageName: "vehicle-year" })
- .then((response) => {
- routeInfo = response.data.Result;
- });
// Assert
- expect(routeInfo).toBe("Route Info Data");
+ const response = await actions.getVehicleModels(context, "2019", "Acura")
+
+ expect(response.data).toEqual(["ILX", "RDX"]);
});
- it("Should return page data from url retrieved", async () => {
+ it("getVehicleStyles action, should return models list", async () => {
+
// Arrange
- let pageData = [];
+ const context = state;
// Act
globalMethods.callHttpClient.mockImplementation(() => {
- return Promise.resolve({
- data: {
- Result: "Page Info Data",
- },
- });
+ return Promise.resolve({ data: { style: "4 DOOR SEDAN" } });
});
- await store
- .dispatch("getPageData", { pageName: "vehicle-year" })
- .then((response) => {
- pageData = response.data.Result;
- });
// Assert
- expect(pageData).toBe("Page Info Data");
+ const response = await actions.getVehicleStyles(context, "2019", "Acura", "ILX")
+
+ expect(response.data).toEqual({ style: "4 DOOR SEDAN" });
});
- it("Should return data from url retrieved", async () => {
+ it("setVehicle action, should get vehicle data and set carId and vehicle category", async () => {
+
// Arrange
- let returnData = [];
+ const context = state;
+ const commit = jest.fn();
+
+ context.commit = commit;
// Act
globalMethods.callHttpClient.mockImplementation(() => {
- return Promise.resolve({
- data: {
- Result: "2018 Honda Civic",
- },
- });
+ return Promise.resolve({ data: { carId: "C00000000", category: "CAR" } });
});
- await store
- .dispatch("lookupVehicleByYmms", { year: "2018", make: "Honda", model: "Civic", style: "2 Door"})
- .then((response) => {
- returnData = response.data.Result;
- });
// Assert
- expect(returnData).toBe("2018 Honda Civic");
+ const response = await actions.setVehicle(context, "C00000000")
+
+ expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, "C00000000");
+ expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, "CAR");
+ expect(response.data).toEqual({ carId: "C00000000", category: "CAR" });
});
- it("Should return vehicle data from url retrieved", async () => {
+ it("getDamageOptions action", async () => {
+
// Arrange
- let returnData = [];
+ const context = state;
// Act
globalMethods.callHttpClient.mockImplementation(() => {
- return Promise.resolve({
- data: {
- Result: "2021 Honda Civic",
- },
- });
+ return Promise.resolve({ data: ["Windshield", "DriversFrontDoor"] });
});
- await store
- .dispatch("lookupVehicleByVin", { vin: "12345678"})
- .then((response) => {
- returnData = response.data.Result;
- });
+
+ const response = await actions.getDamageOptions(context, "C00000000")
// Assert
- expect(returnData).toBe("2021 Honda Civic");
+ expect(response.data).toEqual(["Windshield", "DriversFrontDoor"]);
});
- it("Should return vehicle image data from url retrieved", async () => {
+ it("resetVehicleAndDependencies action", async () => {
+
// Arrange
- let returnData = [];
+ const context = state;
+ const commit = jest.fn();
+
+ context.commit = commit;
// Act
- globalMethods.callMockHttpClient = jest.fn();
- globalMethods.callMockHttpClient.mockImplementation(() => {
- return Promise.resolve({
- data: {
- Result: "2008_honda_civic.jpg",
- },
- });
+ await actions.resetVehicleAndDependencies(context)
+
+ expect(commit).toBeCalledWith(storeMutations.RESET_VEHICLE_AND_DEPS);
+ expect(commit).toBeCalledWith(storeMutations.RESET_DAMAGE_AND_DEPS);
+ expect(commit).toBeCalledWith(storeMutations.RESET_REGISTRATION_AND_DEPS);
+
+ });
+
+ it("resetDamageAndDependencies action", async () => {
+
+ // Arrange
+ const context = state;
+ const commit = jest.fn();
+
+ context.commit = commit;
+
+ // Act
+ await actions.resetDamageAndDependencies(context)
+
+ expect(commit).toBeCalledWith(storeMutations.RESET_DAMAGE_AND_DEPS);
+ expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_AND_DEPS);
+
+ });
+
+ it("resetRegistrationAndDependencies action", async () => {
+
+ // Arrange
+ const context = state;
+ const commit = jest.fn();
+
+ context.commit = commit;
+
+ // Act
+ await actions.resetRegistrationAndDependencies(context)
+
+ expect(commit).toBeCalledWith(storeMutations.RESET_REGISTRATION_AND_DEPS);
+ expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_AND_DEPS);
+
+ });
+
+ it("resetPartsAndDependencies action", async () => {
+
+ // Arrange
+ const context = state;
+ const commit = jest.fn();
+
+ context.commit = commit;
+
+ // Act
+ await actions.resetPartsAndDependencies(context)
+
+ expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_AND_DEPS);
+
+ });
+
+ it("getRouteInfo action, returns route info", async () => {
+
+ // Arrange
+ const context = state;
+
+ globalMethods.callHttpClient.mockImplementation(() => {
+ return Promise.resolve({ data: { Widget: "Data" } });
});
- await store
- .dispatch("getEvoxImage", { relativeUrl: "evox_image.com"})
- .then((response) => {
- returnData = response.data.Result;
- });
- // Assert
- expect(returnData).toBe("2008_honda_civic.jpg");
- });
-});
-
-describe("Mutations", () => {
- it("Should update the year property in the store", () => {
// Act
- store.commit("updateYear", 2020);
+ const response = await actions.getRouteInfo(context, "vehicle-year")
+
+
+ expect(response.data).toEqual({ Widget: "Data" });
- // Assert
- expect(store.state.order.vehicle.year).toBe(2020);
});
- it("Should update the make property in the store", () => {
+ it("getHomepageName action, returns homepage name", async () => {
+
+ // Arrange
+ const context = state;
+
+ globalMethods.callHttpClient.mockImplementation(() => {
+ return Promise.resolve({ data: { Name: "vehicle-year" } });
+ });
+
// Act
- store.commit("updateMake", "Honda");
+ const response = await actions.getHomepageName(context)
+
+
+ expect(response.data).toEqual({ Name: "vehicle-year" });
- // Assert
- expect(store.state.order.vehicle.make).toBe("Honda");
});
- it("Should update the model property in the store", () => {
+ it("getPageData action, returns page data", async () => {
+
+ // Arrange
+ const context = state;
+
+ globalMethods.callHttpClient.mockImplementation(() => {
+ return Promise.resolve({ data: { Results: [{ Widget: "Data" }] } });
+ });
+
// Act
- store.commit("updateModel", "Civic");
+ const response = await actions.getPageData(context, "vehicle-year")
+
+
+ expect(response.data).toEqual({ Results: [{ Widget: "Data" }] });
- // Assert
- expect(store.state.order.vehicle.model).toBe("Civic");
});
- it("Should update the style property in the store", () => {
+ it("getEvoxImage action, returns image url", async () => {
+ // Arrange
+ const context = state;
+
+ globalMethods.callHttpClient.mockImplementation(() => {
+ return Promise.resolve({ data: { imageUrl: "https://test.com" } });
+ });
+
// Act
- store.commit("updateStyle", "2 Door");
+ const response = await actions.getEvoxImage(context, { relativeUrl: "https://relativeurl.com" });
- // Assert
- expect(store.state.order.vehicle.style).toBe("2 Door");
+
+ expect(response.data).toEqual({ imageUrl: "https://test.com" });
});
+
});
describe("Getters", () => {
- const vehicle = store.getters.vehicle;
+ it("Vehicle getter, should return vehicle data", () => {
+ // Arrange
+ const storeState = state;
- expect(typeof vehicle).toBe('object');
-});
+ // Act
+ mutations.updateYear(storeState, "2019");
+ mutations.updateMake(storeState, "Acura");
+ mutations.updateModel(storeState, "ILX");
+
+ // Assert
+ expect(getters.vehicle(storeState).year).toEqual("2019");
+ expect(getters.vehicle(storeState).make).toEqual("Acura");
+ expect(getters.vehicle(storeState).model).toEqual("ILX");
+
+ });
+
+ it("Get event bus item by event category and eventSubCategory", () => {
+ // Arrange
+ const storeState = state;
+ const event = { category: "CategoryOne", subCategory: "SubCategoryOne", eventValue: "EventValueOne" };
+
+ // Act
+ mutations.addEventToBus(storeState, event);
+
+ // Assert
+ //expect(storeState.applicationUser.eventBus).toEqual([event]);
+ expect(getters.eventBusItem(storeState)(event.category, event.subCategory)).toEqual(event.eventValue);
+
+ });
+
+ it("Get event bus", () => {
+ // Arrange
+ const storeState = state;
+ storeState.applicationUser.eventBus = [];
+
+ const event = { category: "CategoryOne", subCategory: "SubCategoryOne", eventValue: "EventValueOne" };
+
+ // Act
+ mutations.addEventToBus(storeState, event);
+
+ // Assert
+ expect(getters.eventBus(storeState)).toEqual([event]);
+
+ });
+
+});
\ No newline at end of file
diff --git a/src/styles/common-button-styles.scss b/src/styles/common-button-styles.scss
deleted file mode 100644
index abaf94879..000000000
--- a/src/styles/common-button-styles.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-//Custom button styles
-.btn {
- &.btn-primary {
- position: relative;
- background: $blue-700;
- @include blue-gradient;
- border: none;
- border-radius: $border-radius-lg;
- color: $white;
- transition: all 150ms linear;
- &:hover {
- background: linear-gradient(270deg, rgba(6,87,124,1) 0%, rgba(6,87,124,1) 100%);
- }
- &:focus, // Mouse, touch, stylus focus
- &:focus-visible { // Keyboard focus for accessibility
- outline: none;
- box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700;
- color: $white;
- @include blue-gradient;
- }
- &:disabled {
- background: $gray-100 !important;
- background: linear-gradient(270deg, $gray-100 0%, $gray-100 100%) !important;
- color: $gray !important;
- height: 48px;
- border: none;
- border-radius: $border-radius-lg;
- }
- }
- &.btn-secondary {
- position: relative;
- background: transparent;
- border: 1px solid $blue;
- border-radius: $border-radius-lg;
- color: $blue;
- transition: all 150ms linear;
- &:hover {
- color: $white;
- @include blue-gradient;
- }
- &:focus, // Mouse, touch, stylus focus
- &:focus-visible { // Keyboard focus for accessibility
- outline: none;
- box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $blue-700;
- color: $white;
- @include blue-gradient;
- }
- &:disabled {
- background: transparent;
- color: $gray !important;
- height: 48px;
- border: 1px solid $gray-300;
- border-radius: $border-radius-lg;
- }
- }
-}
diff --git a/src/styles/common-error-styles.scss b/src/styles/common-error-styles.scss
new file mode 100644
index 000000000..c2c6c3fea
--- /dev/null
+++ b/src/styles/common-error-styles.scss
@@ -0,0 +1,10 @@
+.has-error {
+ .list-button,
+ .list-card,
+ .list-button-horizontal {
+ color: $red;
+ label {
+ border: 1px solid $red;
+ }
+ }
+}
diff --git a/src/styles/common-list-styles.scss b/src/styles/common-list-styles.scss
deleted file mode 100644
index 375b560b0..000000000
--- a/src/styles/common-list-styles.scss
+++ /dev/null
@@ -1,38 +0,0 @@
-.list-group {
- &.list-button {
- input[type="radio"],
- input[type="checkbox"] {
- opacity: 0;
- position: fixed;
- width: 0;
- &:focus-visible + label {
- box-shadow: 0 0 0 2px $blue;
- }
- &:focus + label {
- box-shadow: 0 0 0 2px $blue;
- }
- &:checked + label {
- background: $blue-100;
- box-shadow: 0 0 0 1px $blue;
- }
- &:checked + label p:first-child {
- font-weight: 500;
- }
- }
- label {
- position: relative;
- background: $white;
- transition: all 150ms linear;
- border-radius: $border-radius-lg;
- border: 1px solid $gray-500;
- width: 100%;
- &:hover {
- box-shadow: 0 0 0 4px $blue-100;
- cursor: pointer;
- }
- + p {
- display: none;
- }
- }
- }
-}
diff --git a/src/styles/common-styles.scss b/src/styles/common-styles.scss
index 5e1993716..a4915049b 100644
--- a/src/styles/common-styles.scss
+++ b/src/styles/common-styles.scss
@@ -10,14 +10,6 @@ body {
box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.15); //Use instead of Bootstrap's helper
}
}
- a {
- color: $blue;
- text-decoration: none;
- border-bottom: 1px solid $blue;
- &:hover {
- color: $blue-400;
- }
- }
.pointer {
cursor: pointer;
}
diff --git a/src/ux-components/button-main/button-main.spec.js b/src/ux-components/button-main/button-main.spec.js
new file mode 100644
index 000000000..bbdbbe134
--- /dev/null
+++ b/src/ux-components/button-main/button-main.spec.js
@@ -0,0 +1,101 @@
+import { shallowMount } from "@vue/test-utils";
+import buttonMain from "./button-main";
+import { nextTick } from "vue";
+
+describe("buttonMain.vue", () => {
+ it("Should return btn-primary class", async () => {
+ // Act
+ const wrapper = shallowMount(buttonMain, {
+ propsData: {
+ isPrimary: true,
+ },
+ });
+
+ // Assert
+ const button = wrapper.find("button");
+
+ // Expect
+ expect(button.attributes("class")).toContain("btn-primary");
+ });
+
+ it("Should return aria-disabled state", async () => {
+ // Act
+ const wrapper = shallowMount(buttonMain, {
+ propsData: {
+ isDisabled: true,
+ },
+ });
+
+ // Assert
+ const button = wrapper.find("button");
+
+ // Expect
+ expect(button.attributes()["aria-disabled"]).toEqual("true");
+ });
+
+ it("Should return loader color", async () => {
+ // Act
+ const wrapper = shallowMount(buttonMain, {
+ propsData: {
+ loaderColor: "blue",
+ loaderEnabled: true,
+ },
+ });
+
+ // Assert
+
+ const label = wrapper.find("label");
+
+ wrapper.vm.clicked();
+
+ await nextTick();
+
+ const loader = wrapper.find("loader-stub");
+
+ expect(loader.attributes("class")).toContain("blue");
+ });
+
+ it("Should return loader position", async () => {
+ // Act
+ const wrapper = shallowMount(buttonMain, {
+ propsData: {
+ loaderPosition: "right",
+ loaderEnabled: true,
+ },
+ });
+
+ // Assert
+
+ const label = wrapper.find("label");
+
+ wrapper.vm.clicked();
+
+ await nextTick();
+
+ const loader = wrapper.find("loader-stub");
+
+ expect(loader.attributes("class")).toContain("right");
+ });
+
+ it("Should return loader size in rem", async () => {
+ // Act
+ const wrapper = shallowMount(buttonMain, {
+ propsData: {
+ sizeInRem: 1,
+ loaderEnabled: true,
+ },
+ });
+
+ // Assert
+
+ const label = wrapper.find("label");
+
+ wrapper.vm.clicked();
+
+ await nextTick();
+
+ const loader = wrapper.find("loader-stub");
+
+ expect(loader.attributes("style")).toContain("1rem");
+ });
+});
diff --git a/src/ux-components/button-main/button-main.vue b/src/ux-components/button-main/button-main.vue
new file mode 100644
index 000000000..e44550c30
--- /dev/null
+++ b/src/ux-components/button-main/button-main.vue
@@ -0,0 +1,110 @@
+
+
+ {{ this.buttonText }}
+
+
+
+
+
+
+
diff --git a/src/ux-components/button-primary/button-primary.spec.js b/src/ux-components/button-primary/button-primary.spec.js
deleted file mode 100644
index 3d0843e10..000000000
--- a/src/ux-components/button-primary/button-primary.spec.js
+++ /dev/null
@@ -1 +0,0 @@
-test.todo("some test to be written in the future");
diff --git a/src/ux-components/button-primary/button-primary.vue b/src/ux-components/button-primary/button-primary.vue
deleted file mode 100644
index ca0cc8505..000000000
--- a/src/ux-components/button-primary/button-primary.vue
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
- {{ this.buttonText }}
-
-
-
-
-
diff --git a/src/ux-components/button-secondary/button-secondary.spec.js b/src/ux-components/button-secondary/button-secondary.spec.js
deleted file mode 100644
index 3d0843e10..000000000
--- a/src/ux-components/button-secondary/button-secondary.spec.js
+++ /dev/null
@@ -1 +0,0 @@
-test.todo("some test to be written in the future");
diff --git a/src/ux-components/button-secondary/button-secondary.vue b/src/ux-components/button-secondary/button-secondary.vue
deleted file mode 100644
index ec4d7ec0c..000000000
--- a/src/ux-components/button-secondary/button-secondary.vue
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
- {{ this.buttonText }}
-
-
-
-
-
diff --git a/src/ux-components/checkbox/checkbox.spec.js b/src/ux-components/checkbox/checkbox.spec.js
index 3d0843e10..ab3c29e41 100644
--- a/src/ux-components/checkbox/checkbox.spec.js
+++ b/src/ux-components/checkbox/checkbox.spec.js
@@ -1 +1,78 @@
-test.todo("some test to be written in the future");
+import { shallowMount } from "@vue/test-utils";
+import checkbox from "./checkbox";
+import { nextTick } from "vue";
+
+describe("checkbox.vue", () => {
+ it("Should return checkbox name", async () => {
+ // Act
+ const wrapper = shallowMount(checkbox, {
+ propsData: {
+ checkboxName: "Checkbox",
+ },
+ });
+
+ // Assert
+ const input = wrapper.find("input");
+
+ // Expect
+ expect(input.attributes().name).toEqual("Checkbox");
+ });
+
+ it("Should return checkbox id", async () => {
+ // Act
+ const wrapper = shallowMount(checkbox, {
+ propsData: {
+ buttonID: "Checkbox ID",
+ },
+ });
+
+ // Assert
+ const input = wrapper.find("input");
+
+ // Expect
+ expect(input.attributes().id).toEqual("Checkbox ID");
+ });
+
+ it("Should return tabindex value", async () => {
+ // Act
+ const wrapper = shallowMount(checkbox, {
+ propsData: {
+ tabIndex: "1",
+ },
+ });
+
+ // Assert
+ const input = wrapper.find("input");
+
+ // Expect
+ expect(input.attributes().tabindex).toEqual("1");
+ });
+
+ it("Should return label text", async () => {
+ // Act
+ const wrapper = shallowMount(checkbox, {
+ propsData: {
+ checkboxLabel: "label text",
+ },
+ });
+
+ // Assert
+ const paragraph = wrapper.find("p");
+
+ expect(paragraph.text()).toEqual("label text");
+ });
+
+ it("Should return label text", async () => {
+ // Act
+ const wrapper = shallowMount(checkbox, {
+ propsData: {
+ screenReaderOnlyText: "screenreader text",
+ },
+ });
+
+ // Assert
+ const paragraph = wrapper.find("span");
+
+ expect(paragraph.text()).toEqual("screenreader text");
+ });
+});
diff --git a/src/ux-components/checkbox/checkbox.vue b/src/ux-components/checkbox/checkbox.vue
index 1b6254d29..dca64e689 100644
--- a/src/ux-components/checkbox/checkbox.vue
+++ b/src/ux-components/checkbox/checkbox.vue
@@ -1,10 +1,19 @@
@@ -18,15 +27,15 @@ export default {
tabIndex: Number,
checkboxLabel: String,
screenReaderOnlyText: String,
- isRequired: Boolean
- }
+ isRequired: Boolean,
+ },
};
diff --git a/src/ux-components/list-card/list-card.spec.js b/src/ux-components/list-card/list-card.spec.js
index 8438e01b9..30af40ec3 100644
--- a/src/ux-components/list-card/list-card.spec.js
+++ b/src/ux-components/list-card/list-card.spec.js
@@ -2,7 +2,6 @@ import { shallowMount } from "@vue/test-utils";
import listCard from "./list-card";
describe("list-card.vue", () => {
-
it("Should return input type checkbox if isMultiSelect is true", async () => {
// Act
const wrapper = shallowMount(listCard, {
@@ -13,6 +12,7 @@ describe("list-card.vue", () => {
groupID: "checkbox-demo-1",
groupName: "Checkbox 1",
buttonImage: "windshield-damage.svg",
+ modelValue: ["List Card Checkbox"],
},
});
@@ -22,65 +22,6 @@ describe("list-card.vue", () => {
expect(input.attributes().type).toEqual("checkbox");
});
- it("Should return input type radio if isRadio is true", async () => {
- // Act
- const wrapper = shallowMount(listCard, {
- propsData: {
- isRadio: true,
- buttonLabel: "Windshield",
- buttonID: "List Card Checkbox",
- groupID: "radio-demo-1",
- groupName: "radio 1",
- buttonImage: "windshield-damage.svg",
- },
- });
-
- // Assert
- const input = wrapper.find("input");
-
- expect(input.attributes().type).toEqual("radio");
- });
-
- it("Should return input type checkbox if isMultiSelectHorizontal is true", async () => {
- // Act
- const wrapper = shallowMount(listCard, {
- propsData: {
- isMultiSelectHorizontal: true,
- buttonLabel: "Windshield",
- buttonID: "List Card Checkbox",
- groupID: "radio-demo-1",
- groupName: "radio 1",
- buttonImage: "windshield-damage.svg"
- },
- });
-
- // Assert
- const input = wrapper.find("input");
-
- expect(input.attributes().type).toEqual("checkbox");
-
- });
-
- it("Should return input type radio if isRadioHorizontal is true", async () => {
- // Act
- const wrapper = shallowMount(listCard, {
- propsData: {
- isRadioHorizontal: true,
- buttonLabel: "Windshield",
- buttonID: "List Card Checkbox",
- groupID: "radio-demo-1",
- groupName: "radio 1",
- buttonImage: "windshield-damage.svg"
- },
- });
-
- // Assert
- const input = wrapper.find("input");
-
- expect(input.attributes().type).toEqual("radio");
-
- });
-
it("Should return primary label text", async () => {
// Act
const wrapper = shallowMount(listCard, {
@@ -90,7 +31,8 @@ describe("list-card.vue", () => {
buttonID: "List Card Checkbox",
groupID: "radio-demo-1",
groupName: "radio 1",
- buttonImage: "windshield-damage.svg"
+ buttonImage: "windshield-damage.svg",
+ modelValue: ["List Card Checkbox"],
},
});
@@ -98,7 +40,6 @@ describe("list-card.vue", () => {
const paragraph = wrapper.find("p");
expect(paragraph.text()).toEqual("Windshield");
-
});
it("Should return secondary (sub) label text", async () => {
@@ -111,7 +52,8 @@ describe("list-card.vue", () => {
groupID: "radio-demo-1",
groupName: "radio 1",
buttonImage: "windshield-damage.svg",
- buttonLabelSubCopy: "Test"
+ buttonLabelSubCopy: "Test",
+ modelValue: ["List Card Checkbox"],
},
});
@@ -119,7 +61,6 @@ describe("list-card.vue", () => {
const paragraph = wrapper.find("p:nth-of-type(2)");
expect(paragraph.text()).toEqual("Test");
-
});
it("Should return value used for various text settings including the label 'for' and input id", async () => {
@@ -132,7 +73,8 @@ describe("list-card.vue", () => {
groupID: "radio-demo-1",
groupName: "radio 1",
buttonImage: "windshield-damage.svg",
- buttonLabelSubCopy: "Test"
+ buttonLabelSubCopy: "Test",
+ modelValue: ["List Card Checkbox"],
},
});
@@ -140,7 +82,6 @@ describe("list-card.vue", () => {
const label = wrapper.find("label");
expect(label.attributes().for).toEqual("List Card Checkbox");
-
});
it("Should return input group name used for radio or checkbox", async () => {
@@ -153,7 +94,8 @@ describe("list-card.vue", () => {
groupID: "radio-demo-1",
groupName: "radio 1",
buttonImage: "windshield-damage.svg",
- buttonLabelSubCopy: "Test"
+ buttonLabelSubCopy: "Test",
+ modelValue: ["List Card Checkbox"],
},
});
@@ -161,7 +103,6 @@ describe("list-card.vue", () => {
const input = wrapper.find("input");
expect(input.attributes().name).toEqual("radio 1");
-
});
it("Should return aria-required state", async () => {
@@ -174,7 +115,8 @@ describe("list-card.vue", () => {
groupID: "radio-demo-1",
groupName: "radio 1",
buttonImage: "windshield-damage.svg",
- isRequired: true
+ isRequired: true,
+ modelValue: ["List Card Checkbox"],
},
});
@@ -182,7 +124,112 @@ describe("list-card.vue", () => {
const input = wrapper.find("input");
expect(input.attributes()["aria-required"]).toEqual("true");
-
});
+ it("Should return flex row classes if isWide is true", async () => {
+ // Act
+ const wrapper = shallowMount(listCard, {
+ propsData: {
+ isRadioHorizontal: true,
+ buttonLabel: "Windshield",
+ buttonID: "List Card Checkbox",
+ groupID: "radio-demo-1",
+ groupName: "radio 1",
+ buttonImage: "windshield-damage.svg",
+ isRequired: true,
+ isWide: true,
+ buttonLabelSubCopy: "",
+ modelValue: ["List Card Checkbox"],
+ },
+ });
+
+ // Assert
+ const label = wrapper.find("label");
+ expect(label.classes()).toEqual(["d-flex", "w-100", "align-items-center", "px-2", "h-100", "flex-row", "py-r", "ps-3", "pe-8"]);
+ });
+
+ it("Should return flex row classes if isWide is true and checkboxTop if buttonLabelSubCopy is true", async () => {
+ // Act
+ const wrapper = shallowMount(listCard, {
+ propsData: {
+ isRadioHorizontal: true,
+ buttonLabel: "Windshield",
+ buttonID: "List Card Checkbox",
+ groupID: "radio-demo-1",
+ groupName: "radio 1",
+ buttonImage: "windshield-damage.svg",
+ isRequired: true,
+ isWide: true,
+ buttonLabelSubCopy: "Button Subcopy",
+ modelValue: ["List Card Checkbox"],
+ },
+ });
+
+ // Assert
+ const label = wrapper.find("label");
+ expect(label.classes()).toEqual(["d-flex", "w-100", "align-items-center", "px-2", "h-100", "flex-row", "py-r", "ps-3", "pe-8", "checkboxTop"]);
+ });
+
+ it("Should return flex column classes if isWide is false", async () => {
+ // Act
+ const wrapper = shallowMount(listCard, {
+ propsData: {
+ isRadioHorizontal: true,
+ buttonLabel: "Windshield",
+ buttonID: "List Card Checkbox",
+ groupID: "radio-demo-1",
+ groupName: "radio 1",
+ buttonImage: "windshield-damage.svg",
+ isRequired: true,
+ isWide: false,
+ modelValue: ["List Card Checkbox"],
+ },
+ });
+
+ // Assert
+ const label = wrapper.find("label");
+ expect(label.classes()).toEqual(["d-flex", "w-100", "align-items-center", "px-2", "h-100", "flex-column", "pt-4", "pb-2"]);
+ });
+
+ it("Should emit button value on click", async () => {
+ // Act
+ const wrapper = shallowMount(listCard, {
+ propsData: {
+ isRadioHorizontal: true,
+ buttonLabel: "Windshield",
+ buttonID: "List Card Checkbox",
+ groupID: "radio-demo-1",
+ groupName: "radio 1",
+ buttonImage: "windshield-damage.svg",
+ isRequired: true,
+ isWide: false,
+ modelValue: ["List Card Checkbox"],
+ },
+ });
+ wrapper.vm.handleCheckChange();
+ // Assert
+ expect(wrapper.emitted()["isCheckedChanged"][0]).toEqual([{buttonId: "List Card Checkbox", isChecked: Boolean}]);
+ });
+
+ it("Should set checkValue data if selectedButtonIDs has value(s)", async () => {
+ // Act
+ const wrapper = shallowMount(listCard, {
+ propsData: {
+ isRadioHorizontal: true,
+ buttonLabel: "Windshield",
+ buttonID: "List Card Checkbox",
+ groupID: "radio-demo-1",
+ groupName: "radio 1",
+ buttonImage: "windshield-damage.svg",
+ isRequired: true,
+ isWide: false,
+ modelValue: ["List Card Checkbox"],
+ selectedButtonIDs: ["Car-Front"]
+ },
+ });
+ // Assert
+ expect(wrapper.componentVM.checkValue).toEqual("Car-Front");
+ });
+
+
});
diff --git a/src/ux-components/list-card/list-card.vue b/src/ux-components/list-card/list-card.vue
index 68b1c80b0..caba00d0a 100644
--- a/src/ux-components/list-card/list-card.vue
+++ b/src/ux-components/list-card/list-card.vue
@@ -1,99 +1,164 @@
-
-
-
-
-
- {{buttonLabel}}
- {{buttonLabelSubCopy}}
-
-
-
-
-
-
- {{buttonLabel}}
- {{buttonLabelSubCopy}}
-
-
-
-
-
-
-
-
{{buttonLabel}}
-
{{buttonLabelSubCopy}}
-
-
-
-
-
-
-
-
-
{{buttonLabel}}
-
{{buttonLabelSubCopy}}
-
-
+
+
+
+
+
+
+ {{buttonLabel}}
+
+
+ {{buttonLabelSubCopy}}
+
+
+
{{ buttonLabel }}
+
+ {{ buttonLabelSubCopy }}
+
+
+
+
diff --git a/vue.config.js b/vue.config.js
index 9d9b2401b..316656ed1 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -8,17 +8,13 @@ module.exports = {
loaderOptions: {
sass: {
// Load Order Matters!!!
+ // Note: only include functions, variables and mixins here
prependData: `
@import "./node_modules/bootstrap/scss/functions";
@import "@/styles/ux-variables.scss";
@import "./node_modules/bootstrap/scss/variables";
@import "./node_modules/bootstrap/scss/mixins";
@import "@/styles/mixins/customMixins";
- @import "./node_modules/bootstrap/scss/bootstrap";
- @import "@/styles/common-styles.scss";
- @import "@/styles/common-button-styles.scss";
- @import "@/styles/common-list-styles.scss";
- @import "@/styles/common-typography-styles.scss";
`,
},
},
diff --git a/vue.release.config.js b/vue.release.config.js
index c4b18d5dd..43fffb47f 100644
--- a/vue.release.config.js
+++ b/vue.release.config.js
@@ -7,17 +7,13 @@ module.exports = {
loaderOptions: {
sass: {
// Load Order Matters!!!
+ // Note: only include functions, variables and mixins here
prependData: `
@import "./node_modules/bootstrap/scss/functions";
@import "@/styles/ux-variables.scss";
@import "./node_modules/bootstrap/scss/variables";
@import "./node_modules/bootstrap/scss/mixins";
- @import "@/styles/mixins/customMixins";
- @import "./node_modules/bootstrap/scss/bootstrap";
- @import "@/styles/common-styles.scss";
- @import "@/styles/common-button-styles.scss";
- @import "@/styles/common-list-styles.scss";
- @import "@/styles/common-typography-styles.scss";
+ @import "@/styles/mixins/customMixins";
`,
},
},