Merge pull request #52 from Safelite/feature/CSR-6
Multiple refactors / cleaner code
This commit is contained in:
commit
9bd0ae4fd1
77 changed files with 1037 additions and 1093 deletions
|
|
@ -1,9 +1,21 @@
|
|||
module.exports = {
|
||||
verbose: true,
|
||||
coverageReporters: ["html", "text", "jest-junit"],
|
||||
preset: "@vue/cli-plugin-unit-jest",
|
||||
transform: {
|
||||
"^.+\\.vue$": "vue-jest",
|
||||
transform: { "^.+\\.vue$": "vue-jest" },
|
||||
moduleFileExtensions: ["js", "vue"],
|
||||
collectCoverageFrom: [
|
||||
"src/**/*.{js,vue}",
|
||||
"!src/main.js",
|
||||
"!src/constants/*.js",
|
||||
"!src/router/**/*.js",
|
||||
"!src/helpers/unit-test-helper.js",
|
||||
"!src/layouts/component-test/component-test.vue"
|
||||
], //! means exclude from coverage.
|
||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
statements: 60,
|
||||
},
|
||||
},
|
||||
testMatch : [
|
||||
"**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
|
||||
],
|
||||
};
|
||||
|
|
|
|||
104
package-lock.json
generated
104
package-lock.json
generated
|
|
@ -14,6 +14,7 @@
|
|||
"canvas-confetti": "^1.4.0",
|
||||
"core-js": "^3.6.5",
|
||||
"http-status-codes": "^2.1.4",
|
||||
"jest-junit": "^13.0.0",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.11",
|
||||
"vuex": "^4.0.2",
|
||||
|
|
@ -10957,6 +10958,58 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-junit": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-13.0.0.tgz",
|
||||
"integrity": "sha512-JSHR+Dhb32FGJaiKkqsB7AR3OqWKtldLd6ZH2+FJ8D4tsweb8Id8zEVReU4+OlrRO1ZluqJLQEETm+Q6/KilBg==",
|
||||
"dependencies": {
|
||||
"mkdirp": "^1.0.4",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"uuid": "^8.3.2",
|
||||
"xml": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-junit/node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-junit/node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-junit/node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-junit/node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-leak-detector": {
|
||||
"version": "24.9.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz",
|
||||
|
|
@ -11690,6 +11743,9 @@
|
|||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
|
|
@ -17947,6 +18003,7 @@
|
|||
"integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chokidar": "^3.4.1",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"neo-async": "^2.5.0"
|
||||
},
|
||||
|
|
@ -18010,6 +18067,7 @@
|
|||
"anymatch": "^2.0.0",
|
||||
"async-each": "^1.0.1",
|
||||
"braces": "^2.3.2",
|
||||
"fsevents": "^1.2.7",
|
||||
"glob-parent": "^3.1.0",
|
||||
"inherits": "^2.0.3",
|
||||
"is-binary-path": "^1.0.0",
|
||||
|
|
@ -18921,6 +18979,11 @@
|
|||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xml": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
|
||||
"integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU="
|
||||
},
|
||||
"node_modules/xml-name-validator": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
|
||||
|
|
@ -27805,6 +27868,42 @@
|
|||
"throat": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"jest-junit": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-13.0.0.tgz",
|
||||
"integrity": "sha512-JSHR+Dhb32FGJaiKkqsB7AR3OqWKtldLd6ZH2+FJ8D4tsweb8Id8zEVReU4+OlrRO1ZluqJLQEETm+Q6/KilBg==",
|
||||
"requires": {
|
||||
"mkdirp": "^1.0.4",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"uuid": "^8.3.2",
|
||||
"xml": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"jest-leak-detector": {
|
||||
"version": "24.9.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz",
|
||||
|
|
@ -34352,6 +34451,11 @@
|
|||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"xml": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
|
||||
"integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU="
|
||||
},
|
||||
"xml-name-validator": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"test:unit": "vue-cli-service test:unit",
|
||||
"test:unit": "vue-cli-service test:unit --coverage --ci",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"jest-junit": "^13.0.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-unit-jest": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
26
src/common-components/radio-question/radio-question.spec.js
Normal file
26
src/common-components/radio-question/radio-question.spec.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import radioQuestion from "@/common-components/radio-question/radio-question";
|
||||
|
||||
describe("radioQuestion.vue", () => {
|
||||
it("Should render the 'questionText' prop value as a span value for the radio question and the 'answer' values should render as text values for radio components.", () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(radioQuestion, {
|
||||
propsData: {
|
||||
questionText: "Question Text",
|
||||
answers: ["2023", "2022", "2021"],
|
||||
chooseAnswer: function (test) {
|
||||
console.log(test);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find(".needed_car_info-text").text()).toEqual(
|
||||
"Question Text"
|
||||
);
|
||||
const radioButtons = wrapper.findAllComponents('[data-test="radio"]');
|
||||
expect(radioButtons[0].attributes("text")).toEqual("2023");
|
||||
expect(radioButtons[2].attributes("text")).toEqual("2021");
|
||||
expect(typeof wrapper.props().chooseAnswer).toBe("function");
|
||||
});
|
||||
});
|
||||
34
src/common-components/radio-question/radio-question.vue
Normal file
34
src/common-components/radio-question/radio-question.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<template>
|
||||
<div class="radio_question">
|
||||
<div class="needed_car_info d-flex mt-4 mb-3">
|
||||
<span class="text-center fs-6 fw-bold w-100 needed_car_info-text">{{
|
||||
questionText
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="car_list overflow-scroll position-absolute">
|
||||
<div v-for="answer in answers" :key="answer" class="mb-2">
|
||||
<radio
|
||||
:text="answer"
|
||||
:value="answer"
|
||||
@click="chooseAnswer(answer)"
|
||||
data-test="radio"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radio from "@/ux-components/radio/radio";
|
||||
export default {
|
||||
name: "radio-question",
|
||||
props: {
|
||||
questionText: String,
|
||||
answers: Array,
|
||||
chooseAnswer: Function,
|
||||
},
|
||||
components: {
|
||||
radio,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import radioQuestion from './radioQuestion';
|
||||
|
||||
describe('radioQuestion.vue', () => {
|
||||
it("Should render the 'questionText' prop value as a span value for the radio question and the 'answer' values should render as text values for radio components.", () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(radioQuestion, {
|
||||
propsData: {
|
||||
questionText: 'Question Text',
|
||||
answers: ['2023', '2022', '2021'],
|
||||
chooseAnswer: function(test){ console.log(test) }
|
||||
}
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find('.needed_car_info-text').text()).toEqual('Question Text');
|
||||
const radioButtons = wrapper.findAllComponents('[data-test="radio"]');
|
||||
expect(radioButtons[0].attributes('text')).toEqual('2023');
|
||||
expect(radioButtons[2].attributes('text')).toEqual('2021');
|
||||
expect(typeof wrapper.props().chooseAnswer).toBe('function');
|
||||
})
|
||||
})
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<template>
|
||||
<div class="radio_question">
|
||||
<div class="needed_car_info d-flex mt-4 mb-3">
|
||||
<span class="text-center fs-6 fw-bold w-100 needed_car_info-text">{{ questionText }}</span>
|
||||
</div>
|
||||
<div class="car_list overflow-scroll position-absolute">
|
||||
<div v-for="answer in answers" :key="answer" class="mb-2">
|
||||
<radio :text="answer" :value="answer" @click="chooseAnswer(answer)" data-test="radio" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radio from "@/uxComponents/radio/radio";
|
||||
export default {
|
||||
name: "radio-question",
|
||||
props: {
|
||||
questionText: String,
|
||||
answers: Array,
|
||||
chooseAnswer: Function
|
||||
},
|
||||
components: {
|
||||
radio
|
||||
}
|
||||
};
|
||||
</script>
|
||||
5
src/constants/application-config.js
Normal file
5
src/constants/application-config.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
const applicationConfig = {
|
||||
CONSUMER_APIGATEWAY_URL: process.env.VUE_APP_CONSUMER_API_GATEWAY,
|
||||
};
|
||||
|
||||
export { applicationConfig };
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
const applicationConfig = {
|
||||
CONSUMER_APIGATEWAY_URL: process.env.VUE_APP_CONSUMER_API_GATEWAY
|
||||
}
|
||||
|
||||
export { applicationConfig }
|
||||
|
|
@ -1,27 +1,28 @@
|
|||
const endpoints = {
|
||||
GetRouteInfoEndpoint: {
|
||||
url: '/content/api/v1/content/RouteInfo',
|
||||
method: 'POST'
|
||||
},
|
||||
GetYears: {
|
||||
url: '/vehicle/api/v1/vehicle/years',
|
||||
method: 'GET'
|
||||
},
|
||||
GetMakes: {
|
||||
url: '/vehicle/api/v1/vehicle/Makes',
|
||||
method: 'POST'
|
||||
},
|
||||
GetModels: {
|
||||
url: '/vehicle/api/v1/vehicle/Models',
|
||||
method: 'POST'
|
||||
},
|
||||
GetStyles: {
|
||||
url: '/vehicle/api/v1/vehicle/Styles',
|
||||
method: 'POST'
|
||||
},
|
||||
GetPageData: {
|
||||
method: 'GET'
|
||||
}
|
||||
}
|
||||
GetRouteInfo: {
|
||||
url: "/content/api/v1/content/RouteInfo",
|
||||
method: "POST",
|
||||
},
|
||||
GetVehicleYears: {
|
||||
url: "/vehicle/api/v1/vehicle/years",
|
||||
method: "GET",
|
||||
},
|
||||
GetVehicleMakes: {
|
||||
url: "/vehicle/api/v1/vehicle/Makes",
|
||||
method: "GET",
|
||||
},
|
||||
GetVehicleModels: {
|
||||
url: "/vehicle/api/v1/vehicle/Models",
|
||||
method: "GET",
|
||||
},
|
||||
GetVehicleStyles: {
|
||||
url: "/vehicle/api/v1/vehicle/Styles",
|
||||
method: "GET",
|
||||
},
|
||||
GetPageData: {
|
||||
url: "/content/api/v1/content",
|
||||
method: "GET",
|
||||
},
|
||||
};
|
||||
|
||||
export { endpoints }
|
||||
export { endpoints };
|
||||
|
|
|
|||
10
src/constants/store-actions.js
Normal file
10
src/constants/store-actions.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
const storeActions = {
|
||||
GET_ROUTE_INFO_ACTION: "getRouteInfo",
|
||||
GET_PAGE_DATA: "getPageData",
|
||||
GET_VEHICLE_YEARS: "getVehicleYears",
|
||||
GET_VEHICLE_MAKES: "getVehicleMakes",
|
||||
GET_VEHICLE_MODELS: "getVehicleModels",
|
||||
GET_VEHICLE_STYLES: "getVehicleStyles",
|
||||
};
|
||||
|
||||
export { storeActions };
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
const storeActions = {
|
||||
GET_ROUTE_INFO_ACTION: "getRouteInfo",
|
||||
GET_YEARS: 'getYears',
|
||||
GET_PAGE_DATA: 'getMockPageData',
|
||||
}
|
||||
|
||||
export { storeActions }
|
||||
6
src/constants/widget-names.js
Normal file
6
src/constants/widget-names.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
const widgetNames = {
|
||||
PAGE_HEADER_WIDGET: "PageHeaderWidget",
|
||||
RADIO_QUESTION_WIDGET: "RadioQuestionWidget",
|
||||
};
|
||||
|
||||
export { widgetNames };
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
const widgetNames = {
|
||||
PAGE_HEADING_WIDGET: "PageHeadingWidget",
|
||||
RADIO_QUESTION_WIDGET: "RadioQuestionWidget"
|
||||
}
|
||||
|
||||
export { widgetNames }
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
import axios from "axios";
|
||||
import { applicationConfig } from "@/constants/applicationConfig.js";
|
||||
import { applicationConfig } from "@/constants/application-config.js";
|
||||
import httpStatusCodes from "http-status-codes";
|
||||
|
||||
export default {
|
||||
callHttpClient({ method, endpoint, payload}) {
|
||||
callHttpClient({ method, endpoint, payload }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
const apiGatewayUrl = applicationConfig.CONSUMER_APIGATEWAY_URL;
|
||||
const payloadAndAnalyticsData = Object.assign({}, payload, {AppName: "FixMyGlass"});
|
||||
const payloadAndAnalyticsData = Object.assign({}, payload, {
|
||||
AppName: "FixMyGlass",
|
||||
});
|
||||
|
||||
axios({
|
||||
method: method,
|
||||
|
|
@ -15,8 +16,8 @@ export default {
|
|||
data: payloadAndAnalyticsData,
|
||||
crossDomain: true,
|
||||
responseType: {},
|
||||
}).then((response) => {
|
||||
|
||||
}).then(
|
||||
(response) => {
|
||||
if (response.status == httpStatusCodes.OK) {
|
||||
resolve(response);
|
||||
} else {
|
||||
|
|
@ -30,19 +31,17 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
|
||||
/* istanbul ignore next */
|
||||
callMockHttpClient({ method, endpoint}) {
|
||||
callMockHttpClient({ method, endpoint }) {
|
||||
// For Mock use only!
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
axios({
|
||||
method: method,
|
||||
url: endpoint,
|
||||
crossDomain: true,
|
||||
responseType: {},
|
||||
}).then((response) => {
|
||||
|
||||
}).then(
|
||||
(response) => {
|
||||
if (response.status == httpStatusCodes.OK) {
|
||||
resolve(response);
|
||||
} else {
|
||||
|
|
@ -54,5 +53,5 @@ export default {
|
|||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,73 +1,76 @@
|
|||
import globalMethods from "@/global-methods";
|
||||
import axios from 'axios';
|
||||
import axios from "axios";
|
||||
|
||||
//Mock external dependencies
|
||||
jest.mock('axios');
|
||||
jest.mock("axios");
|
||||
|
||||
it("Global Methods - Call Http Client - Should Resolve Promise", () => {
|
||||
//Arrange
|
||||
const endpoint = 'https://mock.safelite.com';
|
||||
const httpArgs = setupMocksForHttpClient({ endpoint: endpoint });
|
||||
//Arrange
|
||||
const endpoint = "https://mock.safelite.com";
|
||||
const httpArgs = setupMocksForHttpClient({ endpoint: endpoint });
|
||||
|
||||
//Act
|
||||
globalMethods.callHttpClient(httpArgs)
|
||||
.then((response) => {
|
||||
|
||||
//Assert
|
||||
expect(axios.mock.calls[0][0].url).toContain(endpoint);
|
||||
expect(response.data.message).toContain('Success');
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
//Act
|
||||
globalMethods.callHttpClient(httpArgs).then((response) => {
|
||||
//Assert
|
||||
expect(axios.mock.calls[0][0].url).toContain(endpoint);
|
||||
expect(response.data.message).toContain("Success");
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
});
|
||||
|
||||
it("Global Methods - Call Http Client - Should Reject Promise", () => {
|
||||
//Arrange
|
||||
const endpoint = 'https://mock.safelite.com';
|
||||
const httpArgs = setupMocksForHttpClient({ endpoint: endpoint, isError: true });
|
||||
//Arrange
|
||||
const endpoint = "https://mock.safelite.com";
|
||||
const httpArgs = setupMocksForHttpClient({
|
||||
endpoint: endpoint,
|
||||
isError: true,
|
||||
});
|
||||
|
||||
//Act
|
||||
globalMethods.callHttpClient(httpArgs)
|
||||
.catch((err) => {
|
||||
//Assert
|
||||
expect(axios.mock.calls[0][0].url).toContain(endpoint);
|
||||
expect(err.data.message).toContain('Error');
|
||||
expect(err.status).toEqual(500);
|
||||
});
|
||||
//Act
|
||||
globalMethods.callHttpClient(httpArgs).catch((err) => {
|
||||
//Assert
|
||||
expect(axios.mock.calls[0][0].url).toContain(endpoint);
|
||||
expect(err.data.message).toContain("Error");
|
||||
expect(err.status).toEqual(500);
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocksForHttpClient({ endpoint = null, isError = false, additionalData = null }) {
|
||||
function setupMocksForHttpClient({
|
||||
endpoint = null,
|
||||
isError = false,
|
||||
additionalData = null,
|
||||
}) {
|
||||
//Clear node module
|
||||
axios.mockClear();
|
||||
|
||||
//Clear node module
|
||||
axios.mockClear();
|
||||
// Success Response
|
||||
const response = {
|
||||
status: 200,
|
||||
data: {
|
||||
message: "Success",
|
||||
additionalData: additionalData,
|
||||
},
|
||||
};
|
||||
|
||||
// Success Response
|
||||
const response = {
|
||||
status: 200,
|
||||
data: {
|
||||
message: 'Success',
|
||||
additionalData: additionalData
|
||||
}
|
||||
};
|
||||
// Error Response
|
||||
const error = {
|
||||
response: {
|
||||
status: 500,
|
||||
data: {
|
||||
message: "Error",
|
||||
additionalData: additionalData,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Error Response
|
||||
const error = {
|
||||
response: {
|
||||
status: 500,
|
||||
data: {
|
||||
message: 'Error',
|
||||
additionalData: additionalData
|
||||
}
|
||||
}
|
||||
}
|
||||
// Error interceptor on Axios returns a different object, so we need to mimic that.
|
||||
if (isError) {
|
||||
axios.mockRejectedValue(error);
|
||||
} else {
|
||||
axios.mockResolvedValue(response);
|
||||
}
|
||||
|
||||
// Error interceptor on Axios returns a different object, so we need to mimic that.
|
||||
if (isError) {
|
||||
axios.mockRejectedValue(error);
|
||||
} else {
|
||||
axios.mockResolvedValue(response);
|
||||
}
|
||||
|
||||
return {
|
||||
endpoint: endpoint
|
||||
}
|
||||
}
|
||||
return {
|
||||
endpoint: endpoint,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
36
src/helpers/unit-test-helper.js
Normal file
36
src/helpers/unit-test-helper.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import { storeActions } from "@/constants/store-actions";
|
||||
|
||||
export function getMountOptions(mockData, cmsMockData = null) {
|
||||
// Define our mocks to attached to the 'global' object for Vue/Jest.
|
||||
const mocks = {};
|
||||
|
||||
mocks.dispatchNonBlockingStoreAction = jest.fn();
|
||||
mocks.dispatchNonBlockingStoreAction.mockImplementation((actionName) => {
|
||||
let actionFilterResult = mockData.actionList.filter(
|
||||
(x) => x.actionName == actionName
|
||||
);
|
||||
|
||||
if (actionFilterResult.length > 0 && actionFilterResult.length === 1) {
|
||||
return Promise.resolve({
|
||||
data: actionFilterResult[0].data,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if(cmsMockData){
|
||||
mocks.GetContentFromCms = jest.fn();
|
||||
mocks.GetContentFromCms.mockImplementation(() =>
|
||||
{
|
||||
return cmsMockData;
|
||||
});
|
||||
}
|
||||
|
||||
// Mock store actions from js file
|
||||
mocks.storeActions = storeActions;
|
||||
const global = {
|
||||
mocks: mocks,
|
||||
};
|
||||
|
||||
return { global };
|
||||
}
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import { storeActions } from "@/constants/storeActions";
|
||||
|
||||
export function getMountOptions(mockData) {
|
||||
// Define our mocks to attached to the 'global' object for Vue/Jest.
|
||||
const mocks = {};
|
||||
|
||||
mocks.dispatchNonBlockingStoreAction = jest.fn();
|
||||
mocks.dispatchNonBlockingStoreAction.mockImplementation((actionName) => {
|
||||
|
||||
let actionFilterResult = mockData.actionList.filter(x => x.actionName == actionName);
|
||||
|
||||
if (actionFilterResult.length > 0 && actionFilterResult.length === 1) {
|
||||
|
||||
return Promise.resolve({
|
||||
data: actionFilterResult[0].data
|
||||
});
|
||||
}
|
||||
});
|
||||
// Mock store actions from js file
|
||||
mocks.storeActions = storeActions;
|
||||
const global = {
|
||||
mocks: mocks
|
||||
};
|
||||
|
||||
return { global }
|
||||
}
|
||||
112
src/layouts/component-test/component-test.vue
Normal file
112
src/layouts/component-test/component-test.vue
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<template>
|
||||
<div class="container-fluid container-shadow p-2 rounded-3">
|
||||
<div class="row g-2">
|
||||
<radioCard radioLabel="Windshield" radioImage="windshield-damage.svg" altText="Windshield" groupName="damageKey" radioID="windshield" />
|
||||
<radioCard radioLabel="Side Window" radioImage="side-window-damage.svg" altText="Side Window" groupName="damageKey" radioID="sidewindow" />
|
||||
<radioCard radioLabel="Back Glass" radioImage="back-glass-damage.svg" altText="Back Glass" groupName="damageKey" radioID="backglass" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<buttonPrimary buttonText="Primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<buttonSecondary buttonText="Secondary" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<listButton buttonText="List Button" errorText="Test error message" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- The role="radiogroup" and aria-labelledby must be included in the parent component for the radio group -->
|
||||
<div role="radiogroup" aria-labelledby="select-year-radio-group" class="col my-3 d-flex align-items-center flex-column">
|
||||
<!-- The h3 and id must be included. The id must match the aria-labelledby of the parent div. -->
|
||||
<h3 class="visually-hidden" id="select-year-radio-group">
|
||||
Select Vehicle Year
|
||||
</h3>
|
||||
<radioList groupName="demo" ariaLabelBy="vehicle-year" radioID="2021" errorMessage="Test error message" />
|
||||
<radioList groupName="demo" ariaLabelBy="vehicle-year" radioID="2020" errorMessage="Test error message" />
|
||||
<radioList groupName="demo" ariaLabelBy="vehicle-year" radioID="2019" errorMessage="Test error message" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<a href="#">Text Link</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<p>This is default body copy font size/weight</p>
|
||||
<p class="small">
|
||||
This is small body copy using <code>.small</code> class
|
||||
</p>
|
||||
<p>
|
||||
<small>This is also small using <code><small></code> tag</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h1>h1 Heading</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h2>h2 Heading</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h3>h3 Heading</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h4>h4 Heading</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h5>h5 Heading</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h6>h6 Heading</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-3">
|
||||
<div class="select-car">
|
||||
<div class="select-car-form">
|
||||
<radioQuestion questionText="What year is your vehicle?" :answers="this.years" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import buttonPrimary from "@/ux-components/button-primary/button-primary";
|
||||
import buttonSecondary from "@/ux-components/button-secondary/button-secondary";
|
||||
import radioCard from "@/ux-components/radio-card/radio-card";
|
||||
import listButton from "@/ux-components/list-button/list-button";
|
||||
import radioList from "@/ux-components/radio-list/radio-list";
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
buttonPrimary,
|
||||
buttonSecondary,
|
||||
radioCard,
|
||||
listButton,
|
||||
radioList,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
years: [2023, 2022, 2021, 2020],
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
<template>
|
||||
<div class="container-fluid container-shadow p-2 rounded-3">
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio Card</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<radioCard
|
||||
radioLabel="Windshield"
|
||||
radioImage="windshield-damage.svg"
|
||||
altText="Windshield"
|
||||
groupName="damageKey"
|
||||
radioID="windshield"
|
||||
/>
|
||||
<radioCard
|
||||
radioLabel="Side Window"
|
||||
radioImage="side-window-damage.svg"
|
||||
altText="Side Window"
|
||||
groupName="damageKey"
|
||||
radioID="sidewindow"
|
||||
/>
|
||||
<radioCard
|
||||
radioLabel="Back Glass"
|
||||
radioImage="back-glass-damage.svg"
|
||||
altText="Back Glass"
|
||||
groupName="damageKey"
|
||||
radioID="backglass"
|
||||
/>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Buttons</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<buttonPrimary
|
||||
buttonText="Primary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<buttonSecondary
|
||||
buttonText="Secondary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">List Button</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<listButton
|
||||
buttonText="List Button"
|
||||
errorText="Test error message"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio Button Group</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- The role="radiogroup" and aria-labelledby must be included in the parent component for the radio group -->
|
||||
<div role="radiogroup" aria-labelledby="select-year-radio-group" class="col my-3 d-flex align-items-center flex-column">
|
||||
<!-- The h3 and id must be included. The id must match the aria-labelledby of the parent div. -->
|
||||
<h3 class="visually-hidden" id="select-year-radio-group">Select Vehicle Year</h3>
|
||||
<radioList
|
||||
groupName="demo"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2021"
|
||||
errorMessage="Test error message"
|
||||
/>
|
||||
<radioList
|
||||
groupName="demo"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2020"
|
||||
errorMessage="Test error message"
|
||||
/>
|
||||
<radioList
|
||||
groupName="demo"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2019"
|
||||
errorMessage="Test error message"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Text Link</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<a href="#">Text Link</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Typogrophy</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<p>This is default body copy font size/weight</p>
|
||||
<p class="small">This is small body copy using <code>.small</code> class</p>
|
||||
<p><small>This is also small using <code><small></code> tag</small></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Headings</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h1>h1 Heading</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h2>h2 Heading</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h3>h3 Heading</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h4>h4 Heading</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h5>h5 Heading</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<h6>h6 Heading</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Alerts</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<alert
|
||||
alertClass="alert-success"
|
||||
alertHeadline="Dismissible Alert"
|
||||
alertCopy="This is an example of a DISMISSIBLE alert. It will fade away and content around it will shift when dismissed."
|
||||
v-bind:isDismissible = "true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<alert
|
||||
alertClass="alert-danger"
|
||||
alertHeadline="NON-Dismissible Alert"
|
||||
alertCopy="This is an example of a NON-DISMISSIBLE alert."
|
||||
v-bind:isDismissible = "false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<alert
|
||||
alertClass="alert-warning"
|
||||
alertHeadline="Warning Alert"
|
||||
alertCopy="This is an example of a WARNING alert."
|
||||
v-bind:isDismissible = "false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<alert
|
||||
alertClass="alert-info"
|
||||
alertHeadline="Info Alert"
|
||||
alertCopy="This is an example of a INFO alert."
|
||||
v-bind:isDismissible = "false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<alert
|
||||
alertClass="alert-danger"
|
||||
alertHeadline="Danger Alert"
|
||||
alertCopy="This is an example of a DANGER alert."
|
||||
v-bind:isDismissible = "false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<alert
|
||||
alertClass="alert-success"
|
||||
alertHeadline="No Body Copy Alert"
|
||||
alertCopy=""
|
||||
v-bind:isDismissible = "false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import buttonPrimary from "@/uxComponents/buttonPrimary/buttonPrimary";
|
||||
import buttonSecondary from "@/uxComponents/buttonSecondary/buttonSecondary";
|
||||
import radioCard from "@/uxComponents/radioCard/radioCard";
|
||||
import listButton from "@/uxComponents/listButton/listButton";
|
||||
import radioList from "@/uxComponents/radioList/radioList";
|
||||
import alert from "@/uxComponents/alert/alert";
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
buttonPrimary,
|
||||
buttonSecondary,
|
||||
radioCard,
|
||||
listButton,
|
||||
radioList,
|
||||
alert
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
years: [2023, 2022, 2021, 2020],
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
3
src/layouts/not-found/not-found.vue
Normal file
3
src/layouts/not-found/not-found.vue
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<p>Not Found .... :(</p>
|
||||
</template>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<template>
|
||||
<p> Not Found .... :( </p>
|
||||
</template>
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<template>
|
||||
<div class="select-car overflow-hidden">
|
||||
<div class="select-car-form rounded text-center">
|
||||
<Header
|
||||
:text="year"
|
||||
/>
|
||||
<radioQuestion
|
||||
questionText="What is the make of your vehicle?"
|
||||
:answers="makes"
|
||||
:chooseAnswer="selectMake"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radioQuestion from "@/commonComponents/radioQuestion/radioQuestion";
|
||||
import Header from "@/uxComponents/header/header";
|
||||
import store from "@/store";
|
||||
import router from "@/router";
|
||||
import {
|
||||
mapState
|
||||
} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "SelectCar",
|
||||
computed: {
|
||||
...mapState(["year", "makes"]),
|
||||
},
|
||||
methods: {
|
||||
selectMake(make) {
|
||||
this.dispatchNonBlockingStoreAction("selectMake", { make: make }).then( (response) => {
|
||||
const models = response;
|
||||
store.commit('updateMake', {make, models});
|
||||
router.push(`/select-model?year=${store.year}&make=${make}`);
|
||||
});
|
||||
},
|
||||
goBack() {
|
||||
this.$store.state.slideTransition = "slide_reverse";
|
||||
this.$router.push("/select-year");
|
||||
},
|
||||
},
|
||||
components: {
|
||||
radioQuestion,
|
||||
Header,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
<template>
|
||||
<div class="select-car overflow-hidden">
|
||||
<div class="select-car-form rounded text-center">
|
||||
<Header
|
||||
:text="year + ' ' + make"
|
||||
/>
|
||||
<radioQuestion
|
||||
:questionText="'What is the model of your ' + make + '?'"
|
||||
:answers="models"
|
||||
:chooseAnswer="selectModel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radioQuestion from "@/commonComponents/radioQuestion/radioQuestion";
|
||||
import Header from "@/uxComponents/header/header";
|
||||
import store from "@/store";
|
||||
import router from "@/router";
|
||||
import { mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "SelectCar",
|
||||
computed: {
|
||||
...mapState(["year", "make", "models"]),
|
||||
},
|
||||
methods: {
|
||||
selectModel(model) {
|
||||
this.dispatchNonBlockingStoreAction("selectModel", { model: model }).then( (response) => {
|
||||
const styles = response;
|
||||
store.commit("updateModel", { model, styles });
|
||||
router.push(`/select-style?year=${store.year}&make=${store.make}&model=${model}`);
|
||||
});
|
||||
},
|
||||
goBack() {
|
||||
this.$store.state.slideTransition = "slide_reverse";
|
||||
this.$router.push(`/select-make?year=${store.year}`);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
radioQuestion,
|
||||
Header,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<template>
|
||||
<div class="select-car overflow-hidden">
|
||||
<div class="select-car-form rounded text-center">
|
||||
<Header
|
||||
:text="year + ' ' + make + ' ' + model"
|
||||
/>
|
||||
<radioQuestion
|
||||
:questionText="'What style is your ' + model + '?'"
|
||||
:answers="styles"
|
||||
:chooseAnswer="selectStyle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radioQuestion from "@/commonComponents/radioQuestion/radioQuestion";
|
||||
import Header from "@/uxComponents/header/header";
|
||||
import store from "@/store";
|
||||
import router from "@/router";
|
||||
import { mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "SelectCar",
|
||||
computed: {
|
||||
...mapState(["year", "make", "model", "styles"]),
|
||||
},
|
||||
methods: {
|
||||
selectStyle(style) {
|
||||
store.commit("updateStyle", { style });
|
||||
router.push(
|
||||
`/select-damage?year=${store.year}&make=${store.make}&model=${store.model}&style=${style}`
|
||||
);
|
||||
},
|
||||
goBack() {
|
||||
this.$store.state.slideTransition = "slide_reverse";
|
||||
this.$router.push(
|
||||
`/select-model?year=${store.year}&make=${store.make}`
|
||||
);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
radioQuestion,
|
||||
Header,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue'
|
||||
import { getMountOptions } from '@/helpers/unitTestHelper.js';
|
||||
import { storeActions } from '@/constants/storeActions.js'
|
||||
import selectYear from './selectYear.vue';
|
||||
|
||||
describe('selectYear.vue', () => {
|
||||
test("Should render the 'pageHeader.Text' data value 'text' prop value for the Header component, 'radioQuestion.Question' data value as 'questionText' prop value for the 'radioQuestion' component and 'years' values for 'answers' prop values for the 'radioQuestion' component.", async () => {
|
||||
|
||||
// Arrange
|
||||
const mockDataAndAction = {
|
||||
actionList: [
|
||||
{
|
||||
actionName: storeActions.GET_PAGE_DATA,
|
||||
data: {
|
||||
"Result": [
|
||||
{
|
||||
Type: "PageHeadingWidget",
|
||||
Model: {
|
||||
Text: "Mock Data"
|
||||
}
|
||||
},
|
||||
{
|
||||
Type: "RadioQuestionWidget",
|
||||
Model: {
|
||||
Question: "Mock Data"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
actionName: storeActions.GET_YEARS,
|
||||
data: ['2023', '2022', '2021']
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const mountOptions = getMountOptions(mockDataAndAction);
|
||||
|
||||
// Act
|
||||
const wrapper = shallowMount(selectYear, mountOptions);
|
||||
await nextTick()
|
||||
|
||||
// Assert
|
||||
const header = await wrapper.find('.Header');
|
||||
expect(header.attributes('text')).toEqual("Mock Data");
|
||||
|
||||
const radioQuestion = await wrapper.findComponent('.radioQuestion');
|
||||
expect(radioQuestion.attributes('answers')).toEqual('2023,2022,2021');
|
||||
expect(radioQuestion.attributes('questiontext')).toEqual("Mock Data");
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
<template>
|
||||
<div class="select-car">
|
||||
<div class="select-car-form rounded text-center">
|
||||
|
||||
<Header
|
||||
:text="pageHeader.Text" class="Header"
|
||||
/>
|
||||
<radioQuestion
|
||||
class="radioQuestion"
|
||||
:questionText="radioQuestion.Question"
|
||||
:answers="this.years"
|
||||
:chooseAnswer="selectYear"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radioQuestion from "@/commonComponents/radioQuestion/radioQuestion";
|
||||
import Header from "@/uxComponents/header/header";
|
||||
import store from "@/store";
|
||||
import router from "@/router";
|
||||
import { mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "SelectYear",
|
||||
data() {
|
||||
return {
|
||||
years: [],
|
||||
pageHeader: {},
|
||||
radioQuestion: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(["slideTransition", "carImg", "blurImg", "style"]),
|
||||
},
|
||||
mounted() {
|
||||
// Mocking Sitefinity data to (For Page Header and Radio Question)
|
||||
this.dispatchNonBlockingStoreAction(this.storeActions.GET_PAGE_DATA, {relativeUrl: 'https://mockey.qa.sagaws.net/service/content/selectYear'})
|
||||
.then( (response) => {
|
||||
response.data.Result.forEach((m) => {
|
||||
switch (m.Type) {
|
||||
case 'PageHeadingWidget': {
|
||||
this.pageHeader = m.Model;
|
||||
break;
|
||||
}
|
||||
case 'RadioQuestionWidget': {
|
||||
this.radioQuestion = m.Model;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Getting Years list
|
||||
this.dispatchNonBlockingStoreAction(this.storeActions.GET_YEARS)
|
||||
.then( (response) => {
|
||||
this.years = response.data;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
selectYear(year) {
|
||||
this.dispatchNonBlockingStoreAction("selectYear", { year: year }).then( (response) => {
|
||||
const makes = response;
|
||||
store.commit('updateYear', {year, makes});
|
||||
router.push(`select-make?year=${year}`);
|
||||
});
|
||||
}
|
||||
},
|
||||
components: {
|
||||
radioQuestion,
|
||||
Header,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
27
src/layouts/vehicle-year/vehicle-year.spec.js
Normal file
27
src/layouts/vehicle-year/vehicle-year.spec.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { shallowMount, flushPromises } from "@vue/test-utils";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import vehicleYear from "@/layouts/vehicle-year/vehicle-year.vue";
|
||||
|
||||
describe("vehicle-year.vue", () => {
|
||||
test("vehicle-year.vue should render data from CMS", async () => {
|
||||
|
||||
// Arrange
|
||||
const cmsMockData = {
|
||||
PageHeaderWidget: [{ HeaderText: "Select a year to get started" }],
|
||||
RadioQuestionWidget: [{ QuestionText: "What year is your vehicle?" }],
|
||||
}
|
||||
|
||||
const mountOptions = getMountOptions({}, cmsMockData);
|
||||
|
||||
// Act
|
||||
const wrapper = shallowMount(vehicleYear, mountOptions);
|
||||
await flushPromises();
|
||||
|
||||
// Assert
|
||||
const header = await wrapper.find(".Header");
|
||||
expect(header.attributes("text")).toEqual("Select a year to get started");
|
||||
|
||||
const yearQuestion = await wrapper.findComponent({name: 'year-question'});
|
||||
expect(yearQuestion.attributes("questiontext")).toEqual("What year is your vehicle?");
|
||||
});
|
||||
});
|
||||
34
src/layouts/vehicle-year/vehicle-year.vue
Normal file
34
src/layouts/vehicle-year/vehicle-year.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<template v-if="isCmsContentReady">
|
||||
<div class="select-car">
|
||||
<div class="select-car-form rounded text-center">
|
||||
<pageHeader :text="pageHeaderWidgets.HeaderText" class="Header" />
|
||||
<yearQuestion :questionText="radioQuestionWidgets.QuestionText" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
|
||||
import pageHeader from "@/ux-components/header/header";
|
||||
|
||||
export default {
|
||||
name: "vehicle-year",
|
||||
data() {
|
||||
return {
|
||||
pageHeaderWidgets: {},
|
||||
radioQuestionWidgets: {},
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
async created() {
|
||||
const pageContent = await this.GetContentFromCms();
|
||||
|
||||
this.pageHeaderWidgets = pageContent.PageHeaderWidget[0];
|
||||
this.radioQuestionWidgets = pageContent.RadioQuestionWidget[0];
|
||||
},
|
||||
components: {
|
||||
yearQuestion,
|
||||
pageHeader,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
28
src/layouts/vehicle-year/year-question/year-question.spec.js
Normal file
28
src/layouts/vehicle-year/year-question/year-question.spec.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { shallowMount, flushPromises } from "@vue/test-utils";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
|
||||
|
||||
describe('year-question.vue', () => {
|
||||
|
||||
test('year-question should call API to get years', async () => {
|
||||
// Arrange
|
||||
const mockDataAndAction = {
|
||||
actionList: [{ actionName: storeActions.GET_VEHICLE_YEARS, data: ["2023", "2022", "2021"],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mountOptions = getMountOptions(mockDataAndAction);
|
||||
|
||||
// Act
|
||||
const wrapper = shallowMount(yearQuestion, mountOptions);
|
||||
await wrapper.setProps({questionText: 'What year is your vehicle?'})
|
||||
await flushPromises();
|
||||
|
||||
// Assert
|
||||
const radioQuestion = await wrapper.findComponent({name: 'radioQuestion'});
|
||||
expect(radioQuestion.attributes('questiontext')).toBe("What year is your vehicle?");
|
||||
expect(radioQuestion.attributes('answers')).toBe('2023,2022,2021');
|
||||
});
|
||||
});
|
||||
29
src/layouts/vehicle-year/year-question/year-question.vue
Normal file
29
src/layouts/vehicle-year/year-question/year-question.vue
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<radioQuestion class="radioQuestion" :questionText="questionText" :answers="years" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radioQuestion from "@/common-components/radio-question/radio-question";
|
||||
|
||||
export default {
|
||||
name: "year-question",
|
||||
props: {
|
||||
questionText: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
years: [],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.dispatchNonBlockingStoreAction(this.storeActions.GET_VEHICLE_YEARS, {}).then((response) => {
|
||||
this.years = response.data;
|
||||
});
|
||||
},
|
||||
components: {
|
||||
radioQuestion,
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import router from './router';
|
||||
import store from '@/store';
|
||||
import baseMixin from "@/mixins/baseMixin.js";
|
||||
//Bootstrap JavaScript
|
||||
import router from "./router";
|
||||
import store from "@/store";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import "../node_modules/bootstrap/dist/js/bootstrap.js";
|
||||
|
||||
// Vue App Setup
|
||||
|
|
|
|||
69
src/mixins/base-mixin.js
Normal file
69
src/mixins/base-mixin.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import { widgetNames } from "@/constants/widget-names.js";
|
||||
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
isCmsContentReady: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// dispatchBlockingStoreAction(type, payload) {
|
||||
// // globalMethods.showWaitingModal(true);
|
||||
|
||||
// return this.dispatchNonBlockingStoreAction(type, payload).finally(() => {
|
||||
// // globalMethods.showWaitingModal(false);
|
||||
// });
|
||||
// },
|
||||
dispatchNonBlockingStoreAction(type, payload, encodePayload = false) {
|
||||
// Encode the payload if required
|
||||
if (encodePayload) {
|
||||
encodeUriData(payload);
|
||||
}
|
||||
|
||||
return this.$store.dispatch(type, payload);
|
||||
},
|
||||
|
||||
GetContentFromCms() {
|
||||
return this.dispatchNonBlockingStoreAction(this.storeActions.GET_PAGE_DATA,{ pageName: this.$route.query.fmgPage }).then((response) => {
|
||||
|
||||
const pageDataFromCms = {};
|
||||
|
||||
response.data.Result.forEach((widget) => {
|
||||
if (Object.values(this.widgetNames).includes(widget.Type)) {
|
||||
// If we already have this widget, push it on the collection
|
||||
if (widget.Type in pageDataFromCms) {
|
||||
pageDataFromCms[widget.Type].push(widget.Model);
|
||||
return;
|
||||
}
|
||||
|
||||
pageDataFromCms[widget.Type] = [widget.Model];
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Our 'Page' is ready because we have data now
|
||||
this.isCmsContentReady = true;
|
||||
|
||||
return pageDataFromCms;
|
||||
});
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
storeActions() {
|
||||
return storeActions;
|
||||
},
|
||||
widgetNames() {
|
||||
return widgetNames;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function encodeUriData(payload) {
|
||||
if (payload && Object.keys(payload).length > 0) {
|
||||
// Loop through the payload and encode the values
|
||||
Object.keys(payload).forEach((key) => {
|
||||
payload[key] = encodeURIComponent(payload[key]);
|
||||
});
|
||||
}
|
||||
}
|
||||
109
src/mixins/base-mixin.spec.js
Normal file
109
src/mixins/base-mixin.spec.js
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import baseMixin from "@/mixins/base-mixin"
|
||||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import { widgetNames } from "@/constants/widget-names.js";
|
||||
import { flushPromises } from "@vue/test-utils";
|
||||
|
||||
describe("baseMixin.js", () => {
|
||||
test('dispatchNonblockingStoreAction: calls dispatch with type and payload', () => {
|
||||
const mixIn = getMixInInstance({});
|
||||
const type = {};
|
||||
const payload = {};
|
||||
|
||||
mixIn.methods.dispatchNonBlockingStoreAction(type, payload);
|
||||
|
||||
expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload);
|
||||
});
|
||||
|
||||
test('dispatchNonblockingStoreAction: calls dispatch with type and payload, handles Uri encode', () => {
|
||||
const mixIn = getMixInInstance({});
|
||||
const type = {};
|
||||
const payload = { make: 'Alfa Romeo/Chrysler' };
|
||||
|
||||
mixIn.methods.dispatchNonBlockingStoreAction(type, payload, true);
|
||||
|
||||
expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload);
|
||||
});
|
||||
|
||||
test('GetContentFromCms: Should return mapped data and call dispatchNonblockingStoreAction', async () => {
|
||||
const mixIn = getMixInInstance({});
|
||||
|
||||
// Mock dispatch action
|
||||
mixIn.methods.dispatchNonBlockingStoreAction = jest.fn();
|
||||
mixIn.methods.dispatchNonBlockingStoreAction.mockImplementation((action) => {
|
||||
if (action === 'getPageData') {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
Result: [
|
||||
{
|
||||
Type: "PageConfigWidget",
|
||||
Model: {
|
||||
LayoutNames: [
|
||||
"None",
|
||||
"vehicle-year"
|
||||
],
|
||||
LayoutStyle: "vehicle-year"
|
||||
}
|
||||
},
|
||||
{
|
||||
Type: "RadioQuestionWidget",
|
||||
Model: {
|
||||
"QuestionText": "What year is your vehicle?"
|
||||
}
|
||||
},
|
||||
{
|
||||
Type: "RadioQuestionWidget",
|
||||
Model: {
|
||||
"QuestionText": "This is a second radio question"
|
||||
}
|
||||
},
|
||||
{
|
||||
Type: "PageHeaderWidget",
|
||||
Model: {
|
||||
"HeaderText": "Select a year to get started"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const result = await mixIn.methods.GetContentFromCms();
|
||||
await flushPromises();
|
||||
|
||||
|
||||
expect(mixIn.methods.dispatchNonBlockingStoreAction).toBeCalledWith(storeActions.GET_PAGE_DATA, { pageName: 'test-page'});
|
||||
|
||||
expect(result.PageHeaderWidget[0].HeaderText).toEqual('Select a year to get started');
|
||||
|
||||
});
|
||||
})
|
||||
function getMixInInstance({ isDispatchSuccess = true }) {
|
||||
|
||||
// Mock Store
|
||||
const store = {
|
||||
dispatch: jest.fn()
|
||||
}
|
||||
|
||||
if (isDispatchSuccess) {
|
||||
store.dispatch.mockReturnValue(Promise.resolve())
|
||||
} else {
|
||||
store.dispatch.mockReturnValue(Promise.reject())
|
||||
}
|
||||
|
||||
// Mock Route
|
||||
const route = {
|
||||
query: {
|
||||
fmgPage: 'test-page'
|
||||
}
|
||||
};
|
||||
|
||||
// Attach mocks to mixin
|
||||
const baseMixIn = baseMixin;
|
||||
baseMixIn.methods.$route = route;
|
||||
baseMixIn.methods.$store = store;
|
||||
baseMixIn.methods.storeActions = storeActions;
|
||||
baseMixIn.methods.widgetNames = widgetNames;
|
||||
|
||||
return baseMixIn;
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import { storeActions } from "@/constants/storeActions.js";
|
||||
import { widgetNames } from "@/constants/widgetNames.js";
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
dispatchBlockingStoreAction(type, payload) {
|
||||
// globalMethods.showWaitingModal(true);
|
||||
|
||||
return this.dispatchNonBlockingStoreAction(type, payload)
|
||||
.finally(() => {
|
||||
// globalMethods.showWaitingModal(false);
|
||||
});;
|
||||
},
|
||||
dispatchNonBlockingStoreAction(type, payload) {
|
||||
return this.$store.dispatch(type, payload);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
storeActions() {
|
||||
return storeActions;
|
||||
},
|
||||
widgetNames(){
|
||||
return widgetNames;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
import { createWebHistory, createRouter } from "vue-router";
|
||||
import { storeActions } from "@/constants/storeActions.js";
|
||||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
||||
import ComponentTest from "@/layouts/componentTest/componentTest.vue";
|
||||
import NotFound from "@/layouts/notFound/notFound.vue";
|
||||
import ComponentTest from "@/layouts/component-test/component-test.vue";
|
||||
import NotFound from "@/layouts/not-found/not-found.vue";
|
||||
import store from "@/store";
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
path: "/:pathMatch(.*)*",
|
||||
component: NotFound,
|
||||
name: "NotFound"
|
||||
name: "NotFound",
|
||||
},
|
||||
{
|
||||
path: "/component-test", // This is a temporary route for testing.
|
||||
|
|
@ -19,12 +19,10 @@ const routes = [
|
|||
{
|
||||
path: "/",
|
||||
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);
|
||||
} else {
|
||||
|
||||
// If we already have our route, go to it.
|
||||
if (router.hasRoute(to.query.fmgPage)) {
|
||||
return next({
|
||||
|
|
@ -34,24 +32,22 @@ const routes = [
|
|||
}
|
||||
|
||||
// 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) => {
|
||||
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,
|
||||
});
|
||||
|
||||
// Add our dynamic route.
|
||||
router.addRoute({
|
||||
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 })
|
||||
});
|
||||
|
||||
})
|
||||
// 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);
|
||||
|
||||
|
|
@ -68,7 +64,7 @@ const router = createRouter({
|
|||
routes,
|
||||
});
|
||||
|
||||
// Get route information by page name.
|
||||
// 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) => {
|
||||
|
|
@ -81,14 +77,13 @@ function GetRouteInfoFromPageName(pageName) {
|
|||
|
||||
Object.keys(jsonFromResponse).forEach((key) => {
|
||||
routeData.push({
|
||||
path: `${jsonFromResponse[key].RelativeUrl}`,
|
||||
path: "/",
|
||||
name: `${key}`,
|
||||
component: lazyLoadComponent(jsonFromResponse[key].LayoutName),
|
||||
});
|
||||
});
|
||||
|
||||
resolve(routeData);
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
|
|
@ -99,10 +94,10 @@ function GetRouteInfoFromPageName(pageName) {
|
|||
// 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) },
|
||||
name: "NotFound",
|
||||
params: { pathMatch: to.path.split("/").slice(1) },
|
||||
query: to.query,
|
||||
hash: to.hash
|
||||
hash: to.hash,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,103 +10,106 @@ export default createStore({
|
|||
}),
|
||||
],
|
||||
state: {
|
||||
makes: [],
|
||||
models: [],
|
||||
styles: [],
|
||||
year: "",
|
||||
make: "",
|
||||
model: "",
|
||||
style: "",
|
||||
slideTransition: "none",
|
||||
carImg:
|
||||
"https://s3.amazonaws.com/safelite-lab-vehicle-images/Evox/8963_cc0320_032_UG_white_2014_Ford_Focus_18029225538399034889.jpg",
|
||||
blurImg: true,
|
||||
},
|
||||
mutations: {
|
||||
updateYear(state, data) {
|
||||
state.year = data.year;
|
||||
state.makes = data.makes.data;
|
||||
state.slideTransition = "slide";
|
||||
},
|
||||
updateMake(state, data) {
|
||||
state.make = data.make;
|
||||
state.models = data.models.data;
|
||||
state.slideTransition = "slide";
|
||||
},
|
||||
updateModel(state, data) {
|
||||
state.model = data.model;
|
||||
state.styles = data.styles.data;
|
||||
state.slideTransition = "slide";
|
||||
},
|
||||
updateStyle(state, data) {
|
||||
state.style = data.style;
|
||||
state.carImg =
|
||||
"https://s3.amazonaws.com/safelite-lab-vehicle-images/Evox/8963_cc0320_032_UG_white_2014_Ford_Focus_18029225538399034889.jpg";
|
||||
state.blurImg = false;
|
||||
state.slideTransition = "slide";
|
||||
},
|
||||
removeStyle(state) {
|
||||
state.style = "";
|
||||
state.blurImg = true;
|
||||
state.carImg =
|
||||
"https://s3.amazonaws.com/safelite-lab-vehicle-images/Evox/8963_cc0320_032_UG_white_2014_Ford_Focus_18029225538399034889.jpg";
|
||||
},
|
||||
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,
|
||||
problemGlassQuestions: null,
|
||||
problemMoldingQuestions: null,
|
||||
problemPropertyQuestions: null,
|
||||
},
|
||||
items: null,
|
||||
customer: {
|
||||
emailAddress: null,
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
phoneNumber: {
|
||||
isMobile: null,
|
||||
optInSms: null,
|
||||
}
|
||||
},
|
||||
payment: {
|
||||
isInsurance: null,
|
||||
isCash: null,
|
||||
},
|
||||
referral: {
|
||||
referralSeqNum: null,
|
||||
workOrderId: null
|
||||
}
|
||||
}
|
||||
},
|
||||
applicationUser: {
|
||||
experiments: null,
|
||||
}
|
||||
},
|
||||
mutations: {},
|
||||
actions: {
|
||||
getYears(){
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetYears.method,
|
||||
endpoint: endpoints.GetYears.url,
|
||||
payload:{}
|
||||
});
|
||||
},
|
||||
selectYear(context, { year }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetMakes.method,
|
||||
endpoint: endpoints.GetMakes.url,
|
||||
payload:{
|
||||
"Year": year
|
||||
}
|
||||
});
|
||||
},
|
||||
selectMake({ commit, state }, { make }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetModels.method,
|
||||
endpoint: endpoints.GetModels.url,
|
||||
payload:{
|
||||
"Year": state.year,
|
||||
"Make": make
|
||||
}
|
||||
});
|
||||
},
|
||||
selectModel({ commit, state }, { model }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetStyles.method,
|
||||
endpoint: endpoints.GetStyles.url,
|
||||
payload:{
|
||||
"Year": state.year,
|
||||
"Make": state.make,
|
||||
"Model": model
|
||||
}
|
||||
});
|
||||
},
|
||||
getRouteInfo(context, { relativeUrl }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetRouteInfoEndpoint.method,
|
||||
endpoint: endpoints.GetRouteInfoEndpoint.url,
|
||||
payload: {
|
||||
relativeUrl: relativeUrl,
|
||||
},
|
||||
});
|
||||
},
|
||||
// For mock data purposes only
|
||||
getMockPageData(context, { relativeUrl }) {
|
||||
return globalMethods.callMockHttpClient({
|
||||
method: endpoints.GetPageData.method,
|
||||
endpoint: relativeUrl,
|
||||
payload: {
|
||||
},
|
||||
});
|
||||
},
|
||||
// Vehicle API Actions
|
||||
getVehicleYears(context) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetVehicleYears.method,
|
||||
endpoint: endpoints.GetVehicleYears.url,
|
||||
payload: {},
|
||||
});
|
||||
},
|
||||
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: {},
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
1
src/ux-components/button-primary/button-primary.spec.js
Normal file
1
src/ux-components/button-primary/button-primary.spec.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
test.todo("some test to be written in the future");
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
class="btn btn-primary d-flex align-items-center"
|
||||
v-on:click="showLoader()"
|
||||
v-bind:class="[this.isLoading ? 'button-loader' : 'not-loading']"
|
||||
>
|
||||
>
|
||||
{{ this.buttonText }}
|
||||
</button>
|
||||
</template>
|
||||
|
|
@ -15,11 +15,11 @@ export default {
|
|||
name: "buttonPrimary",
|
||||
props: {
|
||||
buttonText: String,
|
||||
isDisabled: Boolean
|
||||
isDisabled: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: false
|
||||
isLoading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -0,0 +1 @@
|
|||
test.todo("some test to be written in the future");
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
class="btn btn-secondary d-flex align-items-center"
|
||||
v-on:click="showLoader()"
|
||||
v-bind:class="[this.isLoading ? 'button-loader' : 'not-loading']"
|
||||
>
|
||||
>
|
||||
{{ this.buttonText }}
|
||||
</button>
|
||||
</template>
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
export default {
|
||||
name: "buttonSecondary",
|
||||
props: {
|
||||
buttonText: String
|
||||
buttonText: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
16
src/ux-components/header/header.spec.js
Normal file
16
src/ux-components/header/header.spec.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import Header from "./header";
|
||||
|
||||
describe("Header.vue", () => {
|
||||
it("Should render the 'text' prop value as a span value for the header span text value.", () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(Header, {
|
||||
propsData: {
|
||||
text: "Header Content",
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find("span").text()).toContain("Header Content");
|
||||
});
|
||||
});
|
||||
16
src/ux-components/header/header.vue
Normal file
16
src/ux-components/header/header.vue
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<div class="current_car_info-text">
|
||||
<div class="d-flex align-items-center justify-content-center">
|
||||
<span class="text-center text-dark fs-5 d-block">{{ text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Header",
|
||||
props: {
|
||||
text: String,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
1
src/ux-components/list-button/list-button.spec.js
Normal file
1
src/ux-components/list-button/list-button.spec.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
test.todo("some test to be written in the future");
|
||||
|
|
@ -3,8 +3,11 @@
|
|||
<button
|
||||
class="btn list-button d-flex align-items-center"
|
||||
v-on:click="showLoader()"
|
||||
v-bind:class="[this.isLoading ? 'button-loader' : 'not-loading',this.isError ? 'error' : '']"
|
||||
>
|
||||
v-bind:class="[
|
||||
this.isLoading ? 'button-loader' : 'not-loading',
|
||||
this.isError ? 'error' : '',
|
||||
]"
|
||||
>
|
||||
{{ this.buttonText }}
|
||||
</button>
|
||||
<label class="small mt-1">{{ this.errorText }}</label>
|
||||
|
|
@ -16,12 +19,12 @@ export default {
|
|||
name: "listButton",
|
||||
props: {
|
||||
buttonText: String,
|
||||
errorText: String
|
||||
errorText: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
isError: false
|
||||
isError: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
1
src/ux-components/radio-card/radio-card.spec.js
Normal file
1
src/ux-components/radio-card/radio-card.spec.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
test.todo("some test to be written in the future");
|
||||
|
|
@ -47,7 +47,7 @@ export default {
|
|||
</script>
|
||||
<style lang="scss">
|
||||
.radio-card {
|
||||
input[type=radio] {
|
||||
input[type="radio"] {
|
||||
&:focus + label {
|
||||
background-color: $white;
|
||||
box-shadow: 0px 0px 0px 4px $blue;
|
||||
|
|
@ -74,5 +74,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
1
src/ux-components/radio-list/radio-list.spec.js
Normal file
1
src/ux-components/radio-list/radio-list.spec.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
test.todo("some test to be written in the future");
|
||||
28
src/ux-components/radio-list/radio-list.vue
Normal file
28
src/ux-components/radio-list/radio-list.vue
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<div class="radiogroup radio-list-button d-flex flex-column w-100">
|
||||
<input type="radio" v-bind:id="radioID" v-bind:name="groupName" v-bind:value="radioID" />
|
||||
<label role="radio" tabindex="0" aria-checked="false" v-bind:for="radioID" class="mb-2 d-flex align-items-center p-2" v-on:click="showLoader()" v-bind:class="[
|
||||
this.isLoading ? 'button-loader' : 'not-loading',
|
||||
this.isError ? 'error' : '',
|
||||
]">{{ radioID }}</label>
|
||||
<p class="small">{{ errorMessage }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "radioList",
|
||||
props: ["groupName", "ariaLabelBy", "radioID", "errorMessage"],
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
showLoader() {
|
||||
this.isLoading = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
23
src/ux-components/radio/radio.spec.js
Normal file
23
src/ux-components/radio/radio.spec.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import radio from "./radio";
|
||||
|
||||
describe("radio.vue", () => {
|
||||
it("Should render the 'text' prop value as a span value for the radio button label and add the 'value' prop value as the radio button value and id.", () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(radio, {
|
||||
propsData: {
|
||||
value: "2023",
|
||||
text: "12",
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find("span").text()).toEqual("12");
|
||||
expect(wrapper.find("input").attributes()).toEqual({
|
||||
class: "position-absolute opacity-0",
|
||||
id: "2023",
|
||||
type: "radio",
|
||||
value: "2023",
|
||||
});
|
||||
});
|
||||
});
|
||||
35
src/ux-components/radio/radio.vue
Normal file
35
src/ux-components/radio/radio.vue
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<template>
|
||||
<div>
|
||||
<input
|
||||
type="radio"
|
||||
:id="this.value"
|
||||
:value="this.value"
|
||||
class="position-absolute opacity-0"
|
||||
v-on:click="showLoader()"
|
||||
/>
|
||||
<label
|
||||
:for="this.value"
|
||||
class="btn list-button d-flex align-items-center"
|
||||
v-bind:class="[this.isLoading ? 'button-loader' : '']"
|
||||
>
|
||||
<span>{{ text }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "radio",
|
||||
props: ["value", "text"],
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
showLoader() {
|
||||
this.isLoading = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<script>
|
||||
import confetti from "/node_modules/canvas-confetti/src/confetti.js";
|
||||
setTimeout(function () {
|
||||
// Adjust timing of confetti event on page load
|
||||
var count = 200;
|
||||
var defaults = {
|
||||
origin: { y: 0.7 },
|
||||
};
|
||||
|
||||
function fire(particleRatio, opts) {
|
||||
confetti(
|
||||
Object.assign({}, defaults, opts, {
|
||||
particleCount: Math.floor(count * particleRatio),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
fire(0.25, {
|
||||
spread: 26,
|
||||
startVelocity: 55,
|
||||
});
|
||||
fire(0.2, {
|
||||
spread: 60,
|
||||
});
|
||||
fire(0.35, {
|
||||
spread: 100,
|
||||
decay: 0.91,
|
||||
scalar: 0.8,
|
||||
});
|
||||
fire(0.1, {
|
||||
spread: 120,
|
||||
startVelocity: 25,
|
||||
decay: 0.92,
|
||||
scalar: 1.2,
|
||||
});
|
||||
fire(0.1, {
|
||||
spread: 120,
|
||||
startVelocity: 45,
|
||||
});
|
||||
}, 1000); // 1000 = 1second
|
||||
export default {
|
||||
name: "confetti",
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import Header from './header';
|
||||
|
||||
describe('Header.vue', () => {
|
||||
it("Should render the 'text' prop value as a span value for the header span text value.", () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(Header, {
|
||||
propsData: {
|
||||
text: 'Header Content'
|
||||
}
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find('span').text()).toContain("Header Content");
|
||||
})
|
||||
});
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<template>
|
||||
<div class="current_car_info-text">
|
||||
<div class="d-flex align-items-center justify-content-center">
|
||||
<span class="text-center text-dark fs-5 d-block">{{ text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Header",
|
||||
props: {
|
||||
text: String
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import radio from './radio';
|
||||
|
||||
describe('radio.vue', () => {
|
||||
it("Should render the 'text' prop value as a span value for the radio button label and add the 'value' prop value as the radio button value and id.", () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(radio, {
|
||||
propsData: {
|
||||
value: '2023',
|
||||
text: '12'
|
||||
}
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find('span').text()).toEqual('12');
|
||||
expect(wrapper.find('input').attributes()).toEqual({
|
||||
class: 'position-absolute opacity-0',
|
||||
id: '2023',
|
||||
type: 'radio',
|
||||
value: '2023'
|
||||
});
|
||||
})
|
||||
})
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<input
|
||||
type="radio"
|
||||
:id="this.value"
|
||||
:value="this.value"
|
||||
class="position-absolute opacity-0"
|
||||
v-on:click="showLoader()"
|
||||
/>
|
||||
<label
|
||||
:for="this.value"
|
||||
class="btn list-button d-flex align-items-center"
|
||||
v-bind:class="[this.isLoading ? 'button-loader' : '']"
|
||||
>
|
||||
<span>{{ text }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "radio",
|
||||
props: [
|
||||
"value",
|
||||
"text"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
showLoader() {
|
||||
this.isLoading = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1 +0,0 @@
|
|||
test.todo('some test to be written in the future');
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<template>
|
||||
<div class="radiogroup radio-list-button d-flex flex-column w-100">
|
||||
<input type="radio" v-bind:id="radioID" v-bind:name="groupName" v-bind:value="radioID">
|
||||
<label role="radio" tabindex="0" aria-checked="false" v-bind:for="radioID" class="mb-2 d-flex align-items-center p-2"
|
||||
v-on:click="showLoader()"
|
||||
v-bind:class="[this.isLoading ? 'button-loader' : 'not-loading',this.isError ? 'error' : '']"
|
||||
>{{radioID}}</label>
|
||||
<p class="small">{{errorMessage}}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "radioList",
|
||||
props: [
|
||||
"groupName",
|
||||
"ariaLabelBy",
|
||||
"radioID",
|
||||
"errorMessage"
|
||||
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
isError: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
showLoader() {
|
||||
this.isLoading = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,34 +1,26 @@
|
|||
process.env.VUE_APP_CONSUMER_API_GATEWAY = "https://consumerapidev.safelite.com";
|
||||
process.env.VUE_APP_CONSUMER_API_GATEWAY =
|
||||
"https://consumerapidev.safelite.com";
|
||||
|
||||
module.exports = {
|
||||
outputDir: "dist/fmg",
|
||||
publicPath: "/fmg",
|
||||
devServer: {
|
||||
port: 8080,
|
||||
proxy: {
|
||||
"api/v1/content*": {
|
||||
target: "https://localhost:44360/",
|
||||
ws: false,
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
css: {
|
||||
loaderOptions: {
|
||||
sass: { // Load Order Matters!!!
|
||||
sass: {
|
||||
// Load Order Matters!!!
|
||||
prependData: `
|
||||
@import "./node_modules/bootstrap/scss/functions";
|
||||
@import "@/styles/uxVariables.scss";
|
||||
@import "@/styles/ux-variables.scss";
|
||||
@import "./node_modules/bootstrap/scss/variables";
|
||||
@import "./node_modules/bootstrap/scss/mixins";
|
||||
@import "./node_modules/bootstrap/scss/bootstrap";
|
||||
@import "@/styles/commonStyles.scss";
|
||||
@import "@/styles/commonButtonStyles.scss";
|
||||
@import "@/styles/commonRadioStyles.scss";
|
||||
@import "@/styles/commonTypographyStyles.scss";
|
||||
@import "@/styles/commonComponentStyles/ymmsCommonStyles.scss";
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "@/styles/common-styles.scss";
|
||||
@import "@/styles/common-button-styles.scss";
|
||||
@import "@/styles/common-radio-styles.scss";
|
||||
@import "@/styles/common-typography-styles.scss";
|
||||
@import "@/styles/common-component-styles/ymms-common-styles.scss";
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,20 +5,21 @@ module.exports = {
|
|||
publicPath: "/fmg",
|
||||
css: {
|
||||
loaderOptions: {
|
||||
sass: { // Load Order Matters!!!
|
||||
sass: {
|
||||
// Load Order Matters!!!
|
||||
prependData: `
|
||||
@import "./node_modules/bootstrap/scss/functions";
|
||||
@import "@/styles/uxVariables.scss";
|
||||
@import "@/styles/ux-variables.scss";
|
||||
@import "./node_modules/bootstrap/scss/variables";
|
||||
@import "./node_modules/bootstrap/scss/mixins";
|
||||
@import "./node_modules/bootstrap/scss/bootstrap";
|
||||
@import "@/styles/commonStyles.scss";
|
||||
@import "@/styles/commonButtonStyles.scss";
|
||||
@import "@/styles/commonRadioStyles.scss";
|
||||
@import "@/styles/commonTypographyStyles.scss";
|
||||
@import "@/styles/commonComponentStyles/ymmsCommonStyles.scss";
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "@/styles/common-styles.scss";
|
||||
@import "@/styles/common-button-styles.scss";
|
||||
@import "@/styles/common-radio-styles.scss";
|
||||
@import "@/styles/common-typography-styles.scss";
|
||||
@import "@/styles/common-component-styles/ymms-common-styles.scss";
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue