Merge branch 'develop' into feature/CSR-18

This commit is contained in:
CarlNation 2022-04-28 07:00:50 -04:00
commit f92a18ba4f
22 changed files with 474 additions and 117 deletions

View file

@ -1,6 +1,9 @@
import { shallowMount } from "@vue/test-utils";
import buttonQuestion from "@/common-components/button-question/button-question";
import { nextTick } from "vue";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import store from "@/store";
jest.mock("@/store",()=>{return{};},{virtual:true});
describe("buttonQuestion.vue", () => {
it("Should show overflow classes on fieldset if isOverflowScrollable is true", () => {
@ -45,6 +48,65 @@ describe("buttonQuestion.vue", () => {
});
});
describe("buttonQuestion.vue", () => {
it("Fieldset classes should contain ui-radio if button type is radio", () => {
// Act
const wrapper = shallowMount(buttonQuestion, {
propsData: {
buttonType: "radio",
}
});
// Assert
const Div = wrapper.find('fieldset div');
expect(Div.classes()).toContain("ui-radio");
});
});
// testing a computed property
describe("buttonQuestion.vue", () => {
it("getColLength should return '12' if prop isWide is set to true", () => {
// Act
const localThis = { isWide: true }
expect(buttonQuestion.computed.getColLength.call(localThis)).toBe("12");
});
});
describe("buttonQuestion.vue", () => {
it("getColLength should return '' if prop isWide is set to false", () => {
// Act
const localThis = {
isWide: false,
answers: ['a', 'b']
}
expect(buttonQuestion.computed.getColLength.call(localThis)).toBe("");
});
});
describe("buttonQuestion.vue", () => {
it("Should return answer.Text if prop useTextForValue is true", async () => {
// Act
const localThis = { useTextForValue: true };
const answer = { 'Name': 'testName', 'Text': 'testText' };
// Assert
expect(buttonQuestion.methods.getValues.call(localThis, answer)).toBe('testText');
});
});
describe("buttonQuestion.vue", () => {
it("Should return answer.Name if prop useTextForValue is false and answer.Name exists", async () => {
// Act
const localThis = { useTextForValue: false };
const answer = { 'Name': 'testName', 'Text': 'testText' };
// Assert
expect(buttonQuestion.methods.getValues.call(localThis, answer)).toBe('testName');
});
});
describe("buttonQuestion.vue", () => {
it("Should trigger event modelValue change to new value on when radio button selected", async () => {
// Act
@ -76,3 +138,54 @@ describe("buttonQuestion.vue", () => {
});
});
describe("buttonQuestion.vue", () => {
it("Should add a value to this.selectedValues if prop isMultiSelect is true, checkValue is true and this.selectedValues already exists", () => {
// Act
const wrapper = shallowMount(buttonQuestion, {
propsData: {
isMultiSelect: true,
modelValue: [ 'a', 'b' ]
}
});
const val = { checkValue: true, value: "2021", }
wrapper.vm.handleCheckedChanged(val);
// Assert
expect(wrapper.vm.selectedValues).toEqual(["a", "b", "2021"]);
});
});
describe("buttonQuestion.vue", () => {
it("Should remove a value to this.selectedValues if prop isMultiSelect is true, checkValue is false and this.selectedValues already exists", () => {
// Act
const wrapper = shallowMount(buttonQuestion, {
propsData: {
isMultiSelect: true,
modelValue: [ 'a', 'b' ]
}
});
const val = { checkValue: false, value: "a", }
wrapper.vm.handleCheckedChanged(val);
// Assert
expect(wrapper.vm.selectedValues).toEqual(["b"]);
});
});
describe("buttonQuestion.vue", () => {
it("Should do nothing to this.selectedValues if this.selectedValues is not an array", () => {
// Act
const wrapper = shallowMount(buttonQuestion, {
propsData: {
isMultiSelect: true,
modelValue: 'a',
}
});
const val = { checkValue: true, value: "c", }
wrapper.vm.handleCheckedChanged(val);
// Assert
expect(wrapper.vm.selectedValues).toEqual("a");
});
});

View file

@ -5,7 +5,7 @@
<span class="fs-5 fw-bold w-100" :class="this.buttonType === 'radio' ? 'text-start' : 'text-center'">{{ questionText }}</span>
</div>
<div class="w-100 d-flex justify-content-center">
<fieldset class="w-100" :class="getFieldSetClasses" :role="isMultiSelect ? 'group' : 'radiogroup'" :aria-labelledby="groupName ? groupName + '-radio-group' : ''">
<fieldset class="w-100" :aria-required=isRequired :class="getFieldSetClasses" :role="isMultiSelect ? 'group' : 'radiogroup'" :aria-labelledby="groupName ? groupName + '-radio-group' : ''">
<legend class="sr-only" :data-focus-target="groupName" tabindex="-1">
{{(isMultiSelect && answers && answers.length > 1) ? 'Select one or more options below.' : 'Select an option below.' }}
</legend>

View file

@ -6,6 +6,7 @@
:answers="answersToDisplay"
:groupName="groupName"
buttonType="listCard"
isRequired
v-model="selectedValues"
validationRules="damage-location-required"
/>

View file

@ -11,6 +11,7 @@
v-model="selectedValues"
:validationRules="validationRules"
:suppressError="suppressError"
:isRequired=isRequired
/>
</div>
</transition>
@ -36,6 +37,7 @@ export default ({
validationRules: String,
suppressError: Boolean,
cmsWidgetName: String,
isRequired: Boolean,
},
methods: {
initializeComponent(replaceOptions){

View file

@ -10,6 +10,7 @@
buttonType="listCard"
v-model="selectedDoorSidesValues"
validationRules="damage-side-required"
isRequired
/>
</div>
</transition>
@ -22,6 +23,7 @@
filterByVehicleCategory
v-model="selectedDriverSideReplaceOptionsValues"
validationRules="driver-side-options-required"
isRequired
/>
<replaceOptionsQuestion
ref="passengerSideOptions"
@ -32,6 +34,7 @@
filterByVehicleCategory
v-model="selectedPassengerSideReplaceOptionsValues"
validationRules="passenger-side-options-required"
isRequired
/>
</div>
</template>

View file

@ -44,6 +44,7 @@
v-model="selectedRearReplaceOptions"
groupName="BackGlassReplaceOptionsQuestion"
validationRules="replace-options-required"
isRequired
/>
<funnel-footer
cmsWidgetName="FunnelFooterWidget"

View file

@ -9,6 +9,7 @@
useTextForValue
v-model="selectedChipCountValues"
:validationRules="validationRules"
isRequired
/>
</div>
</transition>

View file

@ -9,6 +9,7 @@
v-model="selectedValues"
:suppressError="suppressError"
:validationRules="validationRules"
isRequired
/>
</div>
</transition>

View file

@ -27,6 +27,7 @@
v-model="selectedWindshieldReplaceOptionsValues"
validationRules="windshield-replace-options-required|prevent-split-and-single-together"
:suppressError="hasSplitSingleConflict"
isRequired
/>
<alert
class="my-3"

View file

@ -5,7 +5,7 @@
selectingInitiatesLoad
:questionText="questionText"
:answers="makes"
groupName="Choose Vehicle Make"
groupName="ChooseVehicleMake"
textPosition="text-start"
v-model="selectedValueAsArray"
isRequired=true

View file

@ -5,7 +5,7 @@
selectingInitiatesLoad
:questionText="questionText"
:answers="models"
groupName="Choose Vehicle Model"
groupName="ChooseVehicleModel"
textPosition="text-start"
v-model="selectedValueAsArray"
isRequired=true

View file

@ -5,7 +5,7 @@
selectingInitiatesLoad
:questionText="questionText"
:answers="styles"
groupName="Choose Vehicle Style"
groupName="ChooseVehicleStyle"
textPosition="text-start"
v-model="selectedValueAsArray"
isRequired=true

View file

@ -5,7 +5,7 @@
selectingInitiatesLoad
:questionText="questionText"
:answers="years"
groupName="Choose Vehicle Year"
groupName="ChooseVehicleYear"
textPosition="text-start"
v-model="selectedValueAsArray"
isRequired=true

View file

@ -11,7 +11,7 @@
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
<div class="row my-2">
<div class="col">
<textboxQuestion cmsWidgetName="VinNumber" v-model="vin" inputId="vin" disableAutoFill validationRules="vin-required|vin-format" :isDisabled=isVinFieldReadOnly />
<textboxQuestion cmsWidgetName="VinNumber" v-model="vin" inputId="vin" isRequired disableAutoFill validationRules="vin-required|vin-format" :isDisabled=isVinFieldReadOnly />
</div>
</div>
<div class="row my-2">
@ -21,12 +21,12 @@
</div>
<div class="row my-2">
<div class="col">
<textboxQuestion cmsWidgetName="ServiceZIP" v-model="zip" inputId="zip" mask="#####" disableAutoFill validationRules="zip-required" />
<textboxQuestion cmsWidgetName="ServiceZIP" v-model="zip" inputId="zip" mask="#####" isRequired disableAutoFill validationRules="zip-required" />
</div>
</div>
<div class="row my-2">
<div class="col">
<textboxQuestion cmsWidgetName="EmailAddress" v-model="email" inputId="email" disableAutoFill validationRules="email-address-required|email-address-format" />
<textboxQuestion cmsWidgetName="EmailAddress" v-model="email" inputId="email" isRequired disableAutoFill validationRules="email-address-required|email-address-format" />
</div>
</div>
<alert

View file

@ -75,7 +75,7 @@ html {
}
input:checked:focus {
+ label {
box-shadow: 0 0 0 1px $blue;
box-shadow: 0 0 0 2.5px $blue;
border-radius: .5rem;
}
}

View file

@ -100,7 +100,7 @@ describe("list-button-horizontal.vue", () => {
const label = wrapper.find("label");
wrapper.vm.handleCheckChange = jest.fn();
wrapper.vm.handleClick();
wrapper.vm.triggerButton();
await nextTick();
@ -123,7 +123,7 @@ describe("list-button-horizontal.vue", () => {
const label = wrapper.find("label");
wrapper.vm.handleCheckChange = jest.fn();
wrapper.vm.handleClick();
wrapper.vm.triggerButton();
await nextTick();
@ -146,7 +146,7 @@ describe("list-button-horizontal.vue", () => {
const label = wrapper.find("label");
wrapper.vm.handleCheckChange = jest.fn();
wrapper.vm.handleClick();
wrapper.vm.triggerButton();
await nextTick();
@ -195,4 +195,54 @@ describe("list-button-horizontal.vue", () => {
// Assert
expect(wrapper.componentVM.checkValue).toEqual("Car-Front");
});
it("Should run handleCheckChange if selectingInitiatesLoad is false and handleInputChange is triggered", async () => {
// Act
const wrapper = shallowMount(listButtonHorizontal, {
propsData: {
selectingInitiatesLoad: false,
},
});
// Assert
wrapper.vm.handleInputChange();
await nextTick();
expect(wrapper.vm.handleCheckChange).toBeCalled;
});
it("Should do nothing if isMultiSelect is true and handleKeyupArrow is triggered", async () => {
// Act
const wrapper = shallowMount(listButtonHorizontal, {
propsData: {
isMultiSelect: true,
},
});
// Assert
wrapper.vm.handleKeyupArrow();
await nextTick();
expect(wrapper.vm.handleKeyupArrow).toHaveReturned;
});
it("Should run handleCheckChange if selectingInitiatesLoad is false and handleKeyupArrow is triggered", async () => {
// Act
const wrapper = shallowMount(listButtonHorizontal, {
propsData: {
selectingInitiatesLoad: false,
isMultiSelect: false,
},
});
// Assert
wrapper.vm.handleKeyupArrow();
await nextTick();
expect(wrapper.vm.handleCheckChange).toBeCalled;
});
});

View file

@ -2,8 +2,11 @@
<div
class="list-group list-button-horizontal d-flex flex-column w-100 mb-2"
:class="[(errors.length > 0 || hasError) ? 'has-error' : '']"
@mouseup="handleClick(value)"
@keyup.space="handleClick(value)"
@keyup.space="triggerButton()"
@keyup.up="handleKeyupArrow()"
@keyup.down="handleKeyupArrow()"
@keyup.left="handleKeyupArrow()"
@keyup.right="handleKeyupArrow()"
>
<input
:type="isMultiSelect ? 'checkbox' : 'radio'"
@ -12,13 +15,14 @@
:value="value"
:aria-required="isRequired"
v-model="checkValue"
@change="!selectingInitiatesLoad ? handleCheckChange() : ''"
@change="handleInputChange()"
/>
<label
tabindex="-1"
:for="buttonID"
:aria-labelledby="buttonID"
class="d-flex flex-column justify-content-center py-3 px-4"
@mouseup="triggerButton()"
>
<span
class="m-0"
@ -31,13 +35,16 @@
class="m-0 small"
:class="textPosition"
>
{{buttonLabelSubCopy}}
{{ buttonLabelSubCopy }}
</span>
<span v-if="screenReaderOnlyText" class="sr-only">
{{screenReaderOnlyText}}
<span
v-if="screenReaderOnlyText"
class="sr-only"
>
{{ screenReaderOnlyText }}
</span>
<loader
v-if="isLoaderDisplayed && !isMultiSelect"
v-if="isLoaderDisplayed && selectingInitiatesLoad"
:class="[loaderColor, loaderPosition]"
/>
</label>
@ -77,27 +84,47 @@ export default {
checkValue: Boolean,
};
},
created(){
if(Array.isArray(this.selectedValues)){
this.checkValue = this.isMultiSelect ? this.selectedValues.includes(this.value) : this.selectedValues[0];
created() {
if (Array.isArray(this.selectedValues)) {
this.checkValue = this.isMultiSelect
? this.selectedValues.includes(this.value)
: this.selectedValues[0];
}
},
methods: {
displayLoader() {
this.isLoaderDisplayed = true;
},
handleClick(value) {
if(this.selectingInitiatesLoad) {
this.displayLoader();
handleInputChange() {
if(!this.selectingInitiatesLoad) {
this.handleCheckChange();
}
},
handleKeyupArrow() {
if (this.isMultiSelect) {
return; // Prevent arrow keys from doing anything if element is a checkbox
}
if(!this.selectingInitiatesLoad) {
this.handleCheckChange();
}
this.handleChange(value);
this.handleChange(this.value);
},
handleCheckChange(newValue, oldValue){
const isInitialization = typeof(oldValue) === 'function';
if (!isInitialization) {
this.$emit('isCheckedChanged', { checkValue: this.checkValue, value: this.value.toString() });
triggerButton() {
if(this.selectingInitiatesLoad) {
this.displayLoader();
this.handleCheckChange();
}
this.handleChange(this.value);
},
handleCheckChange() {
const emitEvent = {
checkValue: this.checkValue, // only read on checkboxes, on handleCheckedChanged on button-question
value: this.value.toString(),
buttonId: this.buttonID && this.buttonID.toString(),
};
this.$emit("isCheckedChanged", emitEvent);
this.$emit("update:modelValue", emitEvent);
}
},
components: {
@ -105,6 +132,7 @@ export default {
},
setup(props) {
const inputType = props.isMultiSelect ? "checkbox" : "radio";
const fieldOptions = {
type: inputType,
checkedValue: props.value,
@ -118,13 +146,11 @@ export default {
}
const {
checked,
handleChange,
errors,
} = useField(props.groupName, props.validationRules, fieldOptions);
return {
checked,
handleChange,
errors,
fieldOptions, // only need to expose this for unit test purposes
@ -137,10 +163,11 @@ export default {
.list-button-horizontal {
input[type="radio"],
input[type="checkbox"] {
position: absolute;
height: 0;
opacity: 0;
width: 0;
height: 0;
position: absolute;
&:focus-visible + label {
box-shadow: 0 0 0 2.5px $blue;
z-index: 2;

View file

@ -96,11 +96,8 @@ describe("list-button.vue", () => {
});
// Assert
const label = wrapper.find("label");
wrapper.vm.handleCheckChange = jest.fn();
wrapper.vm.handleClick();
wrapper.vm.triggerButton();
await nextTick();
@ -119,10 +116,8 @@ describe("list-button.vue", () => {
});
// Assert
const label = wrapper.find("label");
wrapper.vm.handleCheckChange = jest.fn();
wrapper.vm.handleClick();
wrapper.vm.triggerButton();
await nextTick();
const loader = wrapper.find("loader-stub");
@ -140,11 +135,8 @@ describe("list-button.vue", () => {
});
// Assert
const label = wrapper.find("label");
wrapper.vm.handleCheckChange = jest.fn();
wrapper.vm.handleClick();
wrapper.vm.triggerButton();
await nextTick();
@ -197,4 +189,53 @@ describe("list-button.vue", () => {
expect(wrapper.componentVM.checkValue).toEqual("Car-Front");
});
it("Should run handleCheckChange if selectingInitiatesLoad is false and handleInputChange is triggered", async () => {
// Act
const wrapper = shallowMount(listButton, {
propsData: {
selectingInitiatesLoad: false,
},
});
// Assert
wrapper.vm.handleInputChange();
await nextTick();
expect(wrapper.vm.handleCheckChange).toBeCalled;
});
it("Should do nothing if isMultiSelect is true and handleKeyupArrow is triggered", async () => {
// Act
const wrapper = shallowMount(listButton, {
propsData: {
isMultiSelect: true,
},
});
// Assert
wrapper.vm.handleKeyupArrow();
await nextTick();
expect(wrapper.vm.handleKeyupArrow).toHaveReturned;
});
it("Should run handleCheckChange if selectingInitiatesLoad is false and handleKeyupArrow is triggered", async () => {
// Act
const wrapper = shallowMount(listButton, {
propsData: {
selectingInitiatesLoad: false,
isMultiSelect: false,
},
});
// Assert
wrapper.vm.handleKeyupArrow();
await nextTick();
expect(wrapper.vm.handleCheckChange).toBeCalled;
});
});

View file

@ -2,8 +2,11 @@
<div
class="list-group list-button d-flex flex-column w-100 mb-2"
:class="[(errors.length > 0 || hasError) ? 'has-error' : '']"
@mouseup="handleClick(value)"
@keyup.space="handleClick(value)"
@keyup.space="triggerButton()"
@keyup.up="handleKeyupArrow()"
@keyup.down="handleKeyupArrow()"
@keyup.left="handleKeyupArrow()"
@keyup.right="handleKeyupArrow()"
>
<input
:type="isMultiSelect ? 'checkbox' : 'radio'"
@ -12,13 +15,14 @@
:value="value"
:aria-required="isRequired"
v-model="checkValue"
@change="!selectingInitiatesLoad ? handleCheckChange() : ''"
@change="handleInputChange()"
>
<label
tabindex="-1"
:for="buttonID"
:aria-labelledby="buttonID"
class="d-flex flex-column justify-content-center py-3 px-4"
@mouseup="triggerButton()"
>
<span
class="m-0"
@ -40,7 +44,7 @@
{{ screenReaderOnlyText }}
</span>
<loader
v-if="isLoaderDisplayed && !isMultiSelect"
v-if="isLoaderDisplayed && selectingInitiatesLoad"
:class="[this.loaderColor, this.loaderPosition]"
/>
</label>
@ -80,33 +84,47 @@ export default {
checkValue: Boolean,
};
},
created(){
if(Array.isArray(this.selectedValues)){
this.checkValue = this.isMultiSelect ? this.selectedValues.includes(this.value) : this.selectedValues[0];
created() {
if (Array.isArray(this.selectedValues)) {
this.checkValue = this.isMultiSelect
? this.selectedValues.includes(this.value)
: this.selectedValues[0];
}
},
methods: {
displayLoader() {
this.isLoaderDisplayed = true;
},
handleClick(value) {
handleInputChange() {
if(!this.selectingInitiatesLoad) {
this.handleCheckChange();
}
},
handleKeyupArrow() {
if (this.isMultiSelect) {
return; // Prevent arrow keys from doing anything if element is a checkbox
}
if(!this.selectingInitiatesLoad) {
this.handleCheckChange();
}
this.handleChange(this.value);
},
triggerButton() {
if(this.selectingInitiatesLoad) {
this.displayLoader();
this.handleCheckChange();
}
this.handleChange(value);
this.handleChange(this.value);
},
handleCheckChange(value, oldValue){
const isInitialization = typeof(oldValue) === 'function';
if (!isInitialization) {
const emitEvent = {
checkValue: this.checkValue,
value: this.value.toString(),
buttonId: this.buttonID.toString(),
};
this.$emit('isCheckedChanged', emitEvent);
this.$emit("update:modelValue", emitEvent);
}
handleCheckChange() {
const emitEvent = {
checkValue: this.checkValue, // only read on checkboxes, on handleCheckedChanged on button-question
value: this.value.toString(),
buttonId: this.buttonID && this.buttonID.toString(),
};
this.$emit("isCheckedChanged", emitEvent);
this.$emit("update:modelValue", emitEvent);
},
},
components: {
@ -128,13 +146,11 @@ export default {
}
const {
checked,
handleChange,
errors,
} = useField(props.groupName, props.validationRules, fieldOptions);
return {
checked,
handleChange,
errors,
fieldOptions, // only need to expose this for unit test purposes
@ -154,10 +170,10 @@ export default {
opacity: 0;
&:focus-visible + label {
box-shadow: 0 0 0 2.5px $blue inset;
box-shadow: 0 0 0 2.5px $blue;
}
&:focus + label {
box-shadow: 0 0 0 2.5px $blue inset;
box-shadow: 0 0 0 2.5px $blue;
}
&:checked + label {
color: $black;
@ -165,6 +181,9 @@ export default {
background: $blue-100;
box-shadow: 0 0 0 1px $blue;
}
&:checked:focus + label {
box-shadow: 0 0 0 2.5px $blue;
}
&:checked + label p,
&:checked + label span {
font-weight: 500;

View file

@ -1,5 +1,6 @@
import { shallowMount } from "@vue/test-utils";
import listCard from "./list-card";
import { nextTick } from "vue";
describe("list-card.vue", () => {
it("Should return input type checkbox if isMultiSelect is true", async () => {
@ -18,7 +19,6 @@ describe("list-card.vue", () => {
// Assert
const input = wrapper.find("input");
expect(input.attributes().type).toEqual("checkbox");
});
@ -38,7 +38,6 @@ describe("list-card.vue", () => {
// Assert
const paragraph = wrapper.find("p");
expect(paragraph.text()).toEqual("Windshield");
});
@ -59,7 +58,6 @@ describe("list-card.vue", () => {
// Assert
const paragraph = wrapper.find("p:nth-of-type(2)");
expect(paragraph.text()).toEqual("Test");
});
@ -80,7 +78,6 @@ describe("list-card.vue", () => {
// Assert
const label = wrapper.find("label");
expect(label.attributes().for).toEqual("List Card Checkbox");
});
@ -101,7 +98,6 @@ describe("list-card.vue", () => {
// Assert
const input = wrapper.find("input");
expect(input.attributes().name).toEqual("radio 1");
});
@ -122,7 +118,6 @@ describe("list-card.vue", () => {
// Assert
const input = wrapper.find("input");
expect(input.attributes()["aria-required"]).toEqual("true");
});
@ -247,5 +242,88 @@ describe("list-card.vue", () => {
expect(wrapper.vm.fieldOptions.initialValue).toEqual([ 'Windshield' ]);
});
it("Should run handleCheckChange if selectingInitiatesLoad is false and handleInputChange is triggered", async () => {
// Act
const wrapper = shallowMount(listCard, {
propsData: {
selectingInitiatesLoad: false,
},
});
// Assert
wrapper.vm.handleInputChange();
await nextTick();
expect(wrapper.vm.handleCheckChange).toBeCalled;
});
it("Should do nothing if isMultiSelect is true and handleKeyupArrow is triggered", async () => {
// Act
const wrapper = shallowMount(listCard, {
propsData: {
isMultiSelect: true,
},
});
// Assert
wrapper.vm.handleKeyupArrow();
await nextTick();
expect(wrapper.vm.handleKeyupArrow).toHaveReturned;
});
it("Should run handleCheckChange if selectingInitiatesLoad is false and handleKeyupArrow is triggered", async () => {
// Act
const wrapper = shallowMount(listCard, {
propsData: {
selectingInitiatesLoad: false,
isMultiSelect: false,
},
});
// Assert
wrapper.vm.handleKeyupArrow();
await nextTick();
expect(wrapper.vm.handleCheckChange).toBeCalled;
});
it("Should run handleChange if triggerButton is triggered", async () => {
// Act
const wrapper = shallowMount(listCard, {
propsData: {
selectingInitiatesLoad: false,
},
});
// Assert
wrapper.vm.triggerButton();
await nextTick();
expect(wrapper.vm.handleChange).toBeCalled;
expect(wrapper.vm.handleCheckChange).not.toBeCalled;
expect(wrapper.vm.displayLoader).not.toBeCalled;
});
it("Should run handleCheckChange and displayLoader if triggerButton is triggered and seletingInitiatesLoad is true", async () => {
// Act
const wrapper = shallowMount(listCard, {
propsData: {
selectingInitiatesLoad: true,
},
});
// Assert
wrapper.vm.triggerButton();
await nextTick();
expect(wrapper.vm.handleCheckChange).toBeCalled;
expect(wrapper.vm.displayLoader).toBeCalled;
});
});

View file

@ -6,8 +6,11 @@
isWide ? 'horizontal' : '',
(errors.length > 0 || hasError) ? 'has-error' : '',
]"
@mouseup="handleChange(value)"
@keyup.space="handleChange(value)"
@keyup.space="triggerButton()"
@keyup.up="handleKeyupArrow()"
@keyup.down="handleKeyupArrow()"
@keyup.left="handleKeyupArrow()"
@keyup.right="handleKeyupArrow()"
>
<input
:type="isMultiSelect ? 'checkbox' : 'radio'"
@ -16,13 +19,15 @@
:value="value"
:aria-required="isRequired"
v-model="checkValue"
@change="handleCheckChange(value)"
@change="handleInputChange()"
/>
<label
tabindex="-1"
:for="buttonID"
:aria-labelledby="buttonID"
class="d-flex w-100 align-items-center px-2 h-100"
:class="getLabelClasses"
tabindex="-1"
@mouseup="triggerButton()"
>
<img
:id="buttonImageId"
@ -93,15 +98,6 @@ export default {
: this.selectedValues[0];
}
},
watch: {
// Changing this will impact pre-selection data loads on vehicle-parts.
// If changed, please regression test that vehicle-parts data still loads correctly with previous selections.
modelValue(newVal) {
if (newVal !== undefined) {
this.checkValue = newVal.value;
}
},
},
computed: {
getLabelClasses() {
if (this.isWide) {
@ -116,16 +112,44 @@ export default {
},
},
methods: {
handleCheckChange(newValue, oldValue) {
const isInitialization = typeof oldValue === "function";
if (!isInitialization) {
const emitEvent = {
checkValue: this.checkValue,
value: this.value.toString(),
buttonId: this.buttonID.toString(),
};
this.$emit("isCheckedChanged", emitEvent);
this.$emit("update:modelValue", emitEvent);
handleInputChange() {
if(!this.selectingInitiatesLoad) {
this.handleCheckChange();
}
},
handleKeyupArrow() {
if (this.isMultiSelect) {
return; // Prevent arrow keys from doing anything if element is a checkbox
}
if(!this.selectingInitiatesLoad) {
this.handleCheckChange();
}
this.handleChange(this.value);
},
triggerButton() {
if(this.selectingInitiatesLoad) {
this.displayLoader();
this.handleCheckChange();
}
this.handleChange(this.value);
},
handleCheckChange() {
const emitEvent = {
checkValue: this.checkValue, // only read on checkboxes, on handleCheckedChanged on button-question
value: this.value.toString(),
buttonId: this.buttonID && this.buttonID.toString(),
};
this.$emit("isCheckedChanged", emitEvent);
this.$emit("update:modelValue", emitEvent);
},
},
watch: {
// Changing this will impact pre-selection data loads on vehicle-parts.
// If changed, please regression test that vehicle-parts data still loads correctly with previous selections.
modelValue(newVal) {
if (newVal !== undefined) {
this.checkValue = newVal.value;
}
},
},
@ -213,18 +237,17 @@ export default {
box-shadow: 0 0 0 1px $blue;
border-radius: 0.5rem;
}
&:focus-visible + label {
box-shadow: 0 0 0 2.5px $blue;
border-radius: 0.5rem;
}
&:focus + label {
box-shadow: 0 0 0 2.5px $blue;
border-radius: 0.5rem;
}
&:checked {
&:focus + label {
box-shadow: 0 0 0 2.5px $blue;
}
&:checked:focus + label {
box-shadow: 0 0 0 2.5px $blue;
}
&:checked + label {
p {
color: $black;

View file

@ -56,19 +56,15 @@ export default {
handleClick(value) {
this.handleChange(value);
},
handleCheckChange(newValue, oldValue) {
const isInitialization = typeof oldValue === "function";
if (!isInitialization) {
handleCheckChange() {
const emitEvent = {
checkValue: this.checkValue,
value: this.value.toString(),
buttonID: this.buttonID && this.buttonID.toString(),
};
const emitEvent = {
checkValue: this.checkValue,
value: this.value.toString(),
buttonID: this.buttonID.toString(),
};
this.$emit("isCheckedChanged", emitEvent);
this.$emit("update:modelValue", emitEvent);
}
this.$emit("isCheckedChanged", emitEvent);
this.$emit("update:modelValue", emitEvent);
},
},
setup(props) {