Merge pull request #1948 from Safelite/feature/CSR-2185

CSR-2185 | Update to Node 20.17.0
This commit is contained in:
scottkiener 2024-08-27 16:51:50 -04:00 committed by GitHub
commit cbcf0b1bd2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 10906 additions and 36767 deletions

View file

@ -1,5 +1,6 @@
{ {
"tabWidth": 4, "tabWidth": 4,
"bracketSameLine": true, "bracketSameLine": true,
"printWidth": 100 "printWidth": 100,
"trailingComma" : "es5"
} }

View file

@ -18,7 +18,7 @@ pr:
resources: resources:
containers: containers:
- container: node - container: node
image: packagerepository.sagaws.net:8082/safelite/node-build:15 image: packagerepository.sagaws.net:8082/safelite/node-build:18
- container: awscli - container: awscli
image: packagerepository.sagaws.net:8082/safelite/awscli2-build:3.9 image: packagerepository.sagaws.net:8082/safelite/awscli2-build:3.9
- container: prettier-node - container: prettier-node
@ -28,7 +28,7 @@ resources:
type: github type: github
name: Safelite/AzureDevOps name: Safelite/AzureDevOps
endpoint: Safelite endpoint: Safelite
ref: refs/tags/t5.5.40 ref: refs/tags/t5.6.41
variables: variables:
- group: Digital-Infrastructure - group: Digital-Infrastructure
@ -37,15 +37,15 @@ variables:
stages: stages:
# PR's # PR's
- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: - ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
- stage: TestFormat # - stage: TestFormat
displayName: Test Code Format # displayName: Test Code Format
jobs: # jobs:
- job: checkFormatting # - job: checkFormatting
displayName: Check formatting # displayName: Check formatting
container: prettier-node # container: prettier-node
steps: # steps:
- bash: prettier --check "$(Build.SourcesDirectory)/src/**/*.(js|vue)" # - bash: prettier --check "$(Build.SourcesDirectory)/src/**/*.(js|vue)"
displayName: Run Prettier check # displayName: Run Prettier check
- stage: TestPr - stage: TestPr
displayName: Run Unit Tests For PullRequest displayName: Run Unit Tests For PullRequest

View file

@ -3,7 +3,7 @@ module.exports = {
coverageReporters: ["html", "text", "jest-junit", "cobertura"], coverageReporters: ["html", "text", "jest-junit", "cobertura"],
testResultsProcessor: "jest-junit", testResultsProcessor: "jest-junit",
preset: "@vue/cli-plugin-unit-jest", preset: "@vue/cli-plugin-unit-jest",
transform: { "^.+\\.vue$": "vue-jest" }, transform: { "^.+\\.vue$": "@vue/vue3-jest" },
moduleFileExtensions: ["js", "vue"], moduleFileExtensions: ["js", "vue"],
modulePathIgnorePatterns: ["vin-lookup"], modulePathIgnorePatterns: ["vin-lookup"],
collectCoverageFrom: [ collectCoverageFrom: [

47337
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -11,42 +11,39 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@popperjs/core": "^2.10.2",
"axios": "^0.23.0", "axios": "^0.23.0",
"bootstrap": "^5.1.1", "bootstrap": "^5.3.3",
"canvas-confetti": "^1.4.0", "core-js": "^3.38.1",
"core-js": "^3.6.5", "http-status-codes": "^2.3.0",
"http-status-codes": "^2.1.4", "iframe-resizer": "^4.4.5",
"iframe-resizer": "^4.3.7", "jest-junit": "^13.2.0",
"jest-junit": "^13.0.0",
"jquery": "^3.7.1", "jquery": "^3.7.1",
"jquery-ui": "^1.13.2", "jquery-ui": "^1.14.0",
"maska": "^1.5.0", "maska": "^1.5.2",
"vee-validate": "^4.5.7", "vee-validate": "^4.13.2",
"vue": "^3.0.0", "vue": "^3.4.38",
"vue-plugin-load-script": "^2.1.0", "vue-plugin-load-script": "^2.1.1",
"vue-router": "^4.0.11", "vue-router": "^4.4.3",
"vuex": "^4.0.2", "vuex": "^4.1.0",
"vuex-persistedstate": "^4.1.0", "vuex-persistedstate": "^4.1.0"
"yup": "^0.32.11"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0", "@babel/eslint-parser": "^7.25.1",
"@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-plugin-unit-jest": "~4.5.0", "@vue/cli-plugin-eslint": "~5.0.8",
"@vue/cli-service": "~4.5.0", "@vue/cli-plugin-unit-jest": "~5.0.8",
"@vue/compiler-sfc": "^3.0.0", "@vue/cli-service": "~5.0.8",
"@vue/eslint-config-prettier": "^6.0.0", "@vue/compiler-sfc": "^3.4.38",
"@vue/test-utils": "^2.0.0-0", "@vue/eslint-config-prettier": "^9.0.0",
"babel-eslint": "^10.1.0", "@vue/test-utils": "^2.4.6",
"eslint": "^6.7.2", "@vue/vue3-jest": "^27.0.0",
"eslint-plugin-prettier": "^3.3.1", "eslint": "8.57",
"eslint-plugin-vue": "^7.0.0", "eslint-plugin-prettier": "^5.2.1",
"prettier": "^2.2.1", "eslint-plugin-vue": "^9.27.0",
"sass": "^1.26.5", "prettier": "^3.3.3",
"sass": "^1.77.8",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"typescript": "~3.9.3", "typescript": "^4.9.5"
"vue-jest": "^5.0.0-0"
}, },
"eslintConfig": { "eslintConfig": {
"root": true, "root": true,
@ -58,7 +55,7 @@
"eslint:recommended" "eslint:recommended"
], ],
"parserOptions": { "parserOptions": {
"parser": "babel-eslint" "parser": "@babel/eslint-parser"
}, },
"rules": { "rules": {
"no-unused-vars": "off" "no-unused-vars": "off"

View file

@ -2,5 +2,12 @@ module.exports = {
env: { env: {
jest: true, jest: true,
}, },
rules: {
"vue/multi-word-component-names": "off",
"vue/valid-next-tick": "off",
"vue/no-v-text-v-html-on-component": "off",
"vue/no-reserved-component-names": "off",
"vue/require-toggle-inside-transition": "off",
},
//... //...
}; };

View file

@ -61,7 +61,7 @@ describe("baseInputButton.vue", () => {
describe("mouse clicks", () => { describe("mouse clicks", () => {
describe("checkbox", () => { describe("checkbox", () => {
describe("clicked once", () => { describe("clicked once", () => {
test("correct event and value are emitted", async () => { test("correct event and value are emitted and input is checked", async () => {
// Arrange // Arrange
const { wrapper } = setupMocks({ const { wrapper } = setupMocks({
mockData: { mockData: {
@ -71,31 +71,12 @@ describe("baseInputButton.vue", () => {
}, },
}, },
}); });
// Act // Act
await wrapper.trigger("click"); await wrapper.find("input").setChecked();
// Assert // Assert
expect(wrapper.emitted()["update:modelValue"][0][0]).toEqual(["X"]); expect(wrapper.emitted()["update:modelValue"][0][0]).toEqual(["X"]);
}); expect(wrapper.find("input").element.checked).toBe(true);
test("input is checked", async () => {
// Arrange
const { wrapper } = setupMocks({
mockData: {
propsData: {
isMultiSelect: true,
value: "X",
},
},
});
const input = wrapper.find("input");
// Act
await wrapper.trigger("click");
// Assert
expect(input.element.checked).toBe(true);
}); });
}); });
@ -135,25 +116,7 @@ describe("baseInputButton.vue", () => {
}); });
const input = wrapper.find("input"); const input = wrapper.find("input");
// Act expect(input.element.checked).toBe(true);
await wrapper.trigger("click");
// Assert
expect(input.element.checked).toBe(false);
});
test("input is unchecked", async () => {
// Arrange
const { wrapper } = setupMocks({
mockData: {
propsData: {
isMultiSelect: true,
value: "X",
modelValue: ["X"],
},
},
});
const input = wrapper.find("input");
// Act // Act
await wrapper.trigger("click"); await wrapper.trigger("click");

View file

@ -1147,7 +1147,12 @@ function setupMocks(mountOptionsMockData = {}) {
const baseMountOptions = getMountOptions( const baseMountOptions = getMountOptions(
Object.assign(defaultMountOptions, mountOptionsMockData) Object.assign(defaultMountOptions, mountOptionsMockData)
); );
const allMountOptions = Object.assign(defaultMountOptions, baseMountOptions); const allMountOptions = Object.assign(defaultMountOptions, baseMountOptions);
// Add in group name to avoid vee-validate failures
if (!allMountOptions.propsData.groupName) {
allMountOptions.propsData.groupName = "group-name";
}
return allMountOptions; return allMountOptions;
} }

View file

@ -177,8 +177,8 @@ export default {
const baseClasses = this.isOverflowScrollable const baseClasses = this.isOverflowScrollable
? "container-fluid overflow-scroll position-absolute px-5 pt-1 py-0" ? "container-fluid overflow-scroll position-absolute px-5 pt-1 py-0"
: this.buttonTypeString == "listCard" : this.buttonTypeString == "listCard"
? "w-100" ? "w-100"
: ""; : "";
const withSmallQuestionClass = this.isSmallQuestionText const withSmallQuestionClass = this.isSmallQuestionText
? baseClasses + " small-question-text" ? baseClasses + " small-question-text"
: baseClasses; : baseClasses;

View file

@ -732,7 +732,9 @@ export default {
margin: 0 auto 2rem auto; margin: 0 auto 2rem auto;
max-width: 414px; max-width: 414px;
position: relative; position: relative;
transition: height ease 2s, opacity ease 2s; transition:
height ease 2s,
opacity ease 2s;
display: grid; display: grid;
grid-template-columns: repeat(7, 1fr); grid-template-columns: repeat(7, 1fr);
justify-content: center; justify-content: center;
@ -805,7 +807,9 @@ export default {
outline: none; outline: none;
height: 1.5rem; height: 1.5rem;
opacity: 1; opacity: 1;
transition: height ease 250ms, opacity ease 250ms; transition:
height ease 250ms,
opacity ease 250ms;
input[type="radio"] { input[type="radio"] {
position: absolute; //override bootstrap position: absolute; //override bootstrap
@ -818,7 +822,9 @@ export default {
&:focus + label, &:focus + label,
&:checked:focus + label { &:checked:focus + label {
box-shadow: 0 0 0 3px #fff, 0 0 0 5.5px #1574a1; box-shadow:
0 0 0 3px #fff,
0 0 0 5.5px #1574a1;
background-color: $blue; background-color: $blue;
color: $white; color: $white;
&.current-day { &.current-day {

View file

@ -76,13 +76,17 @@ export default {
background: linear-gradient(270deg, $blue 0%, $blue-800 100%); background: linear-gradient(270deg, $blue 0%, $blue-800 100%);
} }
&:focus { &:focus {
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px,
0 0 0 5.5px $blue-700;
} }
&:focus, // Mouse, touch, stylus focus &:focus, // Mouse, touch, stylus focus
&:focus-visible { &:focus-visible {
// Keyboard focus for accessibility // Keyboard focus for accessibility
outline: none; outline: none;
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px,
0 0 0 5.5px $blue-700;
color: $white; color: $white;
background: linear-gradient(270deg, rgba(6, 87, 124, 1) 0%, rgba(6, 87, 124, 1) 100%); background: linear-gradient(270deg, rgba(6, 87, 124, 1) 0%, rgba(6, 87, 124, 1) 100%);
} }
@ -100,7 +104,9 @@ export default {
&.has-loader { &.has-loader {
color: $white; color: $white;
background: $blue-700; background: $blue-700;
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px,
0 0 0 5.5px $blue-700;
pointer-events: none; pointer-events: none;
} }
&.delay { &.delay {
@ -125,7 +131,9 @@ export default {
&:focus-visible { &:focus-visible {
// Keyboard focus for accessibility // Keyboard focus for accessibility
outline: none; outline: none;
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px $white,
0 0 0 5.5px $blue-700;
color: $white; color: $white;
@include blue-gradient; @include blue-gradient;
} }

View file

@ -174,6 +174,7 @@ describe("capabilityQuestions.vue", () => {
test("Should trigger handleCompletedQuestionChainAnswers if watched data changes", async () => { test("Should trigger handleCompletedQuestionChainAnswers if watched data changes", async () => {
// Arrange // Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.handleCompletedQuestionChainAnswers = jest.fn();
const spy = jest.spyOn(wrapper.vm, "handleCompletedQuestionChainAnswers"); const spy = jest.spyOn(wrapper.vm, "handleCompletedQuestionChainAnswers");
// Act // Act

View file

@ -215,9 +215,10 @@ describe("estimate.vue", () => {
describe("estimate.vue", () => { describe("estimate.vue", () => {
test("should call forwardButtonAction if isExternalParameter is true and form is valid", async () => { test("should call forwardButtonAction if isExternalParameter is true and form is valid", async () => {
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, true); store.getters = {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_VIN_SELECTION, "decline"); isExternalParameter: true,
externalParameterEstimate: { vinSelection: "decline" },
};
// Set up the component // Set up the component
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});

View file

@ -178,6 +178,7 @@ describe("moldingQuestions.vue", () => {
test("Should trigger handleCompletedQuestionChainAnswers if watched data changes", async () => { test("Should trigger handleCompletedQuestionChainAnswers if watched data changes", async () => {
// Arrange // Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.handleCompletedQuestionChainAnswers = jest.fn();
const spy = jest.spyOn(wrapper.vm, "handleCompletedQuestionChainAnswers"); const spy = jest.spyOn(wrapper.vm, "handleCompletedQuestionChainAnswers");
// Act // Act
@ -268,6 +269,7 @@ describe("moldingQuestions.vue", () => {
}, },
}; };
}); });
const spy = jest.spyOn(wrapper.vm, "dispatchStoreAction"); const spy = jest.spyOn(wrapper.vm, "dispatchStoreAction");
// Act // Act

View file

@ -164,6 +164,7 @@ describe("partQuestions.vue...", () => {
order: {}, order: {},
}; };
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.handleCompletedQuestionChainAnswers = jest.fn();
const spy = jest.spyOn(wrapper.vm, "handleCompletedQuestionChainAnswers"); const spy = jest.spyOn(wrapper.vm, "handleCompletedQuestionChainAnswers");
// Act // Act

View file

@ -224,12 +224,12 @@ export default {
// instead of what comes from the backend. This is to prevent issues with part interchange. // instead of what comes from the backend. This is to prevent issues with part interchange.
const availableFrontWipers = orderHasFrontWipers const availableFrontWipers = orderHasFrontWipers
? frontWipersOnOrder ? frontWipersOnOrder
: resultMap.wipers.filter((wiper) => wiper.partType == partTypeStrings.FRONT_WIPER) ?? : (resultMap.wipers.filter((wiper) => wiper.partType == partTypeStrings.FRONT_WIPER) ??
[]; []);
const availableRearWipers = orderHasRearWipers const availableRearWipers = orderHasRearWipers
? rearWipersOnOrder ? rearWipersOnOrder
: resultMap.wipers.filter((wiper) => wiper.partType == partTypeStrings.REAR_WIPER) ?? : (resultMap.wipers.filter((wiper) => wiper.partType == partTypeStrings.REAR_WIPER) ??
[]; []);
const lineItemsToTax = [ const lineItemsToTax = [
resultMap.rainDefense, resultMap.rainDefense,

View file

@ -384,6 +384,7 @@ describe("service-package-question.vue", () => {
}, },
], ],
}); });
wrapper.vm.selectDefaultPackage = jest.fn();
const selectDefaultPackageMock = jest.spyOn(wrapper.vm, "selectDefaultPackage"); const selectDefaultPackageMock = jest.spyOn(wrapper.vm, "selectDefaultPackage");
await nextTick(); await nextTick();

View file

@ -233,7 +233,10 @@ export default {
}, },
getDiscountedPackagePriceString(packageName, servicePackageDiscount) { getDiscountedPackagePriceString(packageName, servicePackageDiscount) {
const formattedPriceFloat = parseFloat( const formattedPriceFloat = parseFloat(
this.getPackagePrice(packageName, { discountedPrice: true, servicePackageDiscount }) this.getPackagePrice(packageName, {
discountedPrice: true,
servicePackageDiscount,
})
).toFixed(2); ).toFixed(2);
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat; return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
}, },

View file

@ -101,6 +101,7 @@ describe("service-package-radio.vue", () => {
}); });
const mockProps = { const mockProps = {
groupName: "group-name",
buttonLabel: "buttonLabel test copy", buttonLabel: "buttonLabel test copy",
buttonLabelAuxillaryCopy: "buttonLabelAuxillaryCopy test copy", buttonLabelAuxillaryCopy: "buttonLabelAuxillaryCopy test copy",
buttonLabelSubCopy: "buttonLabelSubCopy test copy", buttonLabelSubCopy: "buttonLabelSubCopy test copy",

View file

@ -173,7 +173,8 @@ export default {
width: 100%; width: 100%;
padding: 1rem; padding: 1rem;
border: 1px solid $gray-300; border: 1px solid $gray-300;
box-shadow: 0px 4px 8px -4px rgba(0, 0, 0, 0.15), box-shadow:
0px 4px 8px -4px rgba(0, 0, 0, 0.15),
0px 4px 24px -8px rgba(0, 0, 0, 0.2); 0px 4px 24px -8px rgba(0, 0, 0, 0.2);
border-radius: 0.5rem; border-radius: 0.5rem;
overflow: hidden; overflow: hidden;
@ -220,7 +221,9 @@ export default {
+ .package-label { + .package-label {
&:before { &:before {
border: 1px solid #8e9292; border: 1px solid #8e9292;
box-shadow: 0px 0px 0px 4px #9fcee6, 0px 1px 4px rgba(0, 0, 0, 0.2); box-shadow:
0px 0px 0px 4px #9fcee6,
0px 1px 4px rgba(0, 0, 0, 0.2);
} }
} }
} }

View file

@ -309,7 +309,7 @@ describe("service-zip.vue", () => {
// Act // Act
const wrapper = setupMocks({}); const wrapper = setupMocks({});
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation(); jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation();
await wrapper.vm.forwardButtonAction(); await wrapper.vm.forwardButtonAction();
@ -329,7 +329,7 @@ describe("service-zip.vue", () => {
// Act // Act
const wrapper = setupMocks({}); const wrapper = setupMocks({});
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation(); jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation();
await wrapper.vm.forwardButtonAction(); await wrapper.vm.forwardButtonAction();
@ -397,6 +397,7 @@ describe("service-zip.vue", () => {
wrapper.vm.displayInvalidZipAlert = true; wrapper.vm.displayInvalidZipAlert = true;
wrapper.vm.displayNonServiceableZipAlert = true; wrapper.vm.displayNonServiceableZipAlert = true;
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation(); jest.spyOn(wrapper.vm, "navigateForwardWithSingleCarMatch").mockImplementation();
await wrapper.vm.forwardButtonAction(); await wrapper.vm.forwardButtonAction();

View file

@ -75,8 +75,13 @@ export default {
: []; : [];
return filteredAnswers.map((ans) => { return filteredAnswers.map((ans) => {
const newName = ans.Name.includes("-") ? ans.Name.split("-")[1] : ans.Name; const newName = ans.Name.includes("-") ? ans.Name.split("-")[1] : ans.Name;
ans.Name = newName; return {
return ans; Name: newName,
AnswerImageUrl: ans.AnswerImageUrl,
ImageId: ans.ImageId,
SubText: ans.SubText,
Text: ans.Text,
};
}); });
}, },
}, },

View file

@ -142,8 +142,13 @@ export default {
return filteredAnswers.map((ans) => { return filteredAnswers.map((ans) => {
const newName = ans.Name.includes("-") ? ans.Name.split("-")[1] : ans.Name; const newName = ans.Name.includes("-") ? ans.Name.split("-")[1] : ans.Name;
ans.Name = newName; return {
return ans; Name: newName,
AnswerImageUrl: ans.AnswerImageUrl,
ImageId: ans.ImageId,
SubText: ans.SubText,
Text: ans.Text,
};
}); });
}, },
isDriverSideReplaceOptionsQuestionAvailable() { isDriverSideReplaceOptionsQuestionAvailable() {

View file

@ -73,7 +73,7 @@ const basePartResponse = {
}; };
describe("vehicle-parts.vue", () => { describe("vehicle-parts.vue", () => {
test("Set cms content called on load", async (done) => { test("Set cms content called on load", (done) => {
//Arrange //Arrange
store.getters.pageData.mockReturnValue(basePartResponse); store.getters.pageData.mockReturnValue(basePartResponse);
store.getters.lineItems = { glassParts: null }; store.getters.lineItems = { glassParts: null };

View file

@ -27,8 +27,8 @@ describe("input-button-wrapper-mixin", () => {
expect(inputButtonTwo.vm.isMultiSelect).toBe(true); expect(inputButtonTwo.vm.isMultiSelect).toBe(true);
expect(wrapper.vm.value).toEqual([]); expect(wrapper.vm.value).toEqual([]);
await inputButtonOne.find("input").trigger("click"); await inputButtonOne.find("input").setChecked();
await inputButtonTwo.find("input").trigger("click"); await inputButtonTwo.find("input").setChecked();
// Assert // Assert
expect(wrapper.vm.value).toEqual(["value1", "value2"]); expect(wrapper.vm.value).toEqual(["value1", "value2"]);
@ -52,9 +52,9 @@ describe("input-button-wrapper-mixin", () => {
expect(inputButtonTwo.vm.isMultiSelect).toBe(true); expect(inputButtonTwo.vm.isMultiSelect).toBe(true);
expect(wrapper.vm.value).toEqual([]); expect(wrapper.vm.value).toEqual([]);
await inputButtonOne.find("input").trigger("click"); await inputButtonOne.find("input").setChecked();
await inputButtonTwo.find("input").trigger("click"); await inputButtonTwo.find("input").setChecked();
await inputButtonOne.find("input").trigger("click"); await inputButtonOne.find("input").setChecked(false);
// Assert // Assert
expect(wrapper.vm.value).toEqual(["value2"]); expect(wrapper.vm.value).toEqual(["value2"]);
@ -80,8 +80,8 @@ describe("input-button-wrapper-mixin", () => {
expect(inputButtonTwo.vm.isMultiSelect).toBe(false); expect(inputButtonTwo.vm.isMultiSelect).toBe(false);
expect(wrapper.vm.value).toEqual(""); expect(wrapper.vm.value).toEqual("");
await inputButtonOne.find("input").trigger("click"); await inputButtonOne.find("input").setChecked();
await inputButtonTwo.find("input").trigger("click"); await inputButtonTwo.find("input").setChecked();
// Assert // Assert
expect(wrapper.vm.value).toEqual("value2"); expect(wrapper.vm.value).toEqual("value2");
@ -105,9 +105,9 @@ describe("input-button-wrapper-mixin", () => {
expect(inputButtonTwo.vm.isMultiSelect).toBe(false); expect(inputButtonTwo.vm.isMultiSelect).toBe(false);
expect(wrapper.vm.value).toEqual(""); expect(wrapper.vm.value).toEqual("");
await inputButtonOne.find("input").trigger("click"); await inputButtonOne.find("input").setChecked();
await inputButtonTwo.find("input").trigger("click"); await inputButtonTwo.find("input").setChecked();
await inputButtonOne.find("input").trigger("click"); await inputButtonOne.find("input").setChecked();
// Assert // Assert
expect(wrapper.vm.value).toEqual("value1"); expect(wrapper.vm.value).toEqual("value1");
@ -295,23 +295,20 @@ function setupBaseInputButtonWrapper({ mockData = {} }) {
parentComponentTemplate += `<baseInputButtonWrapper v-model="value" groupName="myGroupName" :isMultiSelect="${mockData.isMultiSelect}" value="value1" />`; parentComponentTemplate += `<baseInputButtonWrapper v-model="value" groupName="myGroupName" :isMultiSelect="${mockData.isMultiSelect}" value="value1" />`;
parentComponentTemplate += `<baseInputButtonWrapper v-model="value" groupName="myGroupName" :isMultiSelect="${mockData.isMultiSelect}" value="value2" />`; parentComponentTemplate += `<baseInputButtonWrapper v-model="value" groupName="myGroupName" :isMultiSelect="${mockData.isMultiSelect}" value="value2" />`;
parentComponentTemplate += `</div>`; parentComponentTemplate += `</div>`;
const wrapper = mount( const wrapper = mount({
{ data() {
data() { return {
return { value: mockData.initialValue ?? (mockData.isMultiSelect ? [] : ""),
value: mockData.initialValue ?? (mockData.isMultiSelect ? [] : ""), $route: {
$route: { query: {
query: { fmgPage: "myPage",
fmgPage: "myPage",
},
}, },
}; },
}, };
template: parentComponentTemplate,
components: { baseInputButtonWrapper },
}, },
{} template: parentComponentTemplate,
); components: { baseInputButtonWrapper },
});
return { wrapper }; return { wrapper };
} }

View file

@ -123,9 +123,8 @@ export default {
answerString; answerString;
// mark this question as suppressed if needed (question-chain uses this) // mark this question as suppressed if needed (question-chain uses this)
if (answeredQuestion.suppressThisQuestion) { if (answeredQuestion.suppressThisQuestion) {
glass.questions[ glass.questions[answeredQuestion.questionNum - 1].suppressThisQuestion =
answeredQuestion.questionNum - 1 true;
].suppressThisQuestion = true;
} }
}); });

View file

@ -394,7 +394,7 @@ async function navigate(
destinationFmgPageValue, destinationFmgPageValue,
Object.keys(optionalPageData).length > 0 Object.keys(optionalPageData).length > 0
? optionalPageData ? optionalPageData
: existingPageDataForPage ?? {} : (existingPageDataForPage ?? {})
); );
optionalParams.isSavingNavigation = isSavingNavigation; optionalParams.isSavingNavigation = isSavingNavigation;

View file

@ -214,7 +214,9 @@ html {
box-shadow: none; box-shadow: none;
} }
&.btn.btn-primary:focus-visible { &.btn.btn-primary:focus-visible {
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $gray-700; box-shadow:
0 0 0 3px $white,
0 0 0 5.5px $gray-700;
} }
} }
} }

View file

@ -75,13 +75,17 @@ export default {
background: linear-gradient(270deg, $blue 0%, $blue-800 100%); background: linear-gradient(270deg, $blue 0%, $blue-800 100%);
} }
&:focus { &:focus {
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px,
0 0 0 5.5px $blue-700;
} }
&:focus, // Mouse, touch, stylus focus &:focus, // Mouse, touch, stylus focus
&:focus-visible { &:focus-visible {
// Keyboard focus for accessibility // Keyboard focus for accessibility
outline: none; outline: none;
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px,
0 0 0 5.5px $blue-700;
color: $white; color: $white;
background: linear-gradient(270deg, rgba(6, 87, 124, 1) 0%, rgba(6, 87, 124, 1) 100%); background: linear-gradient(270deg, rgba(6, 87, 124, 1) 0%, rgba(6, 87, 124, 1) 100%);
} }
@ -99,7 +103,9 @@ export default {
&.has-loader { &.has-loader {
color: $white; color: $white;
background: $blue-700; background: $blue-700;
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px,
0 0 0 5.5px $blue-700;
pointer-events: auto; pointer-events: auto;
} }
&.delay { &.delay {
@ -124,7 +130,9 @@ export default {
&:focus-visible { &:focus-visible {
// Keyboard focus for accessibility // Keyboard focus for accessibility
outline: none; outline: none;
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px $white,
0 0 0 5.5px $blue-700;
color: $white; color: $white;
@include blue-gradient; @include blue-gradient;
} }

View file

@ -27,6 +27,7 @@ describe("checkbox.vue", () => {
let { wrapper } = setupMocks({ let { wrapper } = setupMocks({
mountOptionsMockData: { mountOptionsMockData: {
propsData: { propsData: {
groupName: "checkbox-button-test",
buttonLabel: "label text", buttonLabel: "label text",
value: "test value", value: "test value",
}, },
@ -42,7 +43,15 @@ describe("checkbox.vue", () => {
it("Should have correct screenreader-only text", async () => { it("Should have correct screenreader-only text", async () => {
// Act // Act
let { wrapper } = setupMocks({}); let { wrapper } = setupMocks({
mountOptionsMockData: {
propsData: {
groupName: "checkbox-button-test",
buttonLabel: "label text",
value: "test value",
},
},
});
// Arrange // Arrange
await wrapper.setProps({ await wrapper.setProps({

View file

@ -141,7 +141,9 @@ export default {
} }
&:checked:focus + .list-button-horizontal-content { &:checked:focus + .list-button-horizontal-content {
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700; box-shadow:
0 0 0 3px,
0 0 0 5.5px $blue-700;
} }
&:checked + .list-button-horizontal-content p:first-child { &:checked + .list-button-horizontal-content p:first-child {

View file

@ -295,6 +295,12 @@ describe("list-button.vue", () => {
}); });
function setupMocks({ mockData }) { function setupMocks({ mockData }) {
// Add in group name to avoid vee-validate failures
if (!mockData.propsData) {
mockData.propsData = { groupName: "group-name" };
} else if (!mockData.propsData.groupName) {
mockData.propsData.groupName = "group-name";
}
const wrapper = mount(listButton, { const wrapper = mount(listButton, {
...mockData, ...mockData,
mixins: [inputButtonWrapperMixin], mixins: [inputButtonWrapperMixin],

View file

@ -57,6 +57,12 @@ describe("radio.vue", () => {
}); });
function setupMocks({ mountOptionsMockData = {} }) { function setupMocks({ mountOptionsMockData = {} }) {
// Add in group name to avoid vee-validate failures
if (!mountOptionsMockData.propsData) {
mountOptionsMockData.propsData = { groupName: "group-name" };
} else if (!mountOptionsMockData.propsData.groupName) {
mountOptionsMockData.propsData.groupName = "group-name";
}
const wrapper = mount(radio, { const wrapper = mount(radio, {
...mountOptionsMockData, ...mountOptionsMockData,
mixins: [inputButtonWrapperMixin], mixins: [inputButtonWrapperMixin],