DigitalConsumer.FixMyGlass/src/digital-components/textbox-question/textbox-question.spec.js
Carl Nation b437ca183e CASH-2978 added policy number validation
CASH-2978 added policy number validation
2026-07-06 08:12:52 -04:00

452 lines
14 KiB
JavaScript

import { shallowMount } from "@vue/test-utils";
import { defineRule } from "vee-validate";
import textboxQuestion from "./textbox-question";
// Mock CMS content
const questionText = "Question Text";
const mockMixin = {
methods: {
getCmsContent: jest.fn().mockImplementation(() => {
return questionText;
}),
},
};
const maska = jest.fn();
// Real rules registered with vee-validate so the watcher's pre-check (which calls the
// standalone `validate` export, not `this.validate`) exercises genuine valid/invalid paths.
defineRule("spec-always-valid", () => true);
defineRule("spec-always-invalid", () => "invalid");
describe("textboxQuestion.vue", () => {
it("Should coerce non-string modelValue to empty string for v-model.trim", async () => {
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
modelValue: null,
},
mixins: [mockMixin],
});
expect(wrapper.vm.value).toBe("");
});
it("Should render a text input", async () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
mixins: [mockMixin],
});
wrapper.getCmsContent = jest.fn();
// Act
const input = wrapper.find("input");
// Assert
expect(input.exists()).toBe(true);
});
it("Should return rounded-pill class", async () => {
// Act
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
mixins: [mockMixin],
propsData: {
cornerStyle: "rounded",
},
});
// Assert
const paragraph = wrapper.find("input");
expect(paragraph.attributes("class")).toContain("rounded-pill");
});
it("Should return form-control class", async () => {
// Act
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
mixins: [mockMixin],
propsData: {
questionAlignment: "text",
},
});
// Assert
const paragraph = wrapper.find("input");
expect(paragraph.attributes("class")).toContain("form-control");
});
it("Should render the 'questionText' data value as the aria-label attribute.", async () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
mixins: [mockMixin],
});
// Act
const label = wrapper.find("label");
// Assert
expect(label.attributes("aria-label")).toContain(questionText);
});
it("Should return aria-disabled state as disabled", async () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
isDisabled: true,
},
mixins: [mockMixin],
});
// Assert
const input = wrapper.find("input");
// Expect
expect(input.attributes("aria-disabled")).toEqual("true");
});
it("Should emit new value when modelValue is changed", async () => {
// Act
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
modelValue: "val",
},
mixins: [mockMixin],
});
await wrapper.find("input").setValue("val2");
// Assert
expect(wrapper.emitted()).toHaveProperty("change");
});
it("Should call this.handleChange with new value and shouldValidate=true when the value is changed and the new value is valid", async () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
modelValue: "foo",
validationRules: "spec-always-valid",
},
mixins: [mockMixin],
});
wrapper.vm.handleChange = jest.fn().mockImplementation(() => {});
// Act
await wrapper.vm.$options.watch.value.call(wrapper.vm, "bar");
// Assert
expect(wrapper.vm.handleChange).toHaveBeenCalledWith("bar", true);
});
it("Should still call this.handleChange with shouldValidate=false when the new value is invalid, so the field stays in sync for later validation", async () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
modelValue: "foo",
validationRules: "spec-always-invalid",
},
mixins: [mockMixin],
});
wrapper.vm.handleChange = jest.fn().mockImplementation(() => {});
// Act
await wrapper.vm.$options.watch.value.call(wrapper.vm, "bar");
// Assert
expect(wrapper.vm.handleChange).toHaveBeenCalledWith("bar", false);
});
it("Should not display camera or spinner icon when disabled", () => {
// Arrange
const inputId = "test";
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
modelValue: "",
includeImageQuestion: true,
inputId: inputId,
isDisabled: true,
},
mixins: [mockMixin],
attachTo: document.body,
});
// Act
const cameraIcon = wrapper.find('[data-test="image-upload"]');
const loadingIcon = wrapper.findComponent("loader");
// Assert
expect(cameraIcon.exists()).toBe(false);
expect(loadingIcon.exists()).toBe(false);
});
describe("Image Uploading", () => {
it("Should call this.handleChange & emit update when fully valid image is submitted.", async () => {
// Arrange
const inputId = "test";
const responseValue = "testResponse";
const imageHandler = jest.fn().mockImplementation(
() =>
new Promise((resolve, reject) => {
resolve({
data: [responseValue],
});
})
);
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
modelValue: "",
"onUpdate:modelValue": (v) => wrapper.setProps({ modelValue: v }),
includeImageQuestion: true,
inputId: inputId,
imageQuestionSubmitHandler: imageHandler,
},
mixins: [mockMixin],
attachTo: document.body,
});
wrapper.vm.handleChange = jest.fn().mockImplementation(() => {});
wrapper.vm.isImageValid = jest.fn().mockImplementation(() => true);
// Act
const imageUploadField = wrapper.find('[data-test="image-upload"]');
await imageUploadField.trigger("change");
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.imageQuestionSubmitHandler).toHaveBeenCalled();
expect(wrapper.vm.handleChange).toHaveBeenCalled();
expect(wrapper.emitted()).toHaveProperty("update:modelValue");
});
it("Should not call handler and emit image-lookup-error when image is invalid.", async () => {
// Arrange
const inputId = "test";
const responseValue = "testResponse";
const imageHandler = jest.fn().mockImplementation(
() =>
new Promise((resolve, reject) => {
resolve({
data: [responseValue],
});
})
);
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
modelValue: "",
"onUpdate:modelValue": (v) => wrapper.setProps({ modelValue: v }),
includeImageQuestion: true,
inputId: inputId,
imageQuestionSubmitHandler: imageHandler,
},
mixins: [mockMixin],
attachTo: document.body,
});
wrapper.vm.handleChange = jest.fn().mockImplementation(() => {});
wrapper.vm.isImageValid = jest.fn().mockImplementation(() => false);
// Act
const imageUploadField = wrapper.find('[data-test="image-upload"]');
await imageUploadField.trigger("change");
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.imageQuestionSubmitHandler).not.toHaveBeenCalled();
expect(wrapper.vm.handleChange).not.toHaveBeenCalled();
expect(wrapper.emitted()).toHaveProperty("imageValidityError");
});
it("Should emit image-lookup-error when image lookup responds with an error.", async () => {
// Arrange
const inputId = "test";
const imageHandler = jest.fn().mockImplementation(
() =>
new Promise((resolve, reject) => {
reject({});
})
);
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
modelValue: "",
"onUpdate:modelValue": (v) => wrapper.setProps({ modelValue: v }),
includeImageQuestion: true,
inputId: inputId,
imageQuestionSubmitHandler: imageHandler,
},
mixins: [mockMixin],
attachTo: document.body,
});
wrapper.vm.handleChange = jest.fn().mockImplementation(() => {});
wrapper.vm.isImageValid = jest.fn().mockImplementation(() => true);
// Act
const imageUploadField = wrapper.find('[data-test="image-upload"]');
await imageUploadField.trigger("change");
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.imageQuestionSubmitHandler).toHaveBeenCalled();
expect(wrapper.vm.handleChange).not.toHaveBeenCalled();
expect(wrapper.emitted()).toHaveProperty("imageLookupError");
});
});
describe("Image Validation", () => {
it("Should return true if a valid image is tested.", () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
inputId: "input ID",
maxFileSize: 5140 * 1028,
},
mixins: [mockMixin],
});
const image = {
size: 100 * 1028,
};
// Act
const result = wrapper.vm.isImageValid(image);
// Assert
expect(result).toBeTruthy();
});
it("Should return false if null image is tested.", () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
inputId: "input ID",
maxFileSize: 5140 * 1028,
},
mixins: [mockMixin],
});
const image = null;
// Act
const result = wrapper.vm.isImageValid(image);
// Assert
expect(result).toBeFalsy();
});
it("Should return false if oversized image is tested.", () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
global: {
directives: {
maska: maska,
},
},
propsData: {
inputId: "input ID",
maxFileSize: 5140 * 1028,
},
mixins: [mockMixin],
});
const image = {
size: 10000000 * 1028,
};
// Act
const result = wrapper.vm.isImageValid(image);
// Assert
expect(result).toBeFalsy();
});
});
});