kabab-case and a ton of updates
This commit is contained in:
parent
22beb0df5f
commit
ff1511429e
44 changed files with 346 additions and 320 deletions
|
|
@ -9,12 +9,13 @@ module.exports = {
|
||||||
"!src/main.js",
|
"!src/main.js",
|
||||||
"!src/constants/*.js",
|
"!src/constants/*.js",
|
||||||
"!src/router/**/*.js",
|
"!src/router/**/*.js",
|
||||||
"!src/helpers/*.js",
|
"!src/helpers/unitTestHelper.js",
|
||||||
|
"!src/layouts/componentTest/componentTest.vue"
|
||||||
], //! means exclude from coverage.
|
], //! means exclude from coverage.
|
||||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||||
coverageThreshold: {
|
coverageThreshold: {
|
||||||
global: {
|
global: {
|
||||||
statements: 90,
|
statements: 60,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from "@vue/test-utils";
|
||||||
import radioQuestion from "./radioQuestion";
|
import radioQuestion from "@/common-components/radio-question/radio-question";
|
||||||
|
|
||||||
describe("radioQuestion.vue", () => {
|
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.", () => {
|
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.", () => {
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import radio from "@/uxComponents/radio/radio";
|
import radio from "@/ux-components/radio/radio";
|
||||||
export default {
|
export default {
|
||||||
name: "radio-question",
|
name: "radio-question",
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { applicationConfig } from "@/constants/applicationConfig.js";
|
import { applicationConfig } from "@/constants/application-config.js";
|
||||||
import httpStatusCodes from "http-status-codes";
|
import httpStatusCodes from "http-status-codes";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { storeActions } from "@/constants/storeActions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
|
||||||
export function getMountOptions(mockData) {
|
export function getMountOptions(mockData, cmsMockData = null) {
|
||||||
// Define our mocks to attached to the 'global' object for Vue/Jest.
|
// Define our mocks to attached to the 'global' object for Vue/Jest.
|
||||||
const mocks = {};
|
const mocks = {};
|
||||||
|
|
||||||
|
|
@ -16,6 +16,15 @@ export function getMountOptions(mockData) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(cmsMockData){
|
||||||
|
mocks.GetContentFromCms = jest.fn();
|
||||||
|
mocks.GetContentFromCms.mockImplementation(() =>
|
||||||
|
{
|
||||||
|
return cmsMockData;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Mock store actions from js file
|
// Mock store actions from js file
|
||||||
mocks.storeActions = storeActions;
|
mocks.storeActions = storeActions;
|
||||||
const global = {
|
const global = {
|
||||||
|
|
@ -24,3 +33,4 @@ export function getMountOptions(mockData) {
|
||||||
|
|
||||||
return { global };
|
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,152 +0,0 @@
|
||||||
<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 "@/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";
|
|
||||||
export default {
|
|
||||||
name: "App",
|
|
||||||
components: {
|
|
||||||
buttonPrimary,
|
|
||||||
buttonSecondary,
|
|
||||||
radioCard,
|
|
||||||
listButton,
|
|
||||||
radioList,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
years: [2023, 2022, 2021, 2020],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,52 +1,27 @@
|
||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount, flushPromises } from "@vue/test-utils";
|
||||||
import { nextTick } from "vue";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import { getMountOptions } from "@/helpers/unitTestHelper.js";
|
import vehicleYear from "@/layouts/vehicle-year/vehicle-year.vue";
|
||||||
import { storeActions } from "@/constants/storeActions.js";
|
|
||||||
import selectYear from "./selectYear.vue";
|
describe("vehicle-year.vue", () => {
|
||||||
|
test("vehicle-year.vue should render data from CMS", async () => {
|
||||||
|
|
||||||
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
|
// Arrange
|
||||||
const mockDataAndAction = {
|
const cmsMockData = {
|
||||||
actionList: [
|
PageHeaderWidget: [{ HeaderText: "Select a year to get started" }],
|
||||||
{
|
RadioQuestionWidget: [{ QuestionText: "What year is your vehicle?" }],
|
||||||
actionName: storeActions.GET_PAGE_DATA,
|
}
|
||||||
data: {
|
|
||||||
Result: [
|
|
||||||
{
|
|
||||||
Type: "PageHeadingWidget",
|
|
||||||
Model: {
|
|
||||||
Text: "Mock Data",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: "RadioQuestionWidget",
|
|
||||||
Model: {
|
|
||||||
Question: "Mock Data",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
actionName: storeActions.GET_VEHICLE_YEARS,
|
|
||||||
data: ["2023", "2022", "2021"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const mountOptions = getMountOptions(mockDataAndAction);
|
const mountOptions = getMountOptions({}, cmsMockData);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const wrapper = shallowMount(selectYear, mountOptions);
|
const wrapper = shallowMount(vehicleYear, mountOptions);
|
||||||
await nextTick();
|
await flushPromises();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
const header = await wrapper.find(".Header");
|
const header = await wrapper.find(".Header");
|
||||||
expect(header.attributes("text")).toEqual("Mock Data");
|
expect(header.attributes("text")).toEqual("Select a year to get started");
|
||||||
|
|
||||||
const radioQuestion = await wrapper.findComponent(".radioQuestion");
|
const yearQuestion = await wrapper.findComponent({name: 'year-question'});
|
||||||
expect(radioQuestion.attributes("answers")).toEqual("2023,2022,2021");
|
expect(yearQuestion.attributes("questiontext")).toEqual("What year is your vehicle?");
|
||||||
expect(radioQuestion.attributes("questiontext")).toEqual("Mock Data");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template v-if="isPageReady">
|
<template v-if="isCmsContentReady">
|
||||||
<div class="select-car">
|
<div class="select-car">
|
||||||
<div class="select-car-form rounded text-center">
|
<div class="select-car-form rounded text-center">
|
||||||
<Header :text="pageHeaderWidgets.HeaderText" class="Header" />
|
<pageHeader :text="pageHeaderWidgets.HeaderText" class="Header" />
|
||||||
<yearQuestion :questionText="radioQuestionWidgets.QuestionText" />
|
<yearQuestion :questionText="radioQuestionWidgets.QuestionText" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
|
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
|
||||||
import Header from "@/uxComponents/header/header";
|
import pageHeader from "@/ux-components/header/header";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "vehicle-year",
|
name: "vehicle-year",
|
||||||
|
|
@ -22,12 +22,13 @@ export default {
|
||||||
computed: {},
|
computed: {},
|
||||||
async created() {
|
async created() {
|
||||||
const pageContent = await this.GetContentFromCms();
|
const pageContent = await this.GetContentFromCms();
|
||||||
|
|
||||||
this.pageHeaderWidgets = pageContent.PageHeaderWidget[0];
|
this.pageHeaderWidgets = pageContent.PageHeaderWidget[0];
|
||||||
this.radioQuestionWidgets = pageContent.RadioQuestionWidget[0];
|
this.radioQuestionWidgets = pageContent.RadioQuestionWidget[0];
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
yearQuestion,
|
yearQuestion,
|
||||||
Header,
|
pageHeader,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import radioQuestion from "@/commonComponents/radioQuestion/radioQuestion";
|
import radioQuestion from "@/common-components/radio-question/radio-question";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "year-question",
|
name: "year-question",
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ import { createApp } from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import baseMixin from "@/mixins/baseMixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
//Bootstrap JavaScript
|
|
||||||
import "../node_modules/bootstrap/dist/js/bootstrap.js";
|
import "../node_modules/bootstrap/dist/js/bootstrap.js";
|
||||||
|
|
||||||
// Vue App Setup
|
// Vue App Setup
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
import { storeActions } from "@/constants/storeActions.js";
|
import { storeActions } from "@/constants/store-actions.js";
|
||||||
import { widgetNames } from "@/constants/widgetNames.js";
|
import { widgetNames } from "@/constants/widget-names.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
isPageReady: false
|
isCmsContentReady: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
dispatchBlockingStoreAction(type, payload) {
|
// dispatchBlockingStoreAction(type, payload) {
|
||||||
// globalMethods.showWaitingModal(true);
|
// // globalMethods.showWaitingModal(true);
|
||||||
|
|
||||||
return this.dispatchNonBlockingStoreAction(type, payload).finally(() => {
|
// return this.dispatchNonBlockingStoreAction(type, payload).finally(() => {
|
||||||
// globalMethods.showWaitingModal(false);
|
// // globalMethods.showWaitingModal(false);
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
dispatchNonBlockingStoreAction(type, payload, encodePayload = false) {
|
dispatchNonBlockingStoreAction(type, payload, encodePayload = false) {
|
||||||
// Encode the payload if required
|
// Encode the payload if required
|
||||||
if (encodePayload) {
|
if (encodePayload) {
|
||||||
|
|
@ -26,8 +26,9 @@ export default {
|
||||||
|
|
||||||
GetContentFromCms() {
|
GetContentFromCms() {
|
||||||
return this.dispatchNonBlockingStoreAction(this.storeActions.GET_PAGE_DATA,{ pageName: this.$route.query.fmgPage }).then((response) => {
|
return this.dispatchNonBlockingStoreAction(this.storeActions.GET_PAGE_DATA,{ pageName: this.$route.query.fmgPage }).then((response) => {
|
||||||
const pageDataFromCms = {};
|
|
||||||
|
|
||||||
|
const pageDataFromCms = {};
|
||||||
|
|
||||||
response.data.Result.forEach((widget) => {
|
response.data.Result.forEach((widget) => {
|
||||||
if (Object.values(this.widgetNames).includes(widget.Type)) {
|
if (Object.values(this.widgetNames).includes(widget.Type)) {
|
||||||
// If we already have this widget, push it on the collection
|
// If we already have this widget, push it on the collection
|
||||||
|
|
@ -37,11 +38,12 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
pageDataFromCms[widget.Type] = [widget.Model];
|
pageDataFromCms[widget.Type] = [widget.Model];
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Our 'Page' is ready because we have data now
|
// Our 'Page' is ready because we have data now
|
||||||
this.isPageReady = true;
|
this.isCmsContentReady = true;
|
||||||
|
|
||||||
return pageDataFromCms;
|
return pageDataFromCms;
|
||||||
});
|
});
|
||||||
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,8 +1,8 @@
|
||||||
import { createWebHistory, createRouter } from "vue-router";
|
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 { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
||||||
import ComponentTest from "@/layouts/componentTest/componentTest.vue";
|
import ComponentTest from "@/layouts/component-test/component-test.vue";
|
||||||
import NotFound from "@/layouts/notFound/notFound.vue";
|
import NotFound from "@/layouts/not-found/not-found.vue";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
|
|
|
||||||
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>
|
||||||
|
|
@ -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 +0,0 @@
|
||||||
test.todo("some test to be written in the future");
|
|
||||||
|
|
@ -1,42 +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>
|
|
||||||
|
|
@ -10,15 +10,15 @@ module.exports = {
|
||||||
// Load Order Matters!!!
|
// Load Order Matters!!!
|
||||||
prependData: `
|
prependData: `
|
||||||
@import "./node_modules/bootstrap/scss/functions";
|
@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/variables";
|
||||||
@import "./node_modules/bootstrap/scss/mixins";
|
@import "./node_modules/bootstrap/scss/mixins";
|
||||||
@import "./node_modules/bootstrap/scss/bootstrap";
|
@import "./node_modules/bootstrap/scss/bootstrap";
|
||||||
@import "@/styles/commonStyles.scss";
|
@import "@/styles/common-styles.scss";
|
||||||
@import "@/styles/commonButtonStyles.scss";
|
@import "@/styles/common-button-styles.scss";
|
||||||
@import "@/styles/commonRadioStyles.scss";
|
@import "@/styles/common-radio-styles.scss";
|
||||||
@import "@/styles/commonTypographyStyles.scss";
|
@import "@/styles/common-typography-styles.scss";
|
||||||
@import "@/styles/commonComponentStyles/ymmsCommonStyles.scss";
|
@import "@/styles/common-component-styles/ymms-common-styles.scss";
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,15 @@ module.exports = {
|
||||||
// Load Order Matters!!!
|
// Load Order Matters!!!
|
||||||
prependData: `
|
prependData: `
|
||||||
@import "./node_modules/bootstrap/scss/functions";
|
@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/variables";
|
||||||
@import "./node_modules/bootstrap/scss/mixins";
|
@import "./node_modules/bootstrap/scss/mixins";
|
||||||
@import "./node_modules/bootstrap/scss/bootstrap";
|
@import "./node_modules/bootstrap/scss/bootstrap";
|
||||||
@import "@/styles/commonStyles.scss";
|
@import "@/styles/common-styles.scss";
|
||||||
@import "@/styles/commonButtonStyles.scss";
|
@import "@/styles/common-button-styles.scss";
|
||||||
@import "@/styles/commonRadioStyles.scss";
|
@import "@/styles/common-radio-styles.scss";
|
||||||
@import "@/styles/commonTypographyStyles.scss";
|
@import "@/styles/common-typography-styles.scss";
|
||||||
@import "@/styles/commonComponentStyles/ymmsCommonStyles.scss";
|
@import "@/styles/common-component-styles/ymms-common-styles.scss";
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue