Merge remote-tracking branch 'origin/develop' into feature/CSR-77
This commit is contained in:
commit
21c5316950
23 changed files with 532 additions and 233 deletions
|
|
@ -1,8 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
v-if="backButtonAction"
|
@click="handleClick"
|
||||||
@click="backButtonAction"
|
class="back-button-wrapper p-3"
|
||||||
class="back-button-wrapper p-2"
|
|
||||||
:aria-label="backButtonAccessibleText"
|
:aria-label="backButtonAccessibleText"
|
||||||
>
|
>
|
||||||
<div class="button-back">
|
<div class="button-back">
|
||||||
|
|
@ -20,12 +19,13 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
default: "",
|
default: "",
|
||||||
},
|
|
||||||
backButtonAction: {
|
|
||||||
type: Function,
|
|
||||||
default: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
handleClick() {
|
||||||
|
this.$emit('click-event');
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ describe("buttonQuestion.vue", () => {
|
||||||
wrapper.vm.chooseAnswer("2021");
|
wrapper.vm.chooseAnswer("2021");
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.find(".needed_car_info-text").text()).toEqual(
|
expect(wrapper.find(".text-center").text()).toEqual(
|
||||||
"Question Text"
|
"Question Text"
|
||||||
);
|
);
|
||||||
const buttonButtons = wrapper.findAllComponents('[data-test="button"]');
|
const buttonButtons = wrapper.findAllComponents('[data-test="button"]');
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="button_question">
|
<div class="button_question">
|
||||||
<div class="needed_car_info mt-6 mb-4 d-flex">
|
<div class="mt-6 mb-4 d-flex">
|
||||||
<span class="text-center fs-6 fw-bold w-100 needed_car_info-text">{{
|
<span class="text-center fs-6 fw-bold w-100">{{
|
||||||
questionText
|
questionText
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -32,6 +32,7 @@ import listButton from "@/ux-components/list-button/list-button";
|
||||||
export default {
|
export default {
|
||||||
name: "buttonQuestion",
|
name: "buttonQuestion",
|
||||||
props: {
|
props: {
|
||||||
|
isMultiSelect: Boolean,
|
||||||
questionText: String,
|
questionText: String,
|
||||||
answers: Array,
|
answers: Array,
|
||||||
modelValue: String,
|
modelValue: String,
|
||||||
|
|
@ -58,4 +59,4 @@ export default {
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,17 @@
|
||||||
{{ text }}
|
{{ text }}
|
||||||
</span>
|
</span>
|
||||||
<buttonBack
|
<buttonBack
|
||||||
v-if="hasBackButton"
|
v-if="hasBackButton"
|
||||||
:backButtonAction="backButtonAction"
|
:backButtonAccessibleText="backButtonAccessibleText"
|
||||||
/>
|
@click-event="clickEvent"
|
||||||
</h5>
|
/>
|
||||||
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import buttonBack from "@/ux-components/button-back/button-back";
|
import buttonBack from "@/common-components/button-back/button-back";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "FunnelSubHeader",
|
name: "FunnelSubHeader",
|
||||||
|
|
@ -26,14 +27,15 @@ export default {
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
hasBackButton: Boolean,
|
hasBackButton: Boolean,
|
||||||
backButtonUrl: String,
|
|
||||||
backButtonAccessibleText: String,
|
backButtonAccessibleText: String,
|
||||||
backButtonAction: Function,
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
buttonBack,
|
buttonBack,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
clickEvent() {
|
||||||
|
this.$emit('click-event');
|
||||||
|
},
|
||||||
initializeComponent(cmsContent) {
|
initializeComponent(cmsContent) {
|
||||||
this.text = cmsContent.HeaderText;
|
this.text = cmsContent.HeaderText;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,20 @@ export function fetchCmsContentForPage(fmgPage) {
|
||||||
|
|
||||||
response.data.Result.forEach((widget) => {
|
response.data.Result.forEach((widget) => {
|
||||||
|
|
||||||
let widgetWithReplacements = findAndReplaceGlobalStateValues(widget.Model, widget.Type);
|
let widgetWithReplacements = findAndReplaceGlobalStateValues(widget.Model, widget.Name);
|
||||||
|
|
||||||
if (Object.values(widgetNames).includes(widgetWithReplacements.Type)) {
|
// If we already have this widget, push it on the collection
|
||||||
// If we already have this widget, push it on the collection
|
if (widgetWithReplacements.Name in pageDataFromCms) {
|
||||||
if (widgetWithReplacements.Type in pageDataFromCms) {
|
pageDataFromCms[widgetWithReplacements.Name].push(widgetWithReplacements.Model);
|
||||||
pageDataFromCms[widgetWithReplacements.Type].push(widgetWithReplacements.Model);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pageDataFromCms[widgetWithReplacements.Type] = [widgetWithReplacements.Model];
|
pageDataFromCms[widgetWithReplacements.Name] = [widgetWithReplacements.Model];
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(pageDataFromCms).forEach((key) => {
|
||||||
|
if (pageDataFromCms[key].length === 1){
|
||||||
|
pageDataFromCms[key] = pageDataFromCms[key][0];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -66,10 +70,10 @@ function mapStringToState(str) {
|
||||||
|
|
||||||
// Parent function for processWidgetItemForReplacement. This will loop through the parent
|
// Parent function for processWidgetItemForReplacement. This will loop through the parent
|
||||||
// object and pass any objects that need additional processing to the processWidgetItemForReplacement function.
|
// object and pass any objects that need additional processing to the processWidgetItemForReplacement function.
|
||||||
function findAndReplaceGlobalStateValues(widgetModel, widgetType) {
|
function findAndReplaceGlobalStateValues(widgetModel, widgetName) {
|
||||||
|
|
||||||
const objWithReplacements = {
|
const objWithReplacements = {
|
||||||
Type: widgetType,
|
Name: widgetName,
|
||||||
Model: {}
|
Model: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,19 @@ describe("cms-content-helper.js", () => {
|
||||||
const cmsMockData = {
|
const cmsMockData = {
|
||||||
Result: [
|
Result: [
|
||||||
{
|
{
|
||||||
Type: "FunnelSubHeaderWidget",
|
Name: "FunnelHeaderWidget",
|
||||||
Model: {
|
Model: {
|
||||||
HeaderText: "Select a year to get started",
|
HeaderText: "Select a year to get started",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "FunnelSubHeaderWidget",
|
Name: "FunnelSubHeaderWidget",
|
||||||
Model: {
|
Model: {
|
||||||
HeaderText: "Select a model",
|
HeaderText: "Select a model",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "RadioQuestionWidget",
|
Name: "VehicleYearQuestion",
|
||||||
Model: {
|
Model: {
|
||||||
QuestionText: "What year is your vehicle?",
|
QuestionText: "What year is your vehicle?",
|
||||||
},
|
},
|
||||||
|
|
@ -40,7 +40,7 @@ describe("cms-content-helper.js", () => {
|
||||||
// Act
|
// Act
|
||||||
fetchCmsContentForPage("testPage").then((response) => {
|
fetchCmsContentForPage("testPage").then((response) => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(response.FunnelSubHeaderWidget[0].HeaderText).toEqual(
|
expect(response.FunnelHeaderWidget.HeaderText).toEqual(
|
||||||
"Select a year to get started"
|
"Select a year to get started"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -53,7 +53,7 @@ describe("cms-content-helper.js", () => {
|
||||||
const cmsMockData = {
|
const cmsMockData = {
|
||||||
Result: [
|
Result: [
|
||||||
{
|
{
|
||||||
Type: "FunnelSubHeaderWidget",
|
Name: "FunnelSubHeaderWidget",
|
||||||
Model: {
|
Model: {
|
||||||
HeaderText: "{globalState:order.vehicle.year}",
|
HeaderText: "{globalState:order.vehicle.year}",
|
||||||
},
|
},
|
||||||
|
|
@ -65,7 +65,7 @@ describe("cms-content-helper.js", () => {
|
||||||
|
|
||||||
fetchCmsContentForPage("testPage").then((response) => {
|
fetchCmsContentForPage("testPage").then((response) => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(response.FunnelSubHeaderWidget[0].HeaderText).toEqual(
|
expect(response.FunnelSubHeaderWidget.HeaderText).toEqual(
|
||||||
"2019"
|
"2019"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -78,13 +78,13 @@ describe("cms-content-helper.js", () => {
|
||||||
const cmsMockData = {
|
const cmsMockData = {
|
||||||
Result: [
|
Result: [
|
||||||
{
|
{
|
||||||
Type: "FunnelSubHeaderWidget",
|
Name: "FunnelSubHeaderWidget",
|
||||||
Model: {
|
Model: {
|
||||||
HeaderText: "{globalState:order.vehicle.year}",
|
HeaderText: "{globalState:order.vehicle.year}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "RadioQuestionWidget",
|
Name: "VehicleYearQuestion",
|
||||||
Model: {
|
Model: {
|
||||||
ExampleText: "My widget value!",
|
ExampleText: "My widget value!",
|
||||||
},
|
},
|
||||||
|
|
@ -96,8 +96,8 @@ describe("cms-content-helper.js", () => {
|
||||||
|
|
||||||
fetchCmsContentForPage("testPage").then((response) => {
|
fetchCmsContentForPage("testPage").then((response) => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(response.FunnelSubHeaderWidget[0].HeaderText).toEqual("2019");
|
expect(response.FunnelSubHeaderWidget.HeaderText).toEqual("2019");
|
||||||
expect(response.RadioQuestionWidget[0].ExampleText).toEqual("My widget value!");
|
expect(response.VehicleYearQuestion.ExampleText).toEqual("My widget value!");
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -109,13 +109,13 @@ describe("cms-content-helper.js", () => {
|
||||||
const cmsMockData = {
|
const cmsMockData = {
|
||||||
Result: [
|
Result: [
|
||||||
{
|
{
|
||||||
Type: "FunnelSubHeaderWidget",
|
Name: "FunnelSubHeaderWidget",
|
||||||
Model: {
|
Model: {
|
||||||
HeaderText: "{globalState:order.vehicle.year}",
|
HeaderText: "{globalState:order.vehicle.year}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "RadioQuestionWidget",
|
Name: "VehicleMakeQuestion",
|
||||||
Model: {
|
Model: {
|
||||||
OtherObjectInside: {
|
OtherObjectInside: {
|
||||||
ExampleText: "{globalState:order.vehicle.make}",
|
ExampleText: "{globalState:order.vehicle.make}",
|
||||||
|
|
@ -130,8 +130,8 @@ describe("cms-content-helper.js", () => {
|
||||||
fetchCmsContentForPage("testPage").then((response) => {
|
fetchCmsContentForPage("testPage").then((response) => {
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
expect(response.FunnelSubHeaderWidget[0].HeaderText).toEqual("2019");
|
expect(response.FunnelSubHeaderWidget.HeaderText).toEqual("2019");
|
||||||
expect(response.RadioQuestionWidget[0].OtherObjectInside.ExampleText).toEqual("Acura");
|
expect(response.VehicleMakeQuestion.OtherObjectInside.ExampleText).toEqual("Acura");
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -185,24 +185,6 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-2">
|
|
||||||
<div class="col">
|
|
||||||
<h6 class="mx-2 my-4">With error</h6>
|
|
||||||
<fieldset>
|
|
||||||
<legend class="sr-only">Radio button with error state</legend>
|
|
||||||
<listCard
|
|
||||||
isRadioHorizontal
|
|
||||||
buttonImage="windshield-damage.svg"
|
|
||||||
buttonLabel="Windshield"
|
|
||||||
altText=""
|
|
||||||
buttonID="Horizontal Radio Button Error State"
|
|
||||||
groupID="radio-demo-5"
|
|
||||||
buttonLabelSubCopy="Description"
|
|
||||||
hasError
|
|
||||||
/>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row my-4">
|
<div class="row my-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h4 class="m-0 p-2 bg-light rounded">List Button - Single-Line</h4>
|
<h4 class="m-0 p-2 bg-light rounded">List Button - Single-Line</h4>
|
||||||
|
|
@ -227,8 +209,6 @@
|
||||||
loaderPosition="right"
|
loaderPosition="right"
|
||||||
sizeInRem="1"
|
sizeInRem="1"
|
||||||
screenReaderOnlyText=" opens new window"
|
screenReaderOnlyText=" opens new window"
|
||||||
hasError
|
|
||||||
errorMessage="Error"
|
|
||||||
/>
|
/>
|
||||||
<listButton
|
<listButton
|
||||||
isMultiSelect
|
isMultiSelect
|
||||||
|
|
@ -495,7 +475,6 @@
|
||||||
groupName="demo-4"
|
groupName="demo-4"
|
||||||
ariaLabelBy="vehicle-model"
|
ariaLabelBy="vehicle-model"
|
||||||
buttonID="1"
|
buttonID="1"
|
||||||
buttonLabelSubCopy=""
|
|
||||||
textPosition="text-center"
|
textPosition="text-center"
|
||||||
loaderColor="blue"
|
loaderColor="blue"
|
||||||
loaderPosition="right"
|
loaderPosition="right"
|
||||||
|
|
@ -509,7 +488,6 @@
|
||||||
groupName="demo-4"
|
groupName="demo-4"
|
||||||
ariaLabelBy="vehicle-model"
|
ariaLabelBy="vehicle-model"
|
||||||
buttonID="2"
|
buttonID="2"
|
||||||
buttonLabelSubCopy=""
|
|
||||||
textPosition="text-center"
|
textPosition="text-center"
|
||||||
loaderColor="blue"
|
loaderColor="blue"
|
||||||
loaderPosition="right"
|
loaderPosition="right"
|
||||||
|
|
@ -523,7 +501,6 @@
|
||||||
groupName="demo-4"
|
groupName="demo-4"
|
||||||
ariaLabelBy="vehicle-model"
|
ariaLabelBy="vehicle-model"
|
||||||
buttonID="3"
|
buttonID="3"
|
||||||
buttonLabelSubCopy=""
|
|
||||||
textPosition="text-center"
|
textPosition="text-center"
|
||||||
loaderColor="blue"
|
loaderColor="blue"
|
||||||
loaderPosition="right"
|
loaderPosition="right"
|
||||||
|
|
@ -546,8 +523,8 @@
|
||||||
groupName="demo-4-checkbox"
|
groupName="demo-4-checkbox"
|
||||||
ariaLabelBy="vehicle-model"
|
ariaLabelBy="vehicle-model"
|
||||||
buttonID="4"
|
buttonID="4"
|
||||||
buttonLabelSubCopy=""
|
|
||||||
textPosition="text-center"
|
textPosition="text-center"
|
||||||
|
loaderEnabled=true
|
||||||
loaderColor="blue"
|
loaderColor="blue"
|
||||||
loaderPosition="right"
|
loaderPosition="right"
|
||||||
sizeInRem="1"
|
sizeInRem="1"
|
||||||
|
|
@ -559,8 +536,8 @@
|
||||||
groupName="demo-4-checkbox"
|
groupName="demo-4-checkbox"
|
||||||
ariaLabelBy="vehicle-model"
|
ariaLabelBy="vehicle-model"
|
||||||
buttonID="5"
|
buttonID="5"
|
||||||
buttonLabelSubCopy=""
|
|
||||||
textPosition="text-center"
|
textPosition="text-center"
|
||||||
|
loaderEnabled=true
|
||||||
loaderColor="blue"
|
loaderColor="blue"
|
||||||
loaderPosition="right"
|
loaderPosition="right"
|
||||||
sizeInRem="1"
|
sizeInRem="1"
|
||||||
|
|
@ -572,8 +549,8 @@
|
||||||
groupName="demo-4-checkbox"
|
groupName="demo-4-checkbox"
|
||||||
ariaLabelBy="vehicle-model"
|
ariaLabelBy="vehicle-model"
|
||||||
buttonID="6"
|
buttonID="6"
|
||||||
buttonLabelSubCopy=""
|
|
||||||
textPosition="text-center"
|
textPosition="text-center"
|
||||||
|
loaderEnabled=true
|
||||||
loaderColor="blue"
|
loaderColor="blue"
|
||||||
loaderPosition="right"
|
loaderPosition="right"
|
||||||
sizeInRem="1"
|
sizeInRem="1"
|
||||||
|
|
@ -739,7 +716,7 @@
|
||||||
<script>
|
<script>
|
||||||
import buttonPrimary from "@/ux-components/button-primary/button-primary";
|
import buttonPrimary from "@/ux-components/button-primary/button-primary";
|
||||||
import buttonSecondary from "@/ux-components/button-secondary/button-secondary";
|
import buttonSecondary from "@/ux-components/button-secondary/button-secondary";
|
||||||
import buttonBack from "@/ux-components/button-back/button-back";
|
import buttonBack from "@/common-components/button-back/button-back";
|
||||||
import listCard from "@/ux-components/list-card/list-card";
|
import listCard from "@/ux-components/list-card/list-card";
|
||||||
import listButton from "@/ux-components/list-button/list-button";
|
import listButton from "@/ux-components/list-button/list-button";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ describe("vehicle-make.vue", () => {
|
||||||
test("Make question component is initized with api data", async (done) => {
|
test("Make question component is initized with api data", async (done) => {
|
||||||
|
|
||||||
//Arrange
|
//Arrange
|
||||||
const radioQuestionCmsContent = { QuestionText: "What make is your vehicle?" };
|
const vehicleMakeQuestionCmsContent = { QuestionText: "What make is your vehicle?" };
|
||||||
const makeQuestionInitialData = ["honda", "ford", "dodge"];
|
const makeQuestionInitialData = ["honda", "ford", "dodge"];
|
||||||
const { wrapper, apiPromise } = setupMocks( {
|
const { wrapper, apiPromise } = setupMocks( {
|
||||||
radioQuestionCmsContent: radioQuestionCmsContent,
|
vehicleMakeQuestionCmsContent: vehicleMakeQuestionCmsContent,
|
||||||
makeQuestionInitialData: makeQuestionInitialData,
|
makeQuestionInitialData: makeQuestionInitialData,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ describe("vehicle-make.vue", () => {
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
apiPromise.finally(() => {
|
apiPromise.finally(() => {
|
||||||
expect(makeQuestion.methods.initializeComponent).toHaveBeenCalledWith(radioQuestionCmsContent, makeQuestionInitialData);
|
expect(makeQuestion.methods.initializeComponent).toHaveBeenCalledWith(vehicleMakeQuestionCmsContent, makeQuestionInitialData);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -122,7 +122,7 @@ describe("vehicle-make.vue", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks({
|
function setupMocks({
|
||||||
radioQuestionCmsContent = {},
|
vehicleMakeQuestionCmsContent = {},
|
||||||
makeQuestionInitialData = {},
|
makeQuestionInitialData = {},
|
||||||
pageHeaderWidgetHeaderText = {},
|
pageHeaderWidgetHeaderText = {},
|
||||||
mountOptionsMockData = {},
|
mountOptionsMockData = {},
|
||||||
|
|
@ -131,20 +131,18 @@ function setupMocks({
|
||||||
//Mock api responses
|
//Mock api responses
|
||||||
const apiResponses = {
|
const apiResponses = {
|
||||||
cmsContent: {
|
cmsContent: {
|
||||||
FunnelSubHeaderWidget: [pageHeaderWidgetHeaderText],
|
FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
|
||||||
RadioQuestionWidget: [radioQuestionCmsContent],
|
VehicleMakeQuestion: vehicleMakeQuestionCmsContent,
|
||||||
VehicleBannerWidget: [
|
VehicleBannerWidget:
|
||||||
{
|
{
|
||||||
GenericVehicleImage:
|
GenericVehicleImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||||
},
|
},
|
||||||
],
|
FunnelHeaderWidget:
|
||||||
FunnelHeaderWidget: [
|
|
||||||
{
|
{
|
||||||
LogoImage:
|
LogoImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
},
|
||||||
makeQuestionInitialData: makeQuestionInitialData,
|
makeQuestionInitialData: makeQuestionInitialData,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
ref="funnelSubHeader"
|
ref="funnelSubHeader"
|
||||||
:hasBackButton="true"
|
:hasBackButton="true"
|
||||||
backButtonAccessibleText="Change Vehicle Year"
|
backButtonAccessibleText="Change Vehicle Year"
|
||||||
:backButtonAction="backButtonAction"
|
@click-event="backButtonAction"
|
||||||
class="Header"
|
class="Header"
|
||||||
/>
|
/>
|
||||||
<makeQuestion v-model="selectedMake" ref="makeQuestion" />
|
<makeQuestion v-model="selectedMake" ref="makeQuestion" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -55,16 +55,16 @@ export default {
|
||||||
settleAllPromises(promiseResultMap).then((resultMap) => {
|
settleAllPromises(promiseResultMap).then((resultMap) => {
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget[0]);
|
vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget);
|
||||||
vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget[0]);
|
vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget);
|
||||||
vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget[0]);
|
vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget);
|
||||||
vm.$refs.makeQuestion.initializeComponent(resultMap.cmsContent.RadioQuestionWidget[0], resultMap.makeQuestionInitialData);
|
vm.$refs.makeQuestion.initializeComponent(resultMap.cmsContent.VehicleMakeQuestion, resultMap.makeQuestionInitialData);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
backButtonAction: function () {
|
backButtonAction() {
|
||||||
// route to move backwards
|
// route to move backwards
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import baseMixin from "@/mixins/base-mixin.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "model-question",
|
name: "model-question",
|
||||||
mixins: [baseMixin],
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
questionText: null,
|
questionText: null,
|
||||||
|
|
|
||||||
|
|
@ -7,44 +7,35 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
|
|
||||||
// Mock our module for promises.
|
// Mock our module for promises.
|
||||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
settleAllPromises: jest.fn(),
|
settleAllPromises: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe("vehicle-model.vue", () => {
|
describe("vehicle-model.vue", () => {
|
||||||
test("Model question component is initized with api data", async (done) => {
|
test("Model question component is initized with api data", async (done) => {
|
||||||
|
|
||||||
//Arange
|
//Arange
|
||||||
const radioQuestionCmsContent = { QuestionText: "What model is your vehicle?" };
|
const buttonQuestionContent = { QuestionText: "What model is your vehicle?" };
|
||||||
const modelQuestionInitialData = ["accord", "civic", "insight"];
|
const modelQuestionInitialData = ["accord", "civic", "insight"];
|
||||||
const { wrapper, apiPromise } = setupMocks( {
|
const { wrapper, apiPromise } = setupMocks( {
|
||||||
radioQuestionCmsContent: radioQuestionCmsContent,
|
buttonQuestionContent: buttonQuestionContent,
|
||||||
modelQuestionInitialData: modelQuestionInitialData,
|
modelQuestionInitialData: modelQuestionInitialData,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
apiPromise.finally(() => {
|
apiPromise.finally(() => {
|
||||||
expect(modelQuestion.methods.initializeComponent).toHaveBeenCalledWith(radioQuestionCmsContent, modelQuestionInitialData);
|
expect(modelQuestion.methods.initializeComponent).toHaveBeenCalledWith(buttonQuestionContent, modelQuestionInitialData);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("vehicle-model.vue", () => {
|
describe("vehicle-model.vue", () => {
|
||||||
test("Page header is initailized with api data", async (done) => {
|
test("Page header is initailized with api data", async (done) => {
|
||||||
|
|
||||||
//Arrange
|
//Arrange
|
||||||
const pageHeaderWidgetHeaderText = "Select a model to get started";
|
const pageHeaderWidgetHeaderText = "Select a model to get started";
|
||||||
const { wrapper, apiPromise } = setupMocks( { pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText });
|
const { wrapper, apiPromise } = setupMocks( { pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText });
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
apiPromise.finally(() => {
|
apiPromise.finally(() => {
|
||||||
expect(funnelSubHeader.methods.initializeComponent).toHaveBeenCalledWith(pageHeaderWidgetHeaderText);
|
expect(funnelSubHeader.methods.initializeComponent).toHaveBeenCalledWith(pageHeaderWidgetHeaderText);
|
||||||
|
|
@ -52,20 +43,16 @@ describe("vehicle-model.vue", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("vehicle-model.vue", () => {
|
describe("vehicle-model.vue", () => {
|
||||||
test("Page logo image is initailized with api data", async (done) => {
|
test("Page logo image is initailized with api data", async (done) => {
|
||||||
|
|
||||||
//Arrange
|
//Arrange
|
||||||
const SiteHeaderWidget = {
|
const SiteHeaderWidget = {
|
||||||
LogoImage:
|
LogoImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
||||||
}
|
}
|
||||||
const { wrapper, apiPromise } = setupMocks( { SiteHeaderWidget: SiteHeaderWidget});
|
const { wrapper, apiPromise } = setupMocks( { SiteHeaderWidget: SiteHeaderWidget});
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
apiPromise.finally(() => {
|
apiPromise.finally(() => {
|
||||||
expect(funnelHeader.methods.initializeComponent).toHaveBeenCalledWith(SiteHeaderWidget);
|
expect(funnelHeader.methods.initializeComponent).toHaveBeenCalledWith(SiteHeaderWidget);
|
||||||
|
|
@ -73,20 +60,16 @@ describe("vehicle-model.vue", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("vehicle-model.vue", () => {
|
describe("vehicle-model.vue", () => {
|
||||||
test("Vehicle image is initailized with api data", async (done) => {
|
test("Vehicle image is initailized with api data", async (done) => {
|
||||||
|
|
||||||
//Arrange
|
//Arrange
|
||||||
const VehicleBannerWidget = {
|
const VehicleBannerWidget = {
|
||||||
GenericVehicleImage:
|
GenericVehicleImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||||
}
|
}
|
||||||
const { wrapper, apiPromise } = setupMocks( { VehicleBannerWidget: VehicleBannerWidget});
|
const { wrapper, apiPromise } = setupMocks( { VehicleBannerWidget: VehicleBannerWidget});
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
apiPromise.finally(() => {
|
apiPromise.finally(() => {
|
||||||
expect(vehicleBanner.methods.initializeComponent).toHaveBeenCalledWith(VehicleBannerWidget);
|
expect(vehicleBanner.methods.initializeComponent).toHaveBeenCalledWith(VehicleBannerWidget);
|
||||||
|
|
@ -94,10 +77,8 @@ describe("vehicle-model.vue", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("vehicle-model.vue", () => {
|
describe("vehicle-model.vue", () => {
|
||||||
test("BackButtonAction triggers a router.navigate change", async (done) => {
|
test("BackButtonAction triggers a router.navigate change", async (done) => {
|
||||||
|
|
||||||
//Arrange
|
//Arrange
|
||||||
const { wrapper, apiPromise } = setupMocks( {
|
const { wrapper, apiPromise } = setupMocks( {
|
||||||
pageHeaderWidgetHeaderText: "Select a model to get started",
|
pageHeaderWidgetHeaderText: "Select a model to get started",
|
||||||
|
|
@ -107,12 +88,10 @@ describe("vehicle-model.vue", () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm));
|
||||||
wrapper.vm.backButtonAction();
|
wrapper.vm.backButtonAction();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
apiPromise.finally(() => {
|
apiPromise.finally(() => {
|
||||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
||||||
|
|
@ -120,37 +99,32 @@ describe("vehicle-model.vue", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks({
|
function setupMocks({
|
||||||
radioQuestionCmsContent = {},
|
buttonQuestionContent = {},
|
||||||
modelQuestionInitialData = {},
|
modelQuestionInitialData = {},
|
||||||
pageHeaderWidgetHeaderText = {},
|
pageHeaderWidgetHeaderText = {},
|
||||||
mountOptionsMockData = {},
|
mountOptionsMockData = {},
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
//Mock api responses
|
//Mock api responses
|
||||||
const apiResponses = {
|
const apiResponses = {
|
||||||
cmsContent: {
|
cmsContent: {
|
||||||
FunnelSubHeaderWidget: [pageHeaderWidgetHeaderText],
|
FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
|
||||||
RadioQuestionWidget: [radioQuestionCmsContent],
|
VehicleModelQuestion: buttonQuestionContent,
|
||||||
VehicleBannerWidget: [
|
VehicleBannerWidget:
|
||||||
{
|
{
|
||||||
GenericVehicleImage:
|
GenericVehicleImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||||
},
|
},
|
||||||
],
|
FunnelHeaderWidget:
|
||||||
FunnelHeaderWidget: [
|
|
||||||
{
|
{
|
||||||
LogoImage:
|
LogoImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
},
|
||||||
modelQuestionInitialData: modelQuestionInitialData,
|
modelQuestionInitialData: modelQuestionInitialData,
|
||||||
};
|
};
|
||||||
const apiPromise = Promise.resolve(apiResponses);
|
const apiPromise = Promise.resolve(apiResponses);
|
||||||
settleAllPromises.mockImplementation(() => apiPromise);
|
settleAllPromises.mockImplementation(() => apiPromise);
|
||||||
|
|
||||||
//Mock model question methods
|
//Mock model question methods
|
||||||
modelQuestion.methods = {
|
modelQuestion.methods = {
|
||||||
loadInitialData: jest.fn(),
|
loadInitialData: jest.fn(),
|
||||||
|
|
@ -175,6 +149,5 @@ function setupMocks({
|
||||||
vehicleBannerWrapper.vm.initializeComponent = vehicleBanner.methods.initializeComponent;
|
vehicleBannerWrapper.vm.initializeComponent = vehicleBanner.methods.initializeComponent;
|
||||||
const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" });
|
const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" });
|
||||||
funnelSubHeaderWrapper.vm.initializeComponent = funnelSubHeader.methods.initializeComponent;
|
funnelSubHeaderWrapper.vm.initializeComponent = funnelSubHeader.methods.initializeComponent;
|
||||||
|
|
||||||
return { wrapper, apiPromise };
|
return { wrapper, apiPromise };
|
||||||
}
|
}
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
ref="funnelSubHeader"
|
ref="funnelSubHeader"
|
||||||
:hasBackButton="true"
|
:hasBackButton="true"
|
||||||
backButtonAccessibleText="Change Vehicle Make"
|
backButtonAccessibleText="Change Vehicle Make"
|
||||||
:backButtonAction="backButtonAction"
|
@click-event="backButtonAction"
|
||||||
class="Header"
|
class="Header"
|
||||||
/>
|
/>
|
||||||
<modelQuestion v-model="selectedModel" ref="modelQuestion" />
|
<modelQuestion v-model="selectedModel" ref="modelQuestion" />
|
||||||
|
|
@ -55,16 +55,16 @@ export default {
|
||||||
settleAllPromises(promiseResultMap).then((resultMap) => {
|
settleAllPromises(promiseResultMap).then((resultMap) => {
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget[0]);
|
vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget);
|
||||||
vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget[0]);
|
vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget);
|
||||||
vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget[0]);
|
vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget);
|
||||||
vm.$refs.modelQuestion.initializeComponent(resultMap.cmsContent.RadioQuestionWidget[0], resultMap.modelQuestionInitialData);
|
vm.$refs.modelQuestion.initializeComponent(resultMap.cmsContent.VehicleModelQuestion, resultMap.modelQuestionInitialData);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
backButtonAction: function () {
|
backButtonAction() {
|
||||||
// route to move backwards
|
// route to move backwards
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ describe("vehicle-style.vue", () => {
|
||||||
test("Style question component is initized with api data", async (done) => {
|
test("Style question component is initized with api data", async (done) => {
|
||||||
|
|
||||||
//Arrange
|
//Arrange
|
||||||
const radioQuestionCmsContent = { QuestionText: "What style is your vehicle?" };
|
const vehicleStyleQuestionCmsContent = { QuestionText: "What style is your vehicle?" };
|
||||||
const styleQuestionInitialData = ["2 Door", "4 Door"];
|
const styleQuestionInitialData = ["2 Door", "4 Door"];
|
||||||
const { wrapper, apiPromise } = setupMocks( {
|
const { wrapper, apiPromise } = setupMocks( {
|
||||||
radioQuestionCmsContent: radioQuestionCmsContent,
|
vehicleStyleQuestionCmsContent: vehicleStyleQuestionCmsContent,
|
||||||
styleQuestionInitialData: styleQuestionInitialData,
|
styleQuestionInitialData: styleQuestionInitialData,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ describe("vehicle-style.vue", () => {
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
apiPromise.finally(() => {
|
apiPromise.finally(() => {
|
||||||
expect(styleQuestion.methods.initializeComponent).toHaveBeenCalledWith(radioQuestionCmsContent, styleQuestionInitialData);
|
expect(styleQuestion.methods.initializeComponent).toHaveBeenCalledWith(vehicleStyleQuestionCmsContent, styleQuestionInitialData);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -156,7 +156,7 @@ describe("vehicle-style.vue", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks({
|
function setupMocks({
|
||||||
radioQuestionCmsContent = {},
|
vehicleStyleQuestionCmsContent = {},
|
||||||
styleQuestionInitialData = {},
|
styleQuestionInitialData = {},
|
||||||
pageHeaderWidgetHeaderText = {},
|
pageHeaderWidgetHeaderText = {},
|
||||||
mountOptionsMockData = {},
|
mountOptionsMockData = {},
|
||||||
|
|
@ -165,20 +165,18 @@ function setupMocks({
|
||||||
//Mock api responses
|
//Mock api responses
|
||||||
const apiResponses = {
|
const apiResponses = {
|
||||||
cmsContent: {
|
cmsContent: {
|
||||||
FunnelSubHeaderWidget: [pageHeaderWidgetHeaderText],
|
FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
|
||||||
RadioQuestionWidget: [radioQuestionCmsContent],
|
VehicleStyleQuestion: vehicleStyleQuestionCmsContent,
|
||||||
VehicleBannerWidget: [
|
VehicleBannerWidget:
|
||||||
{
|
{
|
||||||
GenericVehicleImage:
|
GenericVehicleImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||||
},
|
},
|
||||||
],
|
FunnelHeaderWidget:
|
||||||
FunnelHeaderWidget: [
|
|
||||||
{
|
{
|
||||||
LogoImage:
|
LogoImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
},
|
||||||
styleQuestionInitialData: styleQuestionInitialData,
|
styleQuestionInitialData: styleQuestionInitialData,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
ref="funnelSubHeader"
|
ref="funnelSubHeader"
|
||||||
:hasBackButton="true"
|
:hasBackButton="true"
|
||||||
backButtonAccessibleText="Change Vehicle Model"
|
backButtonAccessibleText="Change Vehicle Model"
|
||||||
:backButtonAction="backButtonAction"
|
@click-event="backButtonAction"
|
||||||
class="Header"
|
class="Header"
|
||||||
/>
|
/>
|
||||||
<styleQuestion v-model="selectedStyle" ref="styleQuestion" />
|
<styleQuestion v-model="selectedStyle" ref="styleQuestion" />
|
||||||
|
|
@ -55,16 +55,16 @@ export default {
|
||||||
settleAllPromises(promiseResultMap).then((resultMap) => {
|
settleAllPromises(promiseResultMap).then((resultMap) => {
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget[0]);
|
vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget);
|
||||||
vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget[0]);
|
vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget);
|
||||||
vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget[0]);
|
vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget);
|
||||||
vm.$refs.styleQuestion.initializeComponent(resultMap.cmsContent.RadioQuestionWidget[0], resultMap.styleQuestionInitialData);
|
vm.$refs.styleQuestion.initializeComponent(resultMap.cmsContent.VehicleStyleQuestion, resultMap.styleQuestionInitialData);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
backButtonAction: function () {
|
backButtonAction() {
|
||||||
// route to move backwards
|
// route to move backwards
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ describe("vehicle-year.vue", () => {
|
||||||
test("Year question component is initized with api data", async (done) => {
|
test("Year question component is initized with api data", async (done) => {
|
||||||
|
|
||||||
//Arrange
|
//Arrange
|
||||||
const radioQuestionCmsContent = { QuestionText: "What year is your vehicle?" };
|
const vehicleYearQuestionCmsContent = { QuestionText: "What year is your vehicle?" };
|
||||||
const yearQuestionInitialData = ["2023", "2022", "2021"];
|
const yearQuestionInitialData = ["2023", "2022", "2021"];
|
||||||
const { wrapper, apiPromise } = setupMocks( {
|
const { wrapper, apiPromise } = setupMocks( {
|
||||||
radioQuestionCmsContent: radioQuestionCmsContent,
|
vehicleYearQuestionCmsContent: vehicleYearQuestionCmsContent,
|
||||||
yearQuestionInitialData: yearQuestionInitialData,
|
yearQuestionInitialData: yearQuestionInitialData,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ describe("vehicle-year.vue", () => {
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
apiPromise.finally(() => {
|
apiPromise.finally(() => {
|
||||||
expect(yearQuestion.methods.initializeComponent).toHaveBeenCalledWith(radioQuestionCmsContent, yearQuestionInitialData);
|
expect(yearQuestion.methods.initializeComponent).toHaveBeenCalledWith(vehicleYearQuestionCmsContent, yearQuestionInitialData);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -78,7 +78,7 @@ describe("vehicle-year.vue", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks({
|
function setupMocks({
|
||||||
radioQuestionCmsContent = {},
|
vehicleYearQuestionCmsContent = {},
|
||||||
yearQuestionInitialData = {},
|
yearQuestionInitialData = {},
|
||||||
pageHeaderWidgetHeaderText = {},
|
pageHeaderWidgetHeaderText = {},
|
||||||
mountOptionsMockData = {},
|
mountOptionsMockData = {},
|
||||||
|
|
@ -87,20 +87,18 @@ function setupMocks({
|
||||||
//Mock api responses
|
//Mock api responses
|
||||||
const apiResponses = {
|
const apiResponses = {
|
||||||
cmsContent: {
|
cmsContent: {
|
||||||
FunnelSubHeaderWidget: [{ HeaderText: pageHeaderWidgetHeaderText }],
|
FunnelSubHeaderWidget: { HeaderText: pageHeaderWidgetHeaderText },
|
||||||
RadioQuestionWidget: [radioQuestionCmsContent],
|
VehicleYearQuestion: vehicleYearQuestionCmsContent,
|
||||||
VehicleBannerWidget: [
|
VehicleBannerWidget:
|
||||||
{
|
{
|
||||||
GenericVehicleImage:
|
GenericVehicleImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||||
},
|
},
|
||||||
],
|
FunnelHeaderWidget:
|
||||||
FunnelHeaderWidget: [
|
|
||||||
{
|
{
|
||||||
LogoImage:
|
LogoImage:
|
||||||
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
},
|
||||||
yearQuestionInitialData: yearQuestionInitialData,
|
yearQuestionInitialData: yearQuestionInitialData,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@ export default {
|
||||||
settleAllPromises(promiseResultMap).then((resultMap) => {
|
settleAllPromises(promiseResultMap).then((resultMap) => {
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget[0]);
|
vm.$refs.funnelSubHeader.initializeComponent(resultMap.cmsContent.FunnelSubHeaderWidget);
|
||||||
vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget[0]);
|
vm.$refs.funnelHeader.initializeComponent(resultMap.cmsContent.FunnelHeaderWidget);
|
||||||
vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget[0]);
|
vm.$refs.vehicleBanner.initializeComponent(resultMap.cmsContent.VehicleBannerWidget);
|
||||||
vm.$refs.yearQuestion.initializeComponent(resultMap.cmsContent.RadioQuestionWidget[0], resultMap.yearQuestionInitialData);
|
vm.$refs.yearQuestion.initializeComponent(resultMap.cmsContent.VehicleYearQuestion, resultMap.yearQuestionInitialData);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,219 @@
|
||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from "@vue/test-utils";
|
||||||
import listButtonHorizontal from "./list-button-horizontal";
|
import listButtonHorizontal from "./list-button-horizontal";
|
||||||
|
import { nextTick } from "vue";
|
||||||
|
|
||||||
describe("list-button.vue", () => {
|
describe("list-button.vue", () => {
|
||||||
it("Should render the 'buttonID' prop value as the label and id value as well as the button value, groupName as the name value, and fire a click even that sets the display data attribute to true.", async () => {
|
|
||||||
|
it("Should return input type checkbox if isMultiSelect is true", async () => {
|
||||||
// Act
|
// Act
|
||||||
const wrapper = shallowMount(listButtonHorizontal, {
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
propsData: {
|
propsData: {
|
||||||
buttonID: "2023",
|
isMultiSelect: true,
|
||||||
groupName: "TestGroup",
|
|
||||||
loaderColor: "blue",
|
|
||||||
loaderPosition: "right",
|
|
||||||
sizeInRem: "1.5",
|
|
||||||
errorMessage: "null",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
const input = wrapper.find("input");
|
const input = wrapper.find("input");
|
||||||
const label = wrapper.find("label");
|
|
||||||
const paragraph = wrapper.find("span");
|
|
||||||
|
|
||||||
await label.trigger("click");
|
expect(input.attributes().type).toEqual("checkbox");
|
||||||
|
|
||||||
expect(input.attributes()).toEqual({
|
|
||||||
id: "2023",
|
|
||||||
type: "radio",
|
|
||||||
value: "2023",
|
|
||||||
name: "TestGroup",
|
|
||||||
"aria-required": "true",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(label.attributes()).toEqual({
|
|
||||||
tabindex: "-1",
|
|
||||||
for: "2023",
|
|
||||||
class: "d-flex flex-column justify-content-center py-3 px-4 last-item",
|
|
||||||
"aria-checked": "false",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(label.text()).toEqual("2023");
|
|
||||||
|
|
||||||
expect(paragraph.text()).toEqual("2023");
|
|
||||||
|
|
||||||
expect(wrapper.vm.isLoaderDisplayed).toBe(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should return input type radio if isMultiSelect is false or not specified", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
isMultiSelect: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const input = wrapper.find("input");
|
||||||
|
|
||||||
|
expect(input.attributes().type).toEqual("radio");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return primary label text (buttonID)", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
buttonID: "List Card Checkbox"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const label = wrapper.find("label");
|
||||||
|
|
||||||
|
expect(label.attributes().for).toEqual("List Card Checkbox");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return screen reader text", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
screenReaderOnlyText: "Screen Reader Only Text"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const paragraph = wrapper.find("span.sr-only");
|
||||||
|
|
||||||
|
expect(paragraph.text()).toEqual("Screen Reader Only Text");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return text alignment class", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
textPosition: "text-center"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const paragraph = wrapper.find("span.m-0");
|
||||||
|
|
||||||
|
expect(paragraph.attributes('class')).toContain("text-center");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return aria-required state", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
isRequired: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const input = wrapper.find("input");
|
||||||
|
|
||||||
|
expect(input.attributes()["aria-required"]).toEqual("true");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return loader enabled true", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
loaderEnabled: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
const label = wrapper.find("label");
|
||||||
|
|
||||||
|
wrapper.vm.handleClick();
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const loader = wrapper.find("loader-stub");
|
||||||
|
|
||||||
|
expect(loader.exists()).toBe(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return loader color", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
loaderColor: "blue",
|
||||||
|
loaderEnabled: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
const label = wrapper.find("label");
|
||||||
|
|
||||||
|
wrapper.vm.handleClick();
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const loader = wrapper.find("loader-stub");
|
||||||
|
|
||||||
|
expect(loader.attributes('class')).toContain("blue");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return loader position", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
loaderPosition: "right",
|
||||||
|
loaderEnabled: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
const label = wrapper.find("label");
|
||||||
|
|
||||||
|
wrapper.vm.handleClick();
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const loader = wrapper.find("loader-stub");
|
||||||
|
|
||||||
|
expect(loader.attributes('class')).toContain("right");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return loader size in rem", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
sizeInRem: 1,
|
||||||
|
loaderEnabled: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
const label = wrapper.find("label");
|
||||||
|
|
||||||
|
wrapper.vm.handleClick();
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
const loader = wrapper.find("loader-stub");
|
||||||
|
|
||||||
|
expect(loader.attributes('style')).toContain("1rem");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return first item if first item in group", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
positionInGroup: 1
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
const label = wrapper.find("label");
|
||||||
|
|
||||||
|
expect(label.attributes('class')).toContain("first-item");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return last item if last item in group", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listButtonHorizontal, {
|
||||||
|
propsData: {
|
||||||
|
positionInGroup: 3,
|
||||||
|
totalInGroup: 3
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
const label = wrapper.find("label");
|
||||||
|
|
||||||
|
expect(label.attributes('class')).toContain("last-item");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,42 +3,39 @@
|
||||||
<!-- IMPORTANT: Refrain from using more than 4 horizontal buttons on desktop, 3 on mobile. -->
|
<!-- IMPORTANT: Refrain from using more than 4 horizontal buttons on desktop, 3 on mobile. -->
|
||||||
<div v-if="isMultiSelect" class="list-group list-button-horizontal d-flex flex-column w-100 mb-2">
|
<div v-if="isMultiSelect" class="list-group list-button-horizontal d-flex flex-column w-100 mb-2">
|
||||||
<input type="checkbox" :id="buttonID" :name="groupName" :value="buttonID" :aria-required="isRequired">
|
<input type="checkbox" :id="buttonID" :name="groupName" :value="buttonID" :aria-required="isRequired">
|
||||||
<label tabindex="-1" aria-checked="false" :for="buttonID" class="d-flex flex-column justify-content-center py-3 px-4" :class="isFirstOrLastButton">
|
<label tabindex="-1" aria-checked="false" :for="buttonID" :aria-labelledby="buttonID" class="d-flex flex-column justify-content-center py-3 px-4" :class="isFirstOrLastButton">
|
||||||
<span class="m-0" :class="[this.textPosition]">{{buttonID}}</span>
|
<span class="m-0" :class="[this.textPosition]">{{buttonID}}</span>
|
||||||
<span v-if="buttonLabelSubCopy" class="m-0 small" :class="[this.textPosition]">{{buttonLabelSubCopy}}</span>
|
|
||||||
<span v-if="screenReaderOnlyText" class="sr-only">{{screenReaderOnlyText}}</span>
|
<span v-if="screenReaderOnlyText" class="sr-only">{{screenReaderOnlyText}}</span>
|
||||||
</label>
|
</label>
|
||||||
<p class="small">{{errorMessage}}</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="col list-group list-button-horizontal d-flex flex-column mb-2">
|
<div v-else class="col list-group list-button-horizontal d-flex flex-column mb-2">
|
||||||
<input type="radio" :id="buttonID" :name="groupName" :value="buttonID" aria-required="true" @keyup.space="displayLoader()"/>
|
<input type="radio" :id="buttonID" :name="groupName" :value="buttonID" aria-required="true" @keyup.space="handleClick()" @click="handleClick()" />
|
||||||
<label tabindex="-1" aria-checked="false" :for="buttonID" class="d-flex flex-column justify-content-center py-3 px-4" :class="isFirstOrLastButton" @click="displayLoader()">
|
<label tabindex="-1" aria-checked="false" :for="buttonID" :aria-labelledby="buttonID" class="d-flex flex-column justify-content-center py-3 px-4" :class="isFirstOrLastButton">
|
||||||
<span class="m-0" :class="[this.textPosition]">{{buttonID}}</span>
|
<span class="m-0" :class="textPosition">{{buttonID}}</span>
|
||||||
<span v-if="buttonLabelSubCopy" class="m-0 small" :class="[this.textPosition]">{{buttonLabelSubCopy}}</span>
|
|
||||||
<span v-if="screenReaderOnlyText" class="sr-only">{{screenReaderOnlyText}}</span>
|
<span v-if="screenReaderOnlyText" class="sr-only">{{screenReaderOnlyText}}</span>
|
||||||
<loader v-if="isLoaderDisplayed" :style="{width: `${sizeInRem}rem`, height: `${sizeInRem}rem`}" :class="[this.loaderColor, this.loaderPosition]" />
|
<loader v-if="isLoaderDisplayed" :style="{width: `${sizeInRem}rem`, height: `${sizeInRem}rem`}" :class="[loaderColor, loaderPosition]" />
|
||||||
</label>
|
</label>
|
||||||
<p class="small">{{ errorMessage }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import loader from "@/ux-components/loader/loader";
|
import loader from "@/ux-components/loader/loader";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "listButtonHorizontal",
|
name: "listButtonHorizontal",
|
||||||
props: {
|
props: {
|
||||||
isMultiSelect: Boolean,
|
isMultiSelect: Boolean, /* Defines use as checkbox */
|
||||||
groupName: String, /* Required, unique for each button GROUP */
|
groupName: String, /* Required, unique for each button GROUP */
|
||||||
buttonID: String, /* Required, unique for each button. Used for button id, label and <label for> */
|
buttonID: String, /* Required, unique for each button. Used for button id, label and <label for> */
|
||||||
buttonLabelSubCopy: String, /* Optional, used for multi-line buttons */
|
|
||||||
screenReaderOnlyText: String, /* Optional, copy to be read by screenreader */
|
screenReaderOnlyText: String, /* Optional, copy to be read by screenreader */
|
||||||
textPosition: String, /* Optional, use Bootstrap classes: text-start, text-center, text-end. Default (empty) is text-start */
|
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 */
|
loaderEnabled: Boolean, /* Optional, need to include this for loader to be used at all */
|
||||||
loaderColor: String, /* Specify color of loader/spinner. Options are blue, red, green, white, black. Default is blue */
|
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 */
|
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)) */
|
sizeInRem: Number, /* Specify size of loader/spinner in rem. Example: 1.5 (equals 24px (16x1.5)) */
|
||||||
totalInGroup: Number, /* Required, total number of buttons in group. Used to tell first and last in group to apply border radius. */
|
totalInGroup: Number, /* Required, total number of buttons in group. Used to tell first and last in group to apply border radius. */
|
||||||
positionInGroup: Number /* Rquired, position of button in group. Example, 1,2,3 */
|
positionInGroup: Number, /* Required, position of button in group. Example, 1,2,3 */
|
||||||
|
isRequired: Boolean,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -49,6 +46,9 @@ export default {
|
||||||
displayLoader() {
|
displayLoader() {
|
||||||
this.isLoaderDisplayed = true;
|
this.isLoaderDisplayed = true;
|
||||||
},
|
},
|
||||||
|
handleClick() {
|
||||||
|
this.loaderEnabled && this.displayLoader();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
loader,
|
loader,
|
||||||
|
|
@ -66,6 +66,7 @@ export default {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.list-button-horizontal {
|
.list-button-horizontal {
|
||||||
input[type="radio"],
|
input[type="radio"],
|
||||||
|
|
@ -101,13 +102,6 @@ export default {
|
||||||
+ p {
|
+ p {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
&.error {
|
|
||||||
border: 1px solid $danger;
|
|
||||||
+ p {
|
|
||||||
display: flex;
|
|
||||||
color: $danger;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.first-item {
|
&.first-item {
|
||||||
border-bottom-left-radius: 0.5rem;
|
border-bottom-left-radius: 0.5rem;
|
||||||
border-top-left-radius: 0.5rem;
|
border-top-left-radius: 0.5rem;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ describe("list-button.vue", () => {
|
||||||
loaderColor: "blue",
|
loaderColor: "blue",
|
||||||
loaderPosition: "right",
|
loaderPosition: "right",
|
||||||
sizeInRem: "1.5",
|
sizeInRem: "1.5",
|
||||||
errorMessage: "null",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,13 @@ import loader from "@/ux-components/loader/loader";
|
||||||
export default {
|
export default {
|
||||||
name: "listButton",
|
name: "listButton",
|
||||||
props: {
|
props: {
|
||||||
isMultiSelect: Boolean,
|
isMultiSelect: Boolean, /* Defines use as checkbox */
|
||||||
groupName: String, /* Required, unique for each button GROUP */
|
groupName: String, /* Required, unique for each button GROUP */
|
||||||
buttonID: [Number,String], /* Required, unique for each button. Used for button id, label and <label for> */
|
buttonID: [Number,String], /* Required, unique for each button. Used for button id, label and <label for> */
|
||||||
isRequired: Boolean, /* Optional, default is false */
|
isRequired: Boolean, /* Optional, default is false */
|
||||||
screenReaderOnlyText: String, /* Optional, copy to be read by screenreader */
|
screenReaderOnlyText: String, /* Optional, copy to be read by screenreader */
|
||||||
buttonLabelSubCopy: String, /* Optional, used for multi-line buttons */
|
buttonLabelSubCopy: String, /* Optional, used for multi-line buttons */
|
||||||
textPosition: String, /* Optional, use Bootstrap classes: text-start, text-center, text-end. Default (empty) is text-start */
|
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 */
|
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 */
|
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)) */
|
sizeInRem: [Number,String], /* Specify size of loader/spinner in rem. Example: 1.5 (equals 24px (16x1.5)) */
|
||||||
|
|
|
||||||
|
|
@ -1 +1,188 @@
|
||||||
test.todo("some test to be written in the future");
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import listCard from "./list-card";
|
||||||
|
|
||||||
|
describe("list-card.vue", () => {
|
||||||
|
|
||||||
|
it("Should return input type checkbox if isMultiSelect is true", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isMultiSelect: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "checkbox-demo-1",
|
||||||
|
groupName: "Checkbox 1",
|
||||||
|
buttonImage: "windshield-damage.svg",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const input = wrapper.find("input");
|
||||||
|
|
||||||
|
expect(input.attributes().type).toEqual("checkbox");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return input type radio if isRadio is true", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isRadio: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const input = wrapper.find("input");
|
||||||
|
|
||||||
|
expect(input.attributes().type).toEqual("radio");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return input type checkbox if isMultiSelectHorizontal is true", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isMultiSelectHorizontal: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const input = wrapper.find("input");
|
||||||
|
|
||||||
|
expect(input.attributes().type).toEqual("checkbox");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return input type radio if isRadioHorizontal is true", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isRadioHorizontal: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const input = wrapper.find("input");
|
||||||
|
|
||||||
|
expect(input.attributes().type).toEqual("radio");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return primary label text", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isRadioHorizontal: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const paragraph = wrapper.find("p");
|
||||||
|
|
||||||
|
expect(paragraph.text()).toEqual("Windshield");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return secondary (sub) label text", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isRadioHorizontal: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg",
|
||||||
|
buttonLabelSubCopy: "Test"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const paragraph = wrapper.find("p:nth-of-type(2)");
|
||||||
|
|
||||||
|
expect(paragraph.text()).toEqual("Test");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return value used for various text settings including the label 'for' and input id", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isRadioHorizontal: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg",
|
||||||
|
buttonLabelSubCopy: "Test"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const label = wrapper.find("label");
|
||||||
|
|
||||||
|
expect(label.attributes().for).toEqual("List Card Checkbox");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return input group name used for radio or checkbox", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isRadioHorizontal: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg",
|
||||||
|
buttonLabelSubCopy: "Test"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const input = wrapper.find("input");
|
||||||
|
|
||||||
|
expect(input.attributes().name).toEqual("radio 1");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return aria-required state", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(listCard, {
|
||||||
|
propsData: {
|
||||||
|
isRadioHorizontal: true,
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg",
|
||||||
|
isRequired: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const input = wrapper.find("input");
|
||||||
|
|
||||||
|
expect(input.attributes()["aria-required"]).toEqual("true");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,38 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- Heavily documented below -->
|
<!-- Heavily documented below -->
|
||||||
<div v-if="isMultiSelect" class="list-card w-100 rounded-3 d-flex align-items-center" :class="{'error': hasError}">
|
<div v-if="isMultiSelect" class="list-card w-100 rounded-3 d-flex align-items-center">
|
||||||
<input type="checkbox" :id="buttonID" :name="groupName" :value="buttonLabel" :aria-required="isRequired" />
|
<input type="checkbox" :id="buttonID" :name="groupName" :value="buttonLabel" :aria-required="isRequired" />
|
||||||
<label :for="buttonID" class="d-flex flex-column w-100 align-items-center pt-4 pb-2" tabindex="1">
|
<label :for="buttonID" class="d-flex flex-column w-100 align-items-center pt-4 pb-2" tabindex="1">
|
||||||
<img class="order-1" v-bind:src="require(`@/assets/img/icons/${buttonImage}`)" v-bind:alt="altText" />
|
<img class="order-1" v-bind:src="require(`@/assets/img/icons/${buttonImage}`)" v-bind:alt="altText" />
|
||||||
<p class="small m-0 order-3">{{buttonLabel}}</p>
|
<p class="small m-0 order-3">{{buttonLabel}}</p>
|
||||||
<p class="fs-7 m-0 order-4">{{buttonLabelSubCopy}}</p>
|
<p v-if="buttonLabelSubCopy" class="fs-7 m-0 order-4">{{buttonLabelSubCopy}}</p>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="isRadio" class="list-card w-100 rounded-3 d-flex align-items-center" :class="{'error': hasError}">
|
<div v-else-if="isRadio" class="list-card w-100 rounded-3 d-flex align-items-center">
|
||||||
<input type="radio" :id="buttonID" :name="groupName" :value="buttonID" :aria-required="isRequired" />
|
<input type="radio" :id="buttonID" :name="groupName" :value="buttonID" :aria-required="isRequired" />
|
||||||
<label :for="buttonID" class="d-flex flex-column w-100 align-items-center pt-4 pb-2" tabindex="1">
|
<label :for="buttonID" class="d-flex flex-column w-100 align-items-center pt-4 pb-2" tabindex="1">
|
||||||
<img class="order-1" v-bind:src="require(`@/assets/img/icons/${buttonImage}`)" v-bind:alt="altText" />
|
<img class="order-1" v-bind:src="require(`@/assets/img/icons/${buttonImage}`)" v-bind:alt="altText" />
|
||||||
<p class="small mt-2 mb-0 order-2">{{buttonLabel}}</p>
|
<p class="small mt-2 mb-0 order-2">{{buttonLabel}}</p>
|
||||||
<p class="fs-7 m-0 order-3">{{buttonLabelSubCopy}}</p>
|
<p v-if="buttonLabelSubCopy" class="fs-7 m-0 order-3">{{buttonLabelSubCopy}}</p>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="isMultiSelectHorizontal" class="list-card horizontal w-100 rounded-3 d-flex align-items-center" :class="{'error': hasError}">
|
<div v-else-if="isMultiSelectHorizontal" class="list-card horizontal w-100 rounded-3 d-flex align-items-center">
|
||||||
<input type="checkbox" :id="buttonID" :name="groupName" :value="buttonLabel" :aria-required="isRequired" />
|
<input type="checkbox" :id="buttonID" :name="groupName" :value="buttonLabel" :aria-required="isRequired" />
|
||||||
<label :for="buttonID" class="d-flex flex-row w-100 align-items-center py-3 ps-3 pe-8" tabindex="1" :class="{'checkboxTop': buttonLabelSubCopy}">
|
<label :for="buttonID" class="d-flex flex-row w-100 align-items-center py-3 ps-3 pe-8" tabindex="1" :class="{'checkboxTop': buttonLabelSubCopy}">
|
||||||
<img class="ms-auto order-3" v-bind:src="require(`@/assets/img/icons/${buttonImage}`)" v-bind:alt="altText" />
|
<img class="ms-auto order-3" v-bind:src="require(`@/assets/img/icons/${buttonImage}`)" v-bind:alt="altText" />
|
||||||
<div class="order-2">
|
<div class="order-2">
|
||||||
<p class="m-0 small">{{buttonLabel}}</p>
|
<p class="m-0 small">{{buttonLabel}}</p>
|
||||||
<p class="m-0 fs-7">{{buttonLabelSubCopy}}</p>
|
<p v-if="buttonLabelSubCopy" class="m-0 fs-7">{{buttonLabelSubCopy}}</p>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="isRadioHorizontal" class="list-card horizontal w-100 rounded-3 d-flex align-items-center" :class="{'error': hasError}">
|
<div v-else-if="isRadioHorizontal" class="list-card horizontal w-100 rounded-3 d-flex align-items-center">
|
||||||
<input type="radio" :id="buttonID" :name="groupName" :value="buttonLabel" :aria-required="isRequired" />
|
<input type="radio" :id="buttonID" :name="groupName" :value="buttonLabel" :aria-required="isRequired" />
|
||||||
<label :for="buttonID" class="d-flex flex-row w-100 align-items-center py-3 ps-3 pe-8" tabindex="1" :class="{'checkboxTop': buttonLabelSubCopy}">
|
<label :for="buttonID" class="d-flex flex-row w-100 align-items-center py-3 ps-3 pe-8" tabindex="1" :class="{'checkboxTop': buttonLabelSubCopy}">
|
||||||
<img class="ms-auto order-3" v-bind:src="require(`@/assets/img/icons/${buttonImage}`)" v-bind:alt="altText" />
|
<img class="ms-auto order-3" v-bind:src="require(`@/assets/img/icons/${buttonImage}`)" v-bind:alt="altText" />
|
||||||
<div class="order-2">
|
<div class="order-2">
|
||||||
<p class="m-0 small">{{buttonLabel}}</p>
|
<p class="m-0 small">{{buttonLabel}}</p>
|
||||||
<p class="m-0 fs-7">{{buttonLabelSubCopy}}</p>
|
<p v-if="buttonLabelSubCopy" class="m-0 fs-7">{{buttonLabelSubCopy}}</p>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -43,27 +43,24 @@ export default {
|
||||||
name: "listCard",
|
name: "listCard",
|
||||||
props: {
|
props: {
|
||||||
//Must choose one of the following four options
|
//Must choose one of the following four options
|
||||||
isMultiSelect: Boolean,//Defines use as checkbox
|
isMultiSelect: Boolean, //Defines use as checkbox
|
||||||
isRadio: Boolean,//Defines use as radio button
|
isRadio: Boolean, //Defines use as radio button
|
||||||
isMultiSelectHorizontal: Boolean,//Defines use as horizontal checkbox
|
isMultiSelectHorizontal: Boolean, //Defines use as horizontal checkbox
|
||||||
isRadioHorizontal: Boolean,//Defines use as horizontal radio button
|
isRadioHorizontal: Boolean, //Defines use as horizontal radio button
|
||||||
//end must choose
|
//end must choose
|
||||||
buttonImage: String,//Optional: File name of image
|
buttonImage: String,//Required: File name of image
|
||||||
buttonLabel: String,//Required: Label text
|
buttonLabel: String,//Required: Label text
|
||||||
|
isRequired: Boolean, //Required: is aria-required required or not?
|
||||||
altText: String,//Leave empty. Screen readers read the buttonLabel text. If alt has content, it will repeat unnecessarily.
|
altText: String,//Leave empty. Screen readers read the buttonLabel text. If alt has content, it will repeat unnecessarily.
|
||||||
buttonID: String,//Required: Unique
|
buttonID: String,//Required: Unique
|
||||||
groupName: String,//Rquired: Unique
|
groupName: String,//Required: Unique
|
||||||
buttonLabelSubCopy: String,//Optional: sub text
|
buttonLabelSubCopy: String,//Optional: sub tex
|
||||||
hasError: Boolean//Used to show error state
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.list-card {
|
.list-card {
|
||||||
&.error {
|
|
||||||
border: 1px solid $red !important;
|
|
||||||
}
|
|
||||||
border: 1px solid $gray-500;
|
border: 1px solid $gray-500;
|
||||||
&.invalid { //Red border if invalid
|
&.invalid { //Red border if invalid
|
||||||
border: 1px solid $red;
|
border: 1px solid $red;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue