Ran linter
This commit is contained in:
parent
43c6aed0a2
commit
daab1b0f1a
37 changed files with 927 additions and 753 deletions
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
"!src/constants/*.js",
|
||||
"!src/router/**/*.js",
|
||||
"!src/helpers/unit-test-helper.js",
|
||||
"!src/layouts/component-test/component-test.vue"
|
||||
"!src/layouts/component-test/component-test.vue",
|
||||
], //! means exclude from coverage.
|
||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||
coverageThreshold: {
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ 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.", async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(radioQuestion)
|
||||
const wrapper = shallowMount(radioQuestion);
|
||||
await wrapper.setProps({
|
||||
questionText: "Question Text",
|
||||
answers: ["2023", "2022", "2021"],
|
||||
modelValue: "2020"
|
||||
modelValue: "2020",
|
||||
});
|
||||
wrapper.vm.chooseAnswer("2021");
|
||||
|
||||
|
|
|
|||
|
|
@ -6,19 +6,32 @@
|
|||
}}</span>
|
||||
</div>
|
||||
<div class="w-100 d-flex justify-content-center">
|
||||
<div class="car_list overflow-scroll position-absolute container-fluid w-100 pt-1" role="radiogroup" aria-labelledby="select-year-radio-group">
|
||||
<div
|
||||
class="
|
||||
car_list
|
||||
overflow-scroll
|
||||
position-absolute
|
||||
container-fluid
|
||||
w-100
|
||||
pt-1
|
||||
"
|
||||
role="radiogroup"
|
||||
aria-labelledby="select-year-radio-group"
|
||||
>
|
||||
<h3 class="visually-hidden" id="select-year-radio-group">*</h3>
|
||||
<radio v-for="answer in answers" :key="answer"
|
||||
:radioID="answer"
|
||||
@click="chooseAnswer(answer)"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1.5"
|
||||
data-test="radio"
|
||||
groupName="radio-list"
|
||||
textPosition="text-start"
|
||||
:value="modelValue"
|
||||
/>
|
||||
<radio
|
||||
v-for="answer in answers"
|
||||
:key="answer"
|
||||
:radioID="answer"
|
||||
@click="chooseAnswer(answer)"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1.5"
|
||||
data-test="radio"
|
||||
groupName="radio-list"
|
||||
textPosition="text-start"
|
||||
:value="modelValue"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -31,12 +44,12 @@ export default {
|
|||
props: {
|
||||
questionText: String,
|
||||
answers: Array,
|
||||
modelValue: String
|
||||
modelValue: String,
|
||||
},
|
||||
methods: {
|
||||
chooseAnswer(answer) {
|
||||
this.$emit('update:modelValue', answer);
|
||||
}
|
||||
this.$emit("update:modelValue", answer);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
radio,
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import siteHeader from './site-header';
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import siteHeader from "./site-header";
|
||||
|
||||
describe('siteHeader', () => {
|
||||
describe("siteHeader", () => {
|
||||
test("renders the logo image", () => {
|
||||
// Arrange
|
||||
|
||||
test('renders the logo image', () => {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
const wrapper = shallowMount(siteHeader, {
|
||||
propsData: {
|
||||
imageSrc: "image_url",
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find('img')).toBeTruthy();
|
||||
wrapper.unmount();
|
||||
// Act
|
||||
const wrapper = shallowMount(siteHeader, {
|
||||
propsData: {
|
||||
imageSrc: "image_url",
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find("img")).toBeTruthy();
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
<template>
|
||||
<div class="funnel-header d-flex justify-content-center align-items-center" v-if="imageSrc">
|
||||
<img
|
||||
class="logo-image img-fluid"
|
||||
:src="imageSrc"
|
||||
alt="Safelite logo"
|
||||
/>
|
||||
<div
|
||||
class="funnel-header d-flex justify-content-center align-items-center"
|
||||
v-if="imageSrc"
|
||||
>
|
||||
<img class="logo-image img-fluid" :src="imageSrc" alt="Safelite logo" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -14,17 +13,17 @@ export default {
|
|||
props: {
|
||||
imageSrc: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.funnel-header {
|
||||
height: 56px;
|
||||
}
|
||||
.logo-image {
|
||||
max-width: 78px;
|
||||
}
|
||||
</style>
|
||||
.funnel-header {
|
||||
height: 56px;
|
||||
}
|
||||
.logo-image {
|
||||
max-width: 78px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import vehicleBanner from './vehicle-banner';
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import vehicleBanner from "./vehicle-banner";
|
||||
|
||||
describe('vehicleBanner', () => {
|
||||
describe("vehicleBanner", () => {
|
||||
test("renders the blurrycar image", () => {
|
||||
// Arrange
|
||||
|
||||
test('renders the blurrycar image', () => {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
const wrapper = shallowMount(vehicleBanner, {
|
||||
propsData: {
|
||||
vehicleImageSrc: "image_url",
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find('img').attributes('class')).toContain('blurrycar');
|
||||
wrapper.unmount();
|
||||
// Act
|
||||
const wrapper = shallowMount(vehicleBanner, {
|
||||
propsData: {
|
||||
vehicleImageSrc: "image_url",
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.find("img").attributes("class")).toContain("blurrycar");
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ export default {
|
|||
props: {
|
||||
vehicleImageSrc: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vehicle-image {
|
||||
max-width: 290px;
|
||||
}
|
||||
</style>
|
||||
.vehicle-image {
|
||||
max-width: 290px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
const storeMutations = {
|
||||
UPDATE_YEAR: "updateYear",
|
||||
}
|
||||
UPDATE_YEAR: "updateYear",
|
||||
};
|
||||
|
||||
export { storeMutations };
|
||||
export { storeMutations };
|
||||
|
|
|
|||
|
|
@ -3,22 +3,23 @@ import { widgetNames } from "@/constants/widget-names.js";
|
|||
import store from "@/store";
|
||||
|
||||
export function fetchCmsContentForPage(fmgPage) {
|
||||
return store.dispatch(storeActions.GET_PAGE_DATA, { pageName: fmgPage }).then((response) => {
|
||||
const pageDataFromCms = {};
|
||||
return store
|
||||
.dispatch(storeActions.GET_PAGE_DATA, { pageName: fmgPage })
|
||||
.then((response) => {
|
||||
const pageDataFromCms = {};
|
||||
|
||||
response.data.Result.forEach((widget) => {
|
||||
if (Object.values(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;
|
||||
}
|
||||
response.data.Result.forEach((widget) => {
|
||||
if (Object.values(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];
|
||||
}
|
||||
});
|
||||
pageDataFromCms[widget.Type] = [widget.Model];
|
||||
}
|
||||
});
|
||||
|
||||
return pageDataFromCms;
|
||||
return pageDataFromCms;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,52 +2,52 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
|||
import { dispatch } from "@/store";
|
||||
|
||||
jest.mock("@/store", () => ({
|
||||
dispatch: jest.fn()
|
||||
dispatch: jest.fn(),
|
||||
}));
|
||||
|
||||
it("cms-content-helper: Should return data from CMS", () => {
|
||||
// Arrange
|
||||
const cmsMockData = {
|
||||
Result: [
|
||||
{
|
||||
Type: "VehicleBannerWidget",
|
||||
Model: {
|
||||
ImageId: "28452dcb-7762-4cc9-ab09-7643d0b89203",
|
||||
GenericVehicleImage:
|
||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||
GenericVehicleImageFilePath:
|
||||
"images/default-source/default-album/blurred-image.jpg",
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "PageHeaderWidget",
|
||||
Model: {
|
||||
HeaderText: "Select a year to get started",
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "PageHeaderWidget",
|
||||
Model: {
|
||||
HeaderText: "Select a model",
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "RadioQuestionWidget",
|
||||
Model: {
|
||||
QuestionText: "What year is your vehicle?",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Arrange
|
||||
const cmsMockData = {
|
||||
Result: [
|
||||
{
|
||||
Type: "VehicleBannerWidget",
|
||||
Model: {
|
||||
ImageId: "28452dcb-7762-4cc9-ab09-7643d0b89203",
|
||||
GenericVehicleImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||
GenericVehicleImageFilePath: "images/default-source/default-album/blurred-image.jpg"
|
||||
}
|
||||
},
|
||||
{
|
||||
Type: "PageHeaderWidget",
|
||||
Model: {
|
||||
"HeaderText": "Select a year to get started"
|
||||
}
|
||||
},
|
||||
{
|
||||
Type: "PageHeaderWidget",
|
||||
Model: {
|
||||
"HeaderText": "Select a model"
|
||||
}
|
||||
},
|
||||
{
|
||||
Type: "RadioQuestionWidget",
|
||||
Model: {
|
||||
"QuestionText": "What year is your vehicle?"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
dispatch.mockImplementation(() => Promise.resolve({ data: cmsMockData }));
|
||||
|
||||
// Act
|
||||
fetchCmsContentForPage('testPage').then((response) => {
|
||||
|
||||
// Assert
|
||||
expect(response.isCmsContentReady).toBe(true);
|
||||
expect(response.PageHeaderWidget[0].HeaderText).toEqual('Select a year to get started');
|
||||
});
|
||||
dispatch.mockImplementation(() => Promise.resolve({ data: cmsMockData }));
|
||||
|
||||
// Act
|
||||
fetchCmsContentForPage("testPage").then((response) => {
|
||||
// Assert
|
||||
expect(response.isCmsContentReady).toBe(true);
|
||||
expect(response.PageHeaderWidget[0].HeaderText).toEqual(
|
||||
"Select a year to get started"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +1,27 @@
|
|||
export function settleAllPromises(promiseResultMap) {
|
||||
// Pull our keys out of the promise 'table'
|
||||
const promiseNames = Object.entries(promiseResultMap);
|
||||
|
||||
// Pull our keys out of the promise 'table'
|
||||
const promiseNames = Object.entries(promiseResultMap);
|
||||
return Promise.allSettled(
|
||||
promiseNames.map((e) => e[1]).map((n) => n.promise)
|
||||
).then((results) => {
|
||||
const resultMap = {};
|
||||
|
||||
return Promise.allSettled(promiseNames.map(e => e[1]).map(n => n.promise))
|
||||
.then(results => {
|
||||
// Build a map of the results
|
||||
for (let i = 0; i < results.length; ++i) {
|
||||
const promiseName = promiseNames[i][1].resultKey;
|
||||
|
||||
const resultMap = {};
|
||||
// Some Promises like the cms content call don't have a 'data' field
|
||||
// when returned, so other promises do. Map the results to the object
|
||||
// so that the object is the return data.
|
||||
|
||||
// Build a map of the results
|
||||
for (let i = 0; i < results.length; ++i) {
|
||||
|
||||
const promiseName = promiseNames[i][1].resultKey;
|
||||
|
||||
// Some Promises like the cms content call don't have a 'data' field
|
||||
// when returned, so other promises do. Map the results to the object
|
||||
// so that the object is the return data.
|
||||
if (results[i].value.data === undefined) {
|
||||
resultMap[promiseName] = results[i].value;
|
||||
} else {
|
||||
resultMap[promiseName] = results[i].value.data;
|
||||
}
|
||||
}
|
||||
|
||||
if (results[i].value.data === undefined) {
|
||||
resultMap[promiseName] = results[i].value
|
||||
} else {
|
||||
resultMap[promiseName] = results[i].value.data;
|
||||
}
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
});
|
||||
}
|
||||
return resultMap;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,25 @@
|
|||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
|
||||
it("layout-helper: Should settle all promises and return mapped promise results", () => {
|
||||
// Arrange
|
||||
const mockPromiseOne = Promise.resolve({ data: "test-data" });
|
||||
const mockPromiseTwo = Promise.resolve({ data: "test-data-two" });
|
||||
|
||||
// Arrange
|
||||
const mockPromiseOne = Promise.resolve({ data: "test-data" });
|
||||
const mockPromiseTwo = Promise.resolve({ data: "test-data-two" });
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "MockResultOne",
|
||||
promise: mockPromiseOne,
|
||||
},
|
||||
{
|
||||
resultKey: "MockResultTwo",
|
||||
promise: mockPromiseTwo,
|
||||
},
|
||||
];
|
||||
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "MockResultOne",
|
||||
promise: mockPromiseOne,
|
||||
},
|
||||
{
|
||||
resultKey: "MockResultTwo",
|
||||
promise: mockPromiseTwo,
|
||||
},
|
||||
];
|
||||
|
||||
// Act
|
||||
settleAllPromises(promiseResultMap).then(results => {
|
||||
|
||||
// Assert
|
||||
expect(results.MockResultOne).toEqual('test-data');
|
||||
expect(results.MockResultTwo).toEqual('test-data-two');
|
||||
});
|
||||
|
||||
})
|
||||
// Act
|
||||
settleAllPromises(promiseResultMap).then((results) => {
|
||||
// Assert
|
||||
expect(results.MockResultOne).toEqual("test-data");
|
||||
expect(results.MockResultTwo).toEqual("test-data-two");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,245 +2,275 @@
|
|||
<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>
|
||||
<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"
|
||||
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"
|
||||
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"
|
||||
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>
|
||||
<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" loaderColor="white" sizeInRem="1" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<buttonPrimary
|
||||
buttonText="Primary"
|
||||
loaderColor="white"
|
||||
sizeInRem="1"
|
||||
buttonText="Primary"
|
||||
loaderColor="white"
|
||||
sizeInRem="1"
|
||||
@click="onClick"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<buttonSecondary
|
||||
buttonText="Secondary"
|
||||
loaderColor="white"
|
||||
sizeInRem="1"
|
||||
buttonText="Secondary"
|
||||
loaderColor="white"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">List Button</h4>
|
||||
<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"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
buttonText="List Button"
|
||||
errorText="Test error message"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio - Single-Line</h4>
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio - Single-Line</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="demo-1-radio-group" class="col my-3 d-flex align-items-center flex-column">
|
||||
<div
|
||||
role="radiogroup"
|
||||
aria-labelledby="demo-1-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="demo-1-radio-group">Select Vehicle Year</h3>
|
||||
<h3 class="visually-hidden" id="demo-1-radio-group">
|
||||
Select Vehicle Year
|
||||
</h3>
|
||||
<radio
|
||||
groupName="demo-1"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2021"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-1"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2021"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
<radio
|
||||
groupName="demo-1"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2020"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-1"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2020"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
<radio
|
||||
groupName="demo-1"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2019"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-1"
|
||||
ariaLabelBy="vehicle-year"
|
||||
radioID="2019"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio - Multi-Line</h4>
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio - Multi-Line</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="demo-2-radio-group" class="col my-3 d-flex align-items-center flex-column">
|
||||
<div
|
||||
role="radiogroup"
|
||||
aria-labelledby="demo-2-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="demo-2-radio-group">Select Vehicle Year</h3>
|
||||
<h3 class="visually-hidden" id="demo-2-radio-group">
|
||||
Select Vehicle Year
|
||||
</h3>
|
||||
<radio
|
||||
groupName="demo-2"
|
||||
ariaLabelBy="vehicle-make"
|
||||
radioID="Chevrolet"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-2"
|
||||
ariaLabelBy="vehicle-make"
|
||||
radioID="Chevrolet"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
<radio
|
||||
groupName="demo-2"
|
||||
ariaLabelBy="vehicle-make"
|
||||
radioID="Dodge"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-2"
|
||||
ariaLabelBy="vehicle-make"
|
||||
radioID="Dodge"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
<radio
|
||||
groupName="demo-2"
|
||||
ariaLabelBy="vehicle-make"
|
||||
radioID="Ford"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-2"
|
||||
ariaLabelBy="vehicle-make"
|
||||
radioID="Ford"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-start"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio - Multi-Line Centered</h4>
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio - Multi-Line Centered</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="demo-3-radio-group" class="col my-3 d-flex align-items-center flex-column">
|
||||
<div
|
||||
role="radiogroup"
|
||||
aria-labelledby="demo-3-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="demo-3-radio-group">Multi-Line Centered</h3>
|
||||
<h3 class="visually-hidden" id="demo-3-radio-group">
|
||||
Multi-Line Centered
|
||||
</h3>
|
||||
<radio
|
||||
groupName="demo-3"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="Corvette"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-3"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="Corvette"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
<radio
|
||||
groupName="demo-3"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="Testarosa"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-3"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="Testarosa"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
<radio
|
||||
groupName="demo-3"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="S600"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
groupName="demo-3"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="S600"
|
||||
radioLabelSubCopy="Test sub-headline"
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio Horizontal</h4>
|
||||
<h4 class="m-0 p-2 bg-light rounded">Radio Horizontal</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-3">
|
||||
<!-- The role="radiogroup" and aria-labelledby must be included in the parent component for the radio group -->
|
||||
<div role="radiogroup" aria-labelledby="demo-4-radio-group" class="d-flex flex-row p-0">
|
||||
<div
|
||||
role="radiogroup"
|
||||
aria-labelledby="demo-4-radio-group"
|
||||
class="d-flex flex-row p-0"
|
||||
>
|
||||
<!-- The h3 and id must be included. The id must match the aria-labelledby of the parent div. -->
|
||||
<h3 class="visually-hidden" id="demo-4-radio-group">Select Vehicle Year</h3>
|
||||
<h3 class="visually-hidden" id="demo-4-radio-group">
|
||||
Select Vehicle Year
|
||||
</h3>
|
||||
<radioHorizontal
|
||||
groupName="demo-4"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="1"
|
||||
radioLabelSubCopy=""
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
v-bind:totalInGroup="3"
|
||||
v-bind:positionInGroup="1"
|
||||
groupName="demo-4"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="1"
|
||||
radioLabelSubCopy=""
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
v-bind:totalInGroup="3"
|
||||
v-bind:positionInGroup="1"
|
||||
/>
|
||||
<radioHorizontal
|
||||
groupName="demo-4"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="2"
|
||||
radioLabelSubCopy=""
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
v-bind:totalInGroup="3"
|
||||
v-bind:positionInGroup="2"
|
||||
groupName="demo-4"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="2"
|
||||
radioLabelSubCopy=""
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
v-bind:totalInGroup="3"
|
||||
v-bind:positionInGroup="2"
|
||||
/>
|
||||
<radioHorizontal
|
||||
groupName="demo-4"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="3"
|
||||
radioLabelSubCopy=""
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
v-bind:totalInGroup="3"
|
||||
v-bind:positionInGroup="3"
|
||||
groupName="demo-4"
|
||||
ariaLabelBy="vehicle-model"
|
||||
radioID="3"
|
||||
radioLabelSubCopy=""
|
||||
textPosition="text-center"
|
||||
loaderColor="blue"
|
||||
loaderPosition="right"
|
||||
sizeInRem="1"
|
||||
v-bind:totalInGroup="3"
|
||||
v-bind:positionInGroup="3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Text Link</h4>
|
||||
<h4 class="m-0 p-2 bg-light rounded">Text Link</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
|
@ -250,19 +280,23 @@
|
|||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Typogrophy</h4>
|
||||
<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>
|
||||
<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>
|
||||
<h4 class="m-0 p-2 bg-light rounded">Headings</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
|
|
@ -297,119 +331,128 @@
|
|||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Alerts</h4>
|
||||
<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"
|
||||
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"
|
||||
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-info"
|
||||
alertHeadline="Info Alert"
|
||||
alertCopy="This is an example of a INFO alert."
|
||||
v-bind:isDismissible = "false"
|
||||
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-danger"
|
||||
alertHeadline="Danger Alert"
|
||||
alertCopy="This is an example of a DANGER alert."
|
||||
v-bind:isDismissible = "false"
|
||||
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-success"
|
||||
alertHeadline="No Body Copy Alert"
|
||||
alertCopy=""
|
||||
v-bind:isDismissible = "false"
|
||||
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 class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Site Header</h4>
|
||||
<h4 class="m-0 p-2 bg-light rounded">Site Header</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
<div class="col">
|
||||
<siteHeader imageSrc="https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3" />
|
||||
<siteHeader
|
||||
imageSrc="https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<h4 class="m-0 p-2 bg-light rounded">Vehicle Banner</h4>
|
||||
<h4 class="m-0 p-2 bg-light rounded">Vehicle Banner</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
<div class="col">
|
||||
<vehicleBanner vehicleImageSrc="https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3" />
|
||||
<vehicleBanner
|
||||
vehicleImageSrc="https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3"
|
||||
/>
|
||||
</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 radio from "@/ux-components/radio/radio";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||
import siteHeader from "@/common-components/site-header/site-header";
|
||||
import radioHorizontal from "@/ux-components/radio-horizontal/radio-horizontal";
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
buttonPrimary,
|
||||
buttonSecondary,
|
||||
radioCard,
|
||||
listButton,
|
||||
radio,
|
||||
alert,
|
||||
vehicleBanner,
|
||||
radioHorizontal,
|
||||
siteHeader,
|
||||
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 radio from "@/ux-components/radio/radio";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||
import siteHeader from "@/common-components/site-header/site-header";
|
||||
import radioHorizontal from "@/ux-components/radio-horizontal/radio-horizontal";
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
buttonPrimary,
|
||||
buttonSecondary,
|
||||
radioCard,
|
||||
listButton,
|
||||
radio,
|
||||
alert,
|
||||
vehicleBanner,
|
||||
radioHorizontal,
|
||||
siteHeader,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
years: [2023, 2022, 2021, 2020],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$router.navigate("SELECTED_YEAR", this.$route);
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
years: [2023, 2022, 2021, 2020],
|
||||
};
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,7 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<div class="col my-3 d-flex align-items-center">
|
||||
<loader
|
||||
sizeInRem="10"
|
||||
loaderColor="blue"
|
||||
loaderPosition="center"
|
||||
/>
|
||||
<loader sizeInRem="10" loaderColor="blue" loaderPosition="center" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -22,7 +18,7 @@ import loader from "@/ux-components/loader/loader";
|
|||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
loader
|
||||
}
|
||||
loader,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -2,16 +2,15 @@ import { shallowMount, flushPromises } from "@vue/test-utils";
|
|||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import vehicleYear from "@/layouts/vehicle-year/vehicle-year.vue";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
||||
import { nextTick } from 'vue'
|
||||
import { nextTick } from "vue";
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||
settleAllPromises: jest.fn()
|
||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||
settleAllPromises: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("vehicle-year.vue", () => {
|
||||
test("vehicle-year.vue should render data from CMS", async () => {
|
||||
|
||||
// Arrange
|
||||
|
||||
// Our mock data for our call to settleAllPromises
|
||||
|
|
@ -19,31 +18,43 @@ describe("vehicle-year.vue", () => {
|
|||
getPageContent: {
|
||||
PageHeaderWidget: [{ HeaderText: "Select a year to get started" }],
|
||||
RadioQuestionWidget: [{ QuestionText: "What year is your vehicle?" }],
|
||||
VehicleBannerWidget: [{ GenericVehicleImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3" }],
|
||||
SiteHeaderWidget: [{ "LogoImage": "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3" }],
|
||||
VehicleBannerWidget: [
|
||||
{
|
||||
GenericVehicleImage:
|
||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||
},
|
||||
],
|
||||
SiteHeaderWidget: [
|
||||
{
|
||||
LogoImage:
|
||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
||||
},
|
||||
],
|
||||
isCmsContentReady: true,
|
||||
},
|
||||
getVehicleYear: [2023, 2022, 2021],
|
||||
store: {
|
||||
commit: jest.fn(),
|
||||
year: null
|
||||
year: null,
|
||||
},
|
||||
router: {
|
||||
push: jest.fn()
|
||||
}
|
||||
}
|
||||
push: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
// our router information needed.
|
||||
const to = {
|
||||
query: {
|
||||
fmgPage: 'vehicle-year'
|
||||
}
|
||||
fmgPage: "vehicle-year",
|
||||
},
|
||||
};
|
||||
|
||||
const mountOptions = getMountOptions(mockData);
|
||||
|
||||
// our mock implementation of settleAllPromises
|
||||
settleAllPromises.mockImplementation(() => { return Promise.resolve(mockData);});
|
||||
settleAllPromises.mockImplementation(() => {
|
||||
return Promise.resolve(mockData);
|
||||
});
|
||||
|
||||
// Act
|
||||
const wrapper = shallowMount(vehicleYear, mountOptions);
|
||||
|
|
@ -52,7 +63,9 @@ describe("vehicle-year.vue", () => {
|
|||
// Call our beforeRouteEnter on the component.
|
||||
// This passes (c) => c(wrapper.vm) so that next can be called and our
|
||||
// data can be set.
|
||||
vehicleYear.beforeRouteEnter.call(wrapper.vm, to, undefined, (c) => c(wrapper.vm));
|
||||
vehicleYear.beforeRouteEnter.call(wrapper.vm, to, undefined, (c) =>
|
||||
c(wrapper.vm)
|
||||
);
|
||||
|
||||
await nextTick(); // Wait for the DOM to update.
|
||||
|
||||
|
|
@ -60,7 +73,9 @@ describe("vehicle-year.vue", () => {
|
|||
const header = await wrapper.find(".Header");
|
||||
expect(header.attributes("text")).toEqual("Select a year to get started");
|
||||
|
||||
const yearQuestion = wrapper.findComponent({ name: 'year-question' });
|
||||
expect(yearQuestion.attributes("questiontext")).toEqual("What year is your vehicle?");
|
||||
const yearQuestion = wrapper.findComponent({ name: "year-question" });
|
||||
expect(yearQuestion.attributes("questiontext")).toEqual(
|
||||
"What year is your vehicle?"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,9 +2,15 @@
|
|||
<siteHeader :imageSrc="siteHeaderWidget.LogoImage" />
|
||||
<div class="select-car">
|
||||
<div class="select-car-form rounded text-center">
|
||||
<vehicleBanner :vehicleImageSrc="vehicleBannerWidget.GenericVehicleImage" />
|
||||
<vehicleBanner
|
||||
:vehicleImageSrc="vehicleBannerWidget.GenericVehicleImage"
|
||||
/>
|
||||
<pageHeader :text="pageHeaderWidgets.HeaderText" class="Header" />
|
||||
<yearQuestion :questionText="radioQuestionWidgets.QuestionText" :years="vehicleYears" v-model="selectedYear" />
|
||||
<yearQuestion
|
||||
:questionText="radioQuestionWidgets.QuestionText"
|
||||
:years="vehicleYears"
|
||||
v-model="selectedYear"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -29,16 +35,18 @@ export default {
|
|||
vehicleYears: [],
|
||||
siteHeaderWidget: {},
|
||||
vehicleBannerWidget: {},
|
||||
selectedYear: null
|
||||
selectedYear: null,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
|
||||
beforeRouteEnter(to, from, next) {
|
||||
|
||||
// Call APIs
|
||||
const contentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
const getVehicleYearPromise = store.dispatch(storeActions.GET_VEHICLE_YEARS, {});
|
||||
const getVehicleYearPromise = store.dispatch(
|
||||
storeActions.GET_VEHICLE_YEARS,
|
||||
{}
|
||||
);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
|
|
@ -52,13 +60,14 @@ export default {
|
|||
},
|
||||
];
|
||||
settleAllPromises(promiseResultMap).then((resultMap) => {
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.pageHeaderWidgets = resultMap.getPageContent.PageHeaderWidget[0];
|
||||
vm.siteHeaderWidget = resultMap.getPageContent.SiteHeaderWidget[0];
|
||||
vm.radioQuestionWidgets = resultMap.getPageContent.RadioQuestionWidget[0];
|
||||
vm.vehicleBannerWidget = resultMap.getPageContent.VehicleBannerWidget[0];
|
||||
vm.radioQuestionWidgets =
|
||||
resultMap.getPageContent.RadioQuestionWidget[0];
|
||||
vm.vehicleBannerWidget =
|
||||
resultMap.getPageContent.VehicleBannerWidget[0];
|
||||
vm.vehicleYears = resultMap.getVehicleYear;
|
||||
});
|
||||
});
|
||||
|
|
@ -66,9 +75,9 @@ export default {
|
|||
|
||||
watch: {
|
||||
selectedYear(year) {
|
||||
this.$store.commit(this.storeMutations.UPDATE_YEAR, year);
|
||||
this.$router.push('?fmgPage=vehicle-make');
|
||||
}
|
||||
this.$store.commit(this.storeMutations.UPDATE_YEAR, year);
|
||||
this.$router.push("?fmgPage=vehicle-make");
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
|
|
@ -81,15 +90,15 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.select-car {
|
||||
height: calc(100vh - 56px);
|
||||
padding: 0 1.5rem;
|
||||
.select-car {
|
||||
height: calc(100vh - 56px);
|
||||
padding: 0 1.5rem;
|
||||
|
||||
.car_list {
|
||||
// Height will be determined by overall height of content above list
|
||||
height: calc(100% - 300px);
|
||||
padding: 0 1.5rem;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
.car_list {
|
||||
// Height will be determined by overall height of content above list
|
||||
height: calc(100% - 300px);
|
||||
padding: 0 1.5rem;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,25 @@
|
|||
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
|
||||
describe('year-question.vue', () => {
|
||||
test('year-question should take a prop for years and questionText, and trigger a selectYear function when an option is clicked.', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(yearQuestion);
|
||||
await wrapper.setProps({
|
||||
questionText: 'What year is your vehicle?',
|
||||
years: ['2023', '2022', '2021'],
|
||||
modelValue: '2020'
|
||||
});
|
||||
wrapper.vm.$options.watch.selectedYear.call(wrapper.vm);
|
||||
|
||||
// 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");
|
||||
expect(wrapper.componentVM.modelValue).toBe("2020");
|
||||
describe("year-question.vue", () => {
|
||||
test("year-question should take a prop for years and questionText, and trigger a selectYear function when an option is clicked.", async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(yearQuestion);
|
||||
await wrapper.setProps({
|
||||
questionText: "What year is your vehicle?",
|
||||
years: ["2023", "2022", "2021"],
|
||||
modelValue: "2020",
|
||||
});
|
||||
});
|
||||
wrapper.vm.$options.watch.selectedYear.call(wrapper.vm);
|
||||
|
||||
// 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");
|
||||
expect(wrapper.componentVM.modelValue).toBe("2020");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,33 +1,34 @@
|
|||
<template>
|
||||
<radioQuestion class="radioQuestion"
|
||||
:questionText="questionText"
|
||||
<radioQuestion
|
||||
class="radioQuestion"
|
||||
:questionText="questionText"
|
||||
:answers="years"
|
||||
v-model="selectedYear"
|
||||
/>
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radioQuestion from "@/common-components/radio-question/radio-question";
|
||||
|
||||
export default {
|
||||
name: "year-question",
|
||||
data(){
|
||||
return {
|
||||
selectedYear: null
|
||||
}
|
||||
name: "year-question",
|
||||
data() {
|
||||
return {
|
||||
selectedYear: null,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
questionText: String,
|
||||
years: Array,
|
||||
modelValue: String,
|
||||
},
|
||||
components: {
|
||||
radioQuestion,
|
||||
},
|
||||
watch: {
|
||||
selectedYear(val) {
|
||||
this.$emit("update:modelValue", val);
|
||||
},
|
||||
props: {
|
||||
questionText: String,
|
||||
years: Array,
|
||||
modelValue: String
|
||||
},
|
||||
components: {
|
||||
radioQuestion,
|
||||
},
|
||||
watch: {
|
||||
selectedYear(val) {
|
||||
this.$emit('update:modelValue', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@ import { storeMutations } from "@/constants/store-mutations.js";
|
|||
import { widgetNames } from "@/constants/widget-names.js";
|
||||
|
||||
export default {
|
||||
data(){
|
||||
data() {
|
||||
return {
|
||||
isCmsContentReady: false
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// dispatchBlockingStoreAction(type, payload) {
|
||||
|
|
|
|||
|
|
@ -1,54 +1,53 @@
|
|||
import baseMixin from "@/mixins/base-mixin"
|
||||
import baseMixin from "@/mixins/base-mixin";
|
||||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import { widgetNames } from "@/constants/widget-names.js";
|
||||
|
||||
describe("baseMixin.js", () => {
|
||||
test('dispatchNonblockingStoreAction: calls dispatch with type and payload', () => {
|
||||
const mixIn = getMixInInstance({});
|
||||
const type = {};
|
||||
const payload = {};
|
||||
test("dispatchNonblockingStoreAction: calls dispatch with type and payload", () => {
|
||||
const mixIn = getMixInInstance({});
|
||||
const type = {};
|
||||
const payload = {};
|
||||
|
||||
mixIn.methods.dispatchNonBlockingStoreAction(type, payload);
|
||||
mixIn.methods.dispatchNonBlockingStoreAction(type, payload);
|
||||
|
||||
expect(mixIn.methods.$store.dispatch).toBeCalledWith(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' };
|
||||
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);
|
||||
mixIn.methods.dispatchNonBlockingStoreAction(type, payload, true);
|
||||
|
||||
expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload);
|
||||
});
|
||||
})
|
||||
expect(mixIn.methods.$store.dispatch).toBeCalledWith(type, payload);
|
||||
});
|
||||
});
|
||||
function getMixInInstance({ isDispatchSuccess = true }) {
|
||||
// Mock Store
|
||||
const store = {
|
||||
dispatch: jest.fn(),
|
||||
};
|
||||
|
||||
// Mock Store
|
||||
const store = {
|
||||
dispatch: jest.fn()
|
||||
}
|
||||
if (isDispatchSuccess) {
|
||||
store.dispatch.mockReturnValue(Promise.resolve());
|
||||
} else {
|
||||
store.dispatch.mockReturnValue(Promise.reject());
|
||||
}
|
||||
|
||||
if (isDispatchSuccess) {
|
||||
store.dispatch.mockReturnValue(Promise.resolve())
|
||||
} else {
|
||||
store.dispatch.mockReturnValue(Promise.reject())
|
||||
}
|
||||
// Mock Route
|
||||
const route = {
|
||||
query: {
|
||||
fmgPage: "test-page",
|
||||
},
|
||||
};
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
return baseMixIn;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,18 +66,20 @@ const routes = [
|
|||
},
|
||||
];
|
||||
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory("/fmg/"),
|
||||
routes,
|
||||
});
|
||||
|
||||
|
||||
//---------------------------------------------------------- Router Functions ----------------------------------------------------------
|
||||
|
||||
// Navigate to the next route, depending on the scenario.
|
||||
router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => {
|
||||
|
||||
router.navigate = (
|
||||
scenario,
|
||||
currentRoute,
|
||||
optionalQuery = {},
|
||||
optionalParams = {}
|
||||
) => {
|
||||
if (!scenario) {
|
||||
console.error("No scenario provided. Please review the routing table.");
|
||||
return;
|
||||
|
|
@ -88,21 +90,31 @@ router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams =
|
|||
|
||||
if (matchingScenarioMap.destinationFmgPageValue !== undefined) {
|
||||
// We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one.
|
||||
router.push({ path: '/', query: Object.assign(optionalQuery, { fmgPage: matchingScenarioMap.destinationFmgPageValue }), params: optionalParams });
|
||||
router.push({
|
||||
path: "/",
|
||||
query: Object.assign(optionalQuery, {
|
||||
fmgPage: matchingScenarioMap.destinationFmgPageValue,
|
||||
}),
|
||||
params: optionalParams,
|
||||
});
|
||||
} else if (matchingScenarioMap.destinationUrl !== undefined) {
|
||||
navigateToUrl(matchingScenarioMap.destinationUrl);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Get navigation map depeding on the scenario and the current 'page' you're on.
|
||||
router.getNavigationMap = (scenario, currentRoute) => {
|
||||
|
||||
const fmgPageValue = currentRoute.query.fmgPage;
|
||||
const matchedQueryValue = routingTable.filter(item => (item.fmgPageValue === fmgPageValue) && item.maps.filter(map => map.scenario === scenario).length > 0).map(m => m.maps.filter(map => map.scenario === scenario));
|
||||
const matchedQueryValue = routingTable
|
||||
.filter(
|
||||
(item) =>
|
||||
item.fmgPageValue === fmgPageValue &&
|
||||
item.maps.filter((map) => map.scenario === scenario).length > 0
|
||||
)
|
||||
.map((m) => m.maps.filter((map) => map.scenario === scenario));
|
||||
|
||||
return matchedQueryValue[0][0];
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------- Private Functions ----------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
const fmgPageValues = {
|
||||
VEHICLE_YEAR: 'vehicle-year',
|
||||
VEHICLE_MAKE: 'vehicle-make',
|
||||
VEHICLE_YEAR: "vehicle-year",
|
||||
VEHICLE_MAKE: "vehicle-make",
|
||||
};
|
||||
|
||||
export { fmgPageValues };
|
||||
export { fmgPageValues };
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
const navigationScenarios = {
|
||||
SELECTED_YEAR: 'SELECTED_YEAR',
|
||||
const navigationScenarios = {
|
||||
SELECTED_YEAR: "SELECTED_YEAR",
|
||||
};
|
||||
|
||||
export { navigationScenarios } ;
|
||||
export { navigationScenarios };
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
import { fmgPageValues } from '@/router/router-constants/fmgPage-values';
|
||||
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||
|
||||
const routingTable = [
|
||||
{
|
||||
fmgPageValue: fmgPageValues.VEHICLE_YEAR,
|
||||
maps: [
|
||||
{ scenario: navigationScenarios.SELECTED_YEAR, destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE }
|
||||
]
|
||||
},
|
||||
|
||||
]
|
||||
{
|
||||
fmgPageValue: fmgPageValues.VEHICLE_YEAR,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_YEAR,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export { routingTable };
|
||||
export { routingTable };
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export default createStore({
|
|||
zipCode: null,
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
licensePlate: null
|
||||
licensePlate: null,
|
||||
},
|
||||
damage: {
|
||||
isRepair: null,
|
||||
|
|
@ -52,16 +52,16 @@ export default createStore({
|
|||
isCash: null,
|
||||
},
|
||||
referralSeqNum: null,
|
||||
}
|
||||
},
|
||||
},
|
||||
applicationUser: {
|
||||
experiments: null,
|
||||
}
|
||||
},
|
||||
},
|
||||
// See IMPORTANT note at top of "state" declaration.
|
||||
|
||||
mutations: {
|
||||
updateYear(state, year){
|
||||
updateYear(state, year) {
|
||||
state.order.vehicle.year = year;
|
||||
},
|
||||
},
|
||||
|
|
@ -86,7 +86,7 @@ export default createStore({
|
|||
method: endpoints.LookupVehicleByVin.method,
|
||||
endpoint: endpoints.LookupVehicleByVin.url,
|
||||
payload: {
|
||||
"vin": vin // EX "1J4GW58S4XC541166"
|
||||
vin: vin, // EX "1J4GW58S4XC541166"
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
@ -135,6 +135,6 @@ export default createStore({
|
|||
endpoint: relativeUrl,
|
||||
payload: {},
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,121 +1,131 @@
|
|||
import store from './index'
|
||||
import globalMethods from '@/global-methods'
|
||||
import store from "./index";
|
||||
import globalMethods from "@/global-methods";
|
||||
|
||||
describe("Actions", () => {
|
||||
it("Should return list of years retrieved", async () => {
|
||||
// Arrange
|
||||
let years = [];
|
||||
it("Should return list of years retrieved", async () => {
|
||||
// Arrange
|
||||
let years = [];
|
||||
|
||||
// Act
|
||||
globalMethods.callHttpClient = jest.fn();
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: [2023,2022,2021]});
|
||||
});
|
||||
await store.dispatch('getVehicleYears')
|
||||
.then( (response) => {
|
||||
years = response.data;
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(years[0]).toBe(2023);
|
||||
// Act
|
||||
globalMethods.callHttpClient = jest.fn();
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: [2023, 2022, 2021] });
|
||||
});
|
||||
await store.dispatch("getVehicleYears").then((response) => {
|
||||
years = response.data;
|
||||
});
|
||||
|
||||
it("Should return list of makes retrieved", async () => {
|
||||
// Arrange
|
||||
let makes = [];
|
||||
// Assert
|
||||
expect(years[0]).toBe(2023);
|
||||
});
|
||||
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: ['Baic','Honda','Ford']});
|
||||
});
|
||||
await store.dispatch('getVehicleMakes', {year: 2023})
|
||||
.then( (response) => {
|
||||
makes = response.data;
|
||||
});
|
||||
it("Should return list of makes retrieved", async () => {
|
||||
// Arrange
|
||||
let makes = [];
|
||||
|
||||
// Assert
|
||||
expect(makes[0]).toBe('Baic');
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: ["Baic", "Honda", "Ford"] });
|
||||
});
|
||||
await store.dispatch("getVehicleMakes", { year: 2023 }).then((response) => {
|
||||
makes = response.data;
|
||||
});
|
||||
|
||||
it("Should return list of models retrieved", async () => {
|
||||
// Arrange
|
||||
let models = [];
|
||||
// Assert
|
||||
expect(makes[0]).toBe("Baic");
|
||||
});
|
||||
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: ['BJ40 (MEX)','Civic','Accord']});
|
||||
});
|
||||
await store.dispatch('getVehicleModels', {year: 2023, make: 'Baic'})
|
||||
.then( (response) => {
|
||||
models = response.data;
|
||||
});
|
||||
it("Should return list of models retrieved", async () => {
|
||||
// Arrange
|
||||
let models = [];
|
||||
|
||||
// Assert
|
||||
expect(models[0]).toBe('BJ40 (MEX)');
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: ["BJ40 (MEX)", "Civic", "Accord"] });
|
||||
});
|
||||
await store
|
||||
.dispatch("getVehicleModels", { year: 2023, make: "Baic" })
|
||||
.then((response) => {
|
||||
models = response.data;
|
||||
});
|
||||
|
||||
it("Should return list of styles retrieved", async () => {
|
||||
// Arrange
|
||||
let styles = [];
|
||||
// Assert
|
||||
expect(models[0]).toBe("BJ40 (MEX)");
|
||||
});
|
||||
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: ['4 DOOR UTILITY','2 DOOR']});
|
||||
});
|
||||
await store.dispatch('getVehicleStyles', {year: 2023, make: 'Baic', model: 'BJ40 (MEX)'})
|
||||
.then( (response) => {
|
||||
styles = response.data;
|
||||
});
|
||||
it("Should return list of styles retrieved", async () => {
|
||||
// Arrange
|
||||
let styles = [];
|
||||
|
||||
// Assert
|
||||
expect(styles[0]).toBe('4 DOOR UTILITY');
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: ["4 DOOR UTILITY", "2 DOOR"] });
|
||||
});
|
||||
await store
|
||||
.dispatch("getVehicleStyles", {
|
||||
year: 2023,
|
||||
make: "Baic",
|
||||
model: "BJ40 (MEX)",
|
||||
})
|
||||
.then((response) => {
|
||||
styles = response.data;
|
||||
});
|
||||
|
||||
it("Should return data from url retrieved", async () => {
|
||||
// Arrange
|
||||
let routeInfo = [];
|
||||
// Assert
|
||||
expect(styles[0]).toBe("4 DOOR UTILITY");
|
||||
});
|
||||
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: {
|
||||
Result: 'Route Info Data'
|
||||
}});
|
||||
});
|
||||
await store.dispatch('getRouteInfo', { pageName: 'vehicle-year' })
|
||||
.then( (response) => {
|
||||
routeInfo = response.data.Result;
|
||||
});
|
||||
it("Should return data from url retrieved", async () => {
|
||||
// Arrange
|
||||
let routeInfo = [];
|
||||
|
||||
// Assert
|
||||
expect(routeInfo).toBe('Route Info Data');
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
Result: "Route Info Data",
|
||||
},
|
||||
});
|
||||
});
|
||||
await store
|
||||
.dispatch("getRouteInfo", { pageName: "vehicle-year" })
|
||||
.then((response) => {
|
||||
routeInfo = response.data.Result;
|
||||
});
|
||||
|
||||
it("Should return page data from url retrieved", async () => {
|
||||
// Arrange
|
||||
let pageData = [];
|
||||
// Assert
|
||||
expect(routeInfo).toBe("Route Info Data");
|
||||
});
|
||||
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({ data: {
|
||||
Result: 'Page Info Data'
|
||||
}});
|
||||
});
|
||||
await store.dispatch('getPageData', { pageName: 'vehicle-year' })
|
||||
.then( (response) => {
|
||||
pageData = response.data.Result;
|
||||
});
|
||||
it("Should return page data from url retrieved", async () => {
|
||||
// Arrange
|
||||
let pageData = [];
|
||||
|
||||
// Assert
|
||||
expect(pageData).toBe('Page Info Data');
|
||||
// Act
|
||||
globalMethods.callHttpClient.mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
Result: "Page Info Data",
|
||||
},
|
||||
});
|
||||
});
|
||||
})
|
||||
await store
|
||||
.dispatch("getPageData", { pageName: "vehicle-year" })
|
||||
.then((response) => {
|
||||
pageData = response.data.Result;
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(pageData).toBe("Page Info Data");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Mutations", () => {
|
||||
it("Should update the year property in the store", () => {
|
||||
// Act
|
||||
store.commit('updateYear', 2020);
|
||||
it("Should update the year property in the store", () => {
|
||||
// Act
|
||||
store.commit("updateYear", 2020);
|
||||
|
||||
// Assert
|
||||
expect(store.state.order.vehicle.year).toBe(2020);
|
||||
});
|
||||
});
|
||||
// Assert
|
||||
expect(store.state.order.vehicle.year).toBe(2020);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
test.todo('some test to be written in the future');
|
||||
test.todo("some test to be written in the future");
|
||||
|
|
|
|||
|
|
@ -1,12 +1,25 @@
|
|||
<template>
|
||||
<div class="alert fade show text-center mb-0 py-2 px-3" role="alert"
|
||||
:class="[ isDismissible ? 'alert-dismissible' : '', this.alertClass ]"
|
||||
<div
|
||||
class="alert fade show text-center mb-0 py-2 px-3"
|
||||
role="alert"
|
||||
:class="[isDismissible ? 'alert-dismissible' : '', this.alertClass]"
|
||||
>
|
||||
<p class="m-0 fw-bold small alert-heading">{{ alertHeadline }}</p>
|
||||
<p class="m-0 text-body small">{{ alertCopy }}</p>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close p-2"
|
||||
data-bs-dismiss="alert"
|
||||
aria-label="Close"
|
||||
>
|
||||
<p class="m-0 fw-bold small alert-heading">{{alertHeadline}}</p>
|
||||
<p class="m-0 text-body small">{{alertCopy}}</p>
|
||||
<button type="button" class="btn-close p-2" data-bs-dismiss="alert" aria-label="Close">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23.7 23.7" xml:space="preserve">
|
||||
<path d="m23.24 2.7-9.15 9.15L23.24 21a1.581 1.581 0 0 1-1.12 2.7c-.42 0-.82-.16-1.12-.46l-9.15-9.15-9.15 9.15c-.3.3-.7.46-1.12.46A1.581 1.581 0 0 1 .46 21l8.47-8.47.68-.68L.46 2.7c-.62-.62-.62-1.62 0-2.24.62-.62 1.62-.62 2.24 0l8.47 8.47.68.68L21 .46a1.57 1.57 0 0 1 2.23 0c.63.62.63 1.62.01 2.24z"/>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 23.7 23.7"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<path
|
||||
d="m23.24 2.7-9.15 9.15L23.24 21a1.581 1.581 0 0 1-1.12 2.7c-.42 0-.82-.16-1.12-.46l-9.15-9.15-9.15 9.15c-.3.3-.7.46-1.12.46A1.581 1.581 0 0 1 .46 21l8.47-8.47.68-.68L.46 2.7c-.62-.62-.62-1.62 0-2.24.62-.62 1.62-.62 2.24 0l8.47 8.47.68.68L21 .46a1.57 1.57 0 0 1 2.23 0c.63.62.63 1.62.01 2.24z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -26,8 +39,8 @@ export default {
|
|||
alert-warning (yellow)
|
||||
alert-info (blue)
|
||||
*/
|
||||
alertClass: String
|
||||
}
|
||||
alertClass: String,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -39,8 +52,8 @@ export default {
|
|||
.btn-close {
|
||||
background: none;
|
||||
opacity: 1;
|
||||
width: .75rem;
|
||||
height: .75rem;
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
}
|
||||
&.alert-dismissible {
|
||||
button {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
:disabled="isDisabled"
|
||||
:aria-disabled="isDisabled"
|
||||
class="btn btn-primary d-flex align-items-center py-3 px-4"
|
||||
@click='displayComponent'
|
||||
>
|
||||
@click="displayComponent"
|
||||
>
|
||||
<span class="m-0">{{ this.buttonText }}</span>
|
||||
<loader
|
||||
class="ms-2"
|
||||
v-if="display"
|
||||
v-bind:style="{width: `${sizeInRem}rem`, height: `${sizeInRem}rem`}"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"
|
||||
class="ms-2"
|
||||
v-if="display"
|
||||
v-bind:style="{ width: `${sizeInRem}rem`, height: `${sizeInRem}rem` }"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
|
|
@ -24,7 +24,7 @@ export default {
|
|||
isDisabled: Boolean,
|
||||
loaderColor: String,
|
||||
loaderPosition: String,
|
||||
sizeInRem: [Number,String]
|
||||
sizeInRem: [Number, String],
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
:disabled="isDisabled"
|
||||
:aria-disabled="isDisabled"
|
||||
class="btn btn-secondary d-flex align-items-center py-3 px-4"
|
||||
@click='displayComponent'
|
||||
>
|
||||
@click="displayComponent"
|
||||
>
|
||||
<span class="m-0">{{ this.buttonText }}</span>
|
||||
<loader
|
||||
class="ms-2"
|
||||
v-if="display"
|
||||
v-bind:style="{width: `${sizeInRem}rem`, height: `${sizeInRem}rem`}"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"
|
||||
class="ms-2"
|
||||
v-if="display"
|
||||
v-bind:style="{ width: `${sizeInRem}rem`, height: `${sizeInRem}rem` }"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
|
|
@ -24,7 +24,7 @@ export default {
|
|||
isDisabled: Boolean,
|
||||
loaderColor: String,
|
||||
loaderPosition: String,
|
||||
sizeInRem: [Number,String]
|
||||
sizeInRem: [Number, String],
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<template>
|
||||
<div class="current_car_info-text">
|
||||
<div class="d-flex align-items-center justify-content-center">
|
||||
<h2 class="text-center text-dark fs-5 d-block fw-normal mb-0">{{ text }}</h2>
|
||||
<h2 class="text-center text-dark fs-5 d-block fw-normal mb-0">
|
||||
{{ text }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
<template>
|
||||
<div class="d-flex flex-column w-100">
|
||||
<button
|
||||
class="btn list-button d-flex align-items-center justify-content-between py-3 px-4"
|
||||
@click='displayComponent'
|
||||
v-bind:class="[
|
||||
this.isError ? 'error' : '',
|
||||
]"
|
||||
class="
|
||||
btn
|
||||
list-button
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
py-3
|
||||
px-4
|
||||
"
|
||||
@click="displayComponent"
|
||||
v-bind:class="[this.isError ? 'error' : '']"
|
||||
>
|
||||
<span class="m-0">{{ this.buttonText }}</span>
|
||||
<loader
|
||||
v-if="display"
|
||||
v-bind:style="{width: `${sizeInRem}rem`, height: `${sizeInRem}rem`}"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"
|
||||
/>
|
||||
</button>
|
||||
<label class="small mt-1">{{ this.errorText }}</label>
|
||||
</div>
|
||||
<span class="m-0">{{ this.buttonText }}</span>
|
||||
<loader
|
||||
v-if="display"
|
||||
v-bind:style="{ width: `${sizeInRem}rem`, height: `${sizeInRem}rem` }"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"
|
||||
/>
|
||||
</button>
|
||||
<label class="small mt-1">{{ this.errorText }}</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -27,12 +33,12 @@ export default {
|
|||
errorText: String,
|
||||
loaderColor: String,
|
||||
loaderPosition: String,
|
||||
sizeInRem: [Number,String]
|
||||
sizeInRem: [Number, String],
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
display: false,
|
||||
isError: false
|
||||
isError: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<template>
|
||||
<div class="loader"
|
||||
v-bind:style="{width: `${sizeInRem}rem`, height: `${sizeInRem}rem`}"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"
|
||||
<div
|
||||
class="loader"
|
||||
v-bind:style="{ width: `${sizeInRem}rem`, height: `${sizeInRem}rem` }"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
|
|
@ -12,18 +13,18 @@ export default {
|
|||
props: {
|
||||
sizeInRem: {
|
||||
type: Number,
|
||||
default: 1
|
||||
default: 1,
|
||||
},
|
||||
/* Color options: red, green, blue, white, black */
|
||||
loaderColor: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
/* Position options: center, right, left (OPTIONAL, do NOT use on btn-* classes) */
|
||||
loaderPosition: {
|
||||
type: String
|
||||
}
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
@ -31,7 +32,7 @@ export default {
|
|||
display: flex;
|
||||
//Open an overlay to prevent page interaction
|
||||
&:before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
|
@ -43,7 +44,7 @@ export default {
|
|||
}
|
||||
//Spinner basics
|
||||
&:after {
|
||||
content: '';
|
||||
content: "";
|
||||
mask: url(../../assets/img/icons/spinner.svg);
|
||||
mask-size: cover;
|
||||
position: relative;
|
||||
|
|
@ -52,7 +53,7 @@ export default {
|
|||
animation: rotation 1s infinite linear;
|
||||
@keyframes rotation {
|
||||
100% {
|
||||
transform:rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -70,7 +71,8 @@ export default {
|
|||
left: 1rem;
|
||||
}
|
||||
//Spinner color
|
||||
&:after { //Default spinner color (blue) if no other color is specified from the options below
|
||||
&:after {
|
||||
//Default spinner color (blue) if no other color is specified from the options below
|
||||
background-color: $blue;
|
||||
}
|
||||
&.red:after {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ describe("radio.vue", () => {
|
|||
loaderColor: "blue",
|
||||
loaderPosition: "right",
|
||||
sizeInRem: "1.5",
|
||||
errorMessage: 'null'
|
||||
errorMessage: "null",
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -20,14 +20,14 @@ describe("radio.vue", () => {
|
|||
const label = wrapper.find("label");
|
||||
const paragraph = wrapper.find("span");
|
||||
|
||||
await label.trigger('click');
|
||||
await label.trigger("click");
|
||||
|
||||
expect(input.attributes()).toEqual({
|
||||
id: "2023",
|
||||
type: "radio",
|
||||
value: "2023",
|
||||
name: "TestGroup",
|
||||
"aria-required": "true"
|
||||
"aria-required": "true",
|
||||
});
|
||||
|
||||
expect(label.attributes()).toEqual({
|
||||
|
|
@ -35,14 +35,13 @@ describe("radio.vue", () => {
|
|||
tabindex: "-1",
|
||||
for: "2023",
|
||||
class: "d-flex flex-column justify-content-center py-3 px-4 last-item",
|
||||
"aria-checked": "false"
|
||||
"aria-checked": "false",
|
||||
});
|
||||
|
||||
expect(label.text()).toEqual('2023');
|
||||
expect(label.text()).toEqual("2023");
|
||||
|
||||
expect(paragraph.text()).toEqual('2023');
|
||||
expect(paragraph.text()).toEqual("2023");
|
||||
|
||||
expect(wrapper.vm.display).toBe(true);
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,13 +8,34 @@
|
|||
<template>
|
||||
<!-- IMPORTANT: Refrain from using more than 4 horizontal radio buttons on desktop, 3 on mobile. -->
|
||||
<div class="col radiogroup radio-horizontal d-flex flex-column mb-2">
|
||||
<input type="radio" :id="radioID" :name="groupName" :value="radioID" aria-required="true" @keyup.space="displayComponent"/>
|
||||
<label role="radio" tabindex="-1" aria-checked="false" :for="radioID" class="d-flex flex-column justify-content-center py-3 px-4" :class="isFirstOrLastButton" @click='displayComponent'>
|
||||
<span class="m-0" :class="[this.textPosition]">{{radioID}}</span>
|
||||
<span class="m-0 small" :class="[this.textPosition]">{{radioLabelSubCopy}}</span>
|
||||
<loader v-if="display" :style="{width: `${sizeInRem}rem`, height: `${sizeInRem}rem`}" :class="[this.loaderColor, this.loaderPosition]" />
|
||||
<input
|
||||
type="radio"
|
||||
:id="radioID"
|
||||
:name="groupName"
|
||||
:value="radioID"
|
||||
aria-required="true"
|
||||
@keyup.space="displayComponent"
|
||||
/>
|
||||
<label
|
||||
role="radio"
|
||||
tabindex="-1"
|
||||
aria-checked="false"
|
||||
:for="radioID"
|
||||
class="d-flex flex-column justify-content-center py-3 px-4"
|
||||
:class="isFirstOrLastButton"
|
||||
@click="displayComponent"
|
||||
>
|
||||
<span class="m-0" :class="[this.textPosition]">{{ radioID }}</span>
|
||||
<span class="m-0 small" :class="[this.textPosition]">{{
|
||||
radioLabelSubCopy
|
||||
}}</span>
|
||||
<loader
|
||||
v-if="display"
|
||||
:style="{ width: `${sizeInRem}rem`, height: `${sizeInRem}rem` }"
|
||||
:class="[this.loaderColor, this.loaderPosition]"
|
||||
/>
|
||||
</label>
|
||||
<p class="small">{{errorMessage}}</p>
|
||||
<p class="small">{{ errorMessage }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -23,42 +44,52 @@ import loader from "@/ux-components/loader/loader";
|
|||
export default {
|
||||
name: "radioHorizontal",
|
||||
props: {
|
||||
groupName: String, /* Required, unique for each radio button GROUP */
|
||||
radioID: String, /* Required, unique for each radio button. Used for button id, label and <label for> */
|
||||
radioLabelSubCopy: String, /* Optional, used for multi-line radio buttons */
|
||||
textPosition: String, /* Optional, use Bootstrap classes: text-start, text-center, text-end. Default (empty) is text-start */
|
||||
errorMessage: String, /* Optional, if there is an error message to be displayed */
|
||||
loaderColor: String, /* Specify color of loader/spinner. Options are blue, red, green, white, black. Default is blue */
|
||||
loaderPosition: String, /* Specify horizontal position of loader/spinner. Options are center, right, left */
|
||||
sizeInRem: [Number,String], /* Specify size of loader/spinner in rem. Example: 1.5 (equals 24px (16x1.5)) */
|
||||
totalInGroup: Number, /* Required, total number of radio buttons in group. Used to tell first and last in group to apply border radius. */
|
||||
positionInGroup: Number /* Rquired, position of radio button in group. Example, 1,2,3 */
|
||||
groupName: String /* Required, unique for each radio button GROUP */,
|
||||
radioID:
|
||||
String /* Required, unique for each radio button. Used for button id, label and <label for> */,
|
||||
radioLabelSubCopy: String /* Optional, used for multi-line radio buttons */,
|
||||
textPosition:
|
||||
String /* Optional, use Bootstrap classes: text-start, text-center, text-end. Default (empty) is text-start */,
|
||||
errorMessage:
|
||||
String /* Optional, if there is an error message to be displayed */,
|
||||
loaderColor:
|
||||
String /* Specify color of loader/spinner. Options are blue, red, green, white, black. Default is blue */,
|
||||
loaderPosition:
|
||||
String /* Specify horizontal position of loader/spinner. Options are center, right, left */,
|
||||
sizeInRem: [
|
||||
Number,
|
||||
String,
|
||||
] /* Specify size of loader/spinner in rem. Example: 1.5 (equals 24px (16x1.5)) */,
|
||||
totalInGroup:
|
||||
Number /* Required, total number of radio buttons in group. Used to tell first and last in group to apply border radius. */,
|
||||
positionInGroup:
|
||||
Number /* Rquired, position of radio button in group. Example, 1,2,3 */,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isError: false,
|
||||
display: false
|
||||
display: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
displayComponent() {
|
||||
this.display = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
loader,
|
||||
},
|
||||
computed: {
|
||||
isFirstOrLastButton() {
|
||||
let className = '';
|
||||
if(this.positionInGroup == this.totalInGroup) {
|
||||
className = 'last-item'
|
||||
} else if(this.positionInGroup == 1) {
|
||||
className = 'first-item'
|
||||
let className = "";
|
||||
if (this.positionInGroup == this.totalInGroup) {
|
||||
className = "last-item";
|
||||
} else if (this.positionInGroup == 1) {
|
||||
className = "first-item";
|
||||
}
|
||||
return className;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
|
@ -103,12 +134,12 @@ export default {
|
|||
}
|
||||
}
|
||||
&.first-item {
|
||||
border-bottom-left-radius: .5rem;
|
||||
border-top-left-radius: .5rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
border-top-left-radius: 0.5rem;
|
||||
}
|
||||
&.last-item {
|
||||
border-bottom-right-radius: .5rem;
|
||||
border-top-right-radius: .5rem;
|
||||
border-bottom-right-radius: 0.5rem;
|
||||
border-top-right-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ describe("radio.vue", () => {
|
|||
loaderColor: "blue",
|
||||
loaderPosition: "right",
|
||||
sizeInRem: "1.5",
|
||||
errorMessage: 'null'
|
||||
errorMessage: "null",
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -20,14 +20,14 @@ describe("radio.vue", () => {
|
|||
const label = wrapper.find("label");
|
||||
const paragraph = wrapper.find("span");
|
||||
|
||||
await label.trigger('click');
|
||||
await label.trigger("click");
|
||||
|
||||
expect(input.attributes()).toEqual({
|
||||
id: "2023",
|
||||
type: "radio",
|
||||
value: "2023",
|
||||
name: "TestGroup",
|
||||
"aria-required": "true"
|
||||
"aria-required": "true",
|
||||
});
|
||||
|
||||
expect(label.attributes()).toEqual({
|
||||
|
|
@ -35,14 +35,13 @@ describe("radio.vue", () => {
|
|||
tabindex: "-1",
|
||||
for: "2023",
|
||||
class: "d-flex flex-column justify-content-center py-3 px-4",
|
||||
"aria-checked": "false"
|
||||
"aria-checked": "false",
|
||||
});
|
||||
|
||||
expect(label.text()).toEqual('2023');
|
||||
expect(label.text()).toEqual("2023");
|
||||
|
||||
expect(paragraph.text()).toEqual('2023');
|
||||
expect(paragraph.text()).toEqual("2023");
|
||||
|
||||
expect(wrapper.vm.display).toBe(true);
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,14 +7,34 @@
|
|||
<!-- Example -->
|
||||
<!-- <h3 class="visually-hidden" id="demo-radio-group">Select Vehicle Year</h3> -->
|
||||
<div class="radiogroup radio-list-button d-flex flex-column w-100 mb-2">
|
||||
<input type="radio" :id="radioID" :name="groupName" :value="radioID" aria-required="true" @keyup.space="displayComponent">
|
||||
<label role="radio" tabindex="-1" aria-checked="false" :for="radioID" class="d-flex flex-column justify-content-center py-3 px-4" @click='displayComponent'>
|
||||
<span class="m-0" :class="[this.textPosition]">{{radioID}}</span>
|
||||
<span class="m-0 small" :class="[this.textPosition]">{{radioLabelSubCopy}}</span>
|
||||
<loader v-if="display" :style="{width: `${sizeInRem}rem`, height: `${sizeInRem}rem`}" :class="[this.loaderColor, this.loaderPosition]" />
|
||||
</label>
|
||||
<p class="small">{{errorMessage}}</p>
|
||||
</div>
|
||||
<input
|
||||
type="radio"
|
||||
:id="radioID"
|
||||
:name="groupName"
|
||||
:value="radioID"
|
||||
aria-required="true"
|
||||
@keyup.space="displayComponent"
|
||||
/>
|
||||
<label
|
||||
role="radio"
|
||||
tabindex="-1"
|
||||
aria-checked="false"
|
||||
:for="radioID"
|
||||
class="d-flex flex-column justify-content-center py-3 px-4"
|
||||
@click="displayComponent"
|
||||
>
|
||||
<span class="m-0" :class="[this.textPosition]">{{ radioID }}</span>
|
||||
<span class="m-0 small" :class="[this.textPosition]">{{
|
||||
radioLabelSubCopy
|
||||
}}</span>
|
||||
<loader
|
||||
v-if="display"
|
||||
:style="{ width: `${sizeInRem}rem`, height: `${sizeInRem}rem` }"
|
||||
:class="[this.loaderColor, this.loaderPosition]"
|
||||
/>
|
||||
</label>
|
||||
<p class="small">{{ errorMessage }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -22,19 +42,27 @@ import loader from "@/ux-components/loader/loader";
|
|||
export default {
|
||||
name: "radioList",
|
||||
props: {
|
||||
groupName: String, /* Required, unique for each radio button GROUP */
|
||||
radioID: String, /* Required, unique for each radio button. Used for button id, label and <label for> */
|
||||
radioLabelSubCopy: String, /* Optional, used for multi-line radio buttons */
|
||||
textPosition: String, /* Optional, use Bootstrap classes: text-start, text-center, text-end. Default (empty) is text-start */
|
||||
errorMessage: String, /* Optional, if there is an error message to be displayed */
|
||||
loaderColor: String, /* Specify color of loader/spinner. Options are blue, red, green, white, black. Default is blue */
|
||||
loaderPosition: String, /* Specify horizontal position of loader/spinner. Options are center, right, left */
|
||||
sizeInRem: [Number,String], /* Specify size of loader/spinner in rem. Example: 1.5 (equals 24px (16x1.5)) */
|
||||
groupName: String /* Required, unique for each radio button GROUP */,
|
||||
radioID:
|
||||
String /* Required, unique for each radio button. Used for button id, label and <label for> */,
|
||||
radioLabelSubCopy: String /* Optional, used for multi-line radio buttons */,
|
||||
textPosition:
|
||||
String /* Optional, use Bootstrap classes: text-start, text-center, text-end. Default (empty) is text-start */,
|
||||
errorMessage:
|
||||
String /* Optional, if there is an error message to be displayed */,
|
||||
loaderColor:
|
||||
String /* Specify color of loader/spinner. Options are blue, red, green, white, black. Default is blue */,
|
||||
loaderPosition:
|
||||
String /* Specify horizontal position of loader/spinner. Options are center, right, left */,
|
||||
sizeInRem: [
|
||||
Number,
|
||||
String,
|
||||
] /* Specify size of loader/spinner in rem. Example: 1.5 (equals 24px (16x1.5)) */,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isError: false,
|
||||
display: false
|
||||
display: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
Loading…
Reference in a new issue