DigitalConsumer.FixMyGlass/src/fmg-components/address-questions/address-questions.spec.js

671 lines
26 KiB
JavaScript

// Components
import addressQuestions from "@/fmg-components/address-questions/address-questions";
import alert from "@/ux-components/alert/alert";
// Supporting Files
import { mount, shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { storeMutations } from "@/constants/store-mutations";
import store from "@/store";
let autocompleteElement;
describe("address-questions.vue", () => {
beforeEach(() => {
// Create the `addressField1` element (autocomplete's input)
autocompleteElement = document.createElement("input");
autocompleteElement.getPlace = jest.fn();
document.getElementById = jest.fn().mockReturnValue(autocompleteElement);
document.getElementsByClassName = jest
.fn()
.mockReturnValue([document.createElement("div")]);
});
describe("initial state", () => {
test("Should only show the street address field", () => {
// Arrange
const { wrapper } = setupMocks({});
// Assert
const streetAddressField = wrapper.findComponent({ ref: "autocomplete" });
const cityField = wrapper.findComponent({ ref: "city" });
const stateField = wrapper.findComponent({ ref: "state" });
const zipCodeField = wrapper.findComponent({ ref: "zipCode" });
expect(streetAddressField.exists()).toBe(true);
expect(streetAddressField.isVisible()).toBe(true);
expect(cityField.exists()).toBe(true);
expect(cityField.isVisible()).toBe(false);
expect(stateField.exists()).toBe(true);
expect(stateField.isVisible()).toBe(false);
expect(zipCodeField.exists()).toBe(true);
expect(zipCodeField.isVisible()).toBe(false);
const alerts = wrapper.findAllComponents(alert);
expect(alerts.length).toEqual(0);
});
test("Should render addressQuestions sub-components (textbox-questions and dropdown-questions)", async () => {
// Arrange
const { wrapper } = setupMocks({});
// Act
const streetAddress = wrapper.findComponent({ ref: "autocomplete" });
const city = wrapper.findComponent({ ref: "city" });
const state = wrapper.findComponent({ ref: "state" });
const zipCode = wrapper.findComponent({ ref: "zipCode" });
// Assert
expect(streetAddress.exists()).toBe(true);
expect(city.exists()).toBe(true);
expect(state.exists()).toBe(true);
expect(zipCode.exists()).toBe(true);
});
test("Should render apartmentNumberOrBusinessName textbox-question when captureApartmentNumberOrBusinessName = true", async () => {
// Arrange
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "",
apartmentNumberOrBusinessName: "",
city: "",
state: "",
zipCode: "",
},
captureApartmentNumberOrBusinessName: true,
},
});
await wrapper.setData({
showAddressFields: true,
});
// Act
const streetAddress = wrapper.findComponent({ ref: "autocomplete" });
const apartmentNumberOrBusinessName = wrapper.findComponent({
ref: "apartmentNumberOrBusinessName",
});
const city = wrapper.findComponent({ ref: "city" });
const state = wrapper.findComponent({ ref: "state" });
const zipCode = wrapper.findComponent({ ref: "zipCode" });
// Assert
expect(streetAddress.exists()).toBe(true);
expect(apartmentNumberOrBusinessName.exists()).toBe(true);
expect(apartmentNumberOrBusinessName.isVisible()).toBe(true);
expect(city.exists()).toBe(true);
expect(state.exists()).toBe(true);
expect(zipCode.exists()).toBe(true);
});
test("Should *not* render apartmentNumberOrBusinessName textbox-question when captureApartmentNumberOrBusinessName = false", async () => {
// Arrange
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "",
apartmentNumberOrBusinessName: "",
city: "",
state: "",
zipCode: "",
},
captureApartmentNumberOrBusinessName: false,
},
});
await wrapper.setData({
showAddressFields: true,
});
// Act
const streetAddress = wrapper.findComponent({ ref: "autocomplete" });
const apartmentNumberOrBusinessName = wrapper.findComponent({
ref: "apartmentNumberOrBusinessName",
});
const city = wrapper.findComponent({ ref: "city" });
const state = wrapper.findComponent({ ref: "state" });
const zipCode = wrapper.findComponent({ ref: "zipCode" });
// Assert
expect(streetAddress.exists()).toBe(true);
expect(apartmentNumberOrBusinessName.exists()).toBe(true);
expect(apartmentNumberOrBusinessName.isVisible()).toBe(false);
expect(city.exists()).toBe(true);
expect(state.exists()).toBe(true);
expect(zipCode.exists()).toBe(true);
});
test("Should set this.showAddressFields to true when the model is prepopulated", async () => {
// Arrange / Act
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "foo",
city: "foo",
state: "foo",
zipCode: "55555",
},
},
});
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.showAddressFields).toBe(true);
});
});
describe("happy paths", () => {
test("full street address is passed in => address fields are displayed", async () => {
// Arrange/Act
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "12345 Test Road",
city: "Tests",
state: "OH",
zipCode: "12312",
},
},
});
await wrapper.vm.$nextTick();
// Assert
const cityField = wrapper.findComponent({ ref: "city" });
const stateField = wrapper.findComponent({ ref: "state" });
const zipField = wrapper.findComponent({ ref: "zipCode" });
expect(cityField.exists()).toBeTruthy();
expect(cityField.isVisible()).toBeTruthy();
expect(stateField.exists()).toBeTruthy();
expect(cityField.isVisible()).toBeTruthy();
expect(zipField.exists()).toBeTruthy();
expect(cityField.isVisible()).toBeTruthy();
});
test("full street address is passed in => don't load Google Autocomplete script", async () => {
// Arrange/Act
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "12345 Test Road",
city: "Tests",
state: "OH",
zipCode: "12312",
},
},
});
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.$loadScript).not.toHaveBeenCalled();
});
// test("address field is typed into => disable autofill", async () => { // TEMPORARY
// // Arrange
// let inputEventCallbackFunction;
// autocompleteElement.addEventListener = jest
// .fn()
// .mockImplementation((eventName, callbackFunction) => {
// if (eventName == "input") {
// inputEventCallbackFunction = callbackFunction;
// }
// });
// const { wrapper } = setupMocks({});
// await wrapper.vm.$nextTick();
// const e = {
// inputType: "insertText",
// };
// // Act
// inputEventCallbackFunction(e);
// await wrapper.vm.$nextTick();
// // Assert
// expect(autocompleteElement.getAttribute("autocomplete")).toEqual("new-password");
// });
test("street address is entered, user chooses good result from autocomplete results => other fields are filled in", async () => {
// Arrange
const { wrapper } = setupMocks({});
await wrapper.setData({
addressModel: {
streetAddress: "123 Test Street",
},
});
const selectedPlace = {
address_components: [
{
long_name: "1234",
short_name: "1234",
types: ["street_number"],
},
{
long_name: "Test Road",
short_name: "Test Road",
types: ["route"],
},
{
long_name: "East Columbus",
short_name: "Columbus",
types: ["neighborhood", "political"],
},
{
long_name: "Columbus",
short_name: "Columbus",
types: ["locality", "political"],
},
{
long_name: "Franklin County",
short_name: "Franklin County",
types: ["administrative_area_level_2", "political"],
},
{
long_name: "Ohio",
short_name: "OH",
types: ["administrative_area_level_1", "political"],
},
{
long_name: "United States",
short_name: "US",
types: ["country", "political"],
},
{
long_name: "43215",
short_name: "43215",
types: ["postal_code"],
},
],
};
// Act
autocompleteElement.dispatchEvent(
new CustomEvent("place_changed", { detail: selectedPlace })
);
// Assert
wrapper.vm.$nextTick(function () {
const addressModel = wrapper.vm.addressModel;
expect(addressModel.streetAddress).toEqual("1234 Test Road");
expect(addressModel.city).toEqual("Columbus");
expect(addressModel.state).toEqual("OH");
expect(addressModel.zipCode).toEqual("43215");
});
});
// test("street address is entered, but user clicks away => first result is selected and other fields are filled in", async () => {
// // Arrange
// let changeEventCallbackFunction;
// autocompleteElement.addEventListener = jest
// .fn()
// .mockImplementation((eventName, callbackFunction) => {
// if (eventName == "change") {
// changeEventCallbackFunction = callbackFunction;
// }
// });
// const { wrapper } = setupMocks({
// querySelectorFunction: function (query) {
// if (query == ".pac-container .pac-item > .pac-item-query") {
// let element = document.createElement("div");
// element.textContent = "123 Test Street";
// return element;
// } else if (query == ".pac-container .pac-item > span:nth-child(3)") {
// let element = document.createElement("div");
// element.textContent = "Columbus, OH 43230";
// return element;
// }
// },
// geocoderResult: {
// address_components: [
// {
// long_name: "1234",
// short_name: "1234",
// types: ["street_number"],
// },
// {
// long_name: "Test Road",
// short_name: "Test Road",
// types: ["route"],
// },
// {
// long_name: "East Columbus",
// short_name: "Columbus",
// types: ["neighborhood", "political"],
// },
// {
// long_name: "Columbus",
// short_name: "Columbus",
// types: ["locality", "political"],
// },
// {
// long_name: "Franklin County",
// short_name: "Franklin County",
// types: ["administrative_area_level_2", "political"],
// },
// {
// long_name: "Ohio",
// short_name: "OH",
// types: ["administrative_area_level_1", "political"],
// },
// {
// long_name: "United States",
// short_name: "US",
// types: ["country", "political"],
// },
// {
// long_name: "43215",
// short_name: "43215",
// types: ["postal_code"],
// },
// ],
// },
// });
// let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
// let verificationAlert = wrapper.findComponent({ ref: "alertVerificationWarning" });
// expect(noMatchAlert.exists()).toBeFalsy();
// expect(verificationAlert.exists()).toBeFalsy();
// await wrapper.vm.$nextTick();
// // Act
// changeEventCallbackFunction();
// await wrapper.vm.$nextTick();
// // Assert
// const addressModel = wrapper.vm.addressModel;
// expect(addressModel.streetAddress).toEqual("1234 Test Road");
// expect(addressModel.city).toEqual("Columbus");
// expect(addressModel.state).toEqual("OH");
// expect(addressModel.zipCode).toEqual("43215");
// });
});
describe("alerts", () => {
test("user enters address that yields no autocomplete results and pressed enter or tab => show noMatch alert", async () => {
// Arrange
let changeEventCallbackFunction;
autocompleteElement.addEventListener = jest
.fn()
.mockImplementation((eventName, callbackFunction) => {
if (eventName == "keydown") {
changeEventCallbackFunction = callbackFunction;
}
});
const { wrapper } = setupMocks({});
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
expect(noMatchAlert.exists()).toBeFalsy();
await wrapper.vm.$nextTick();
const e = {
code: "Enter",
};
// Act
//autocompleteElement.dispatchEvent(new Event("keydown"), e);
changeEventCallbackFunction(e);
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.displayNoMatchWarning).toBeTruthy();
noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
expect(noMatchAlert.exists()).toBeTruthy();
expect(noMatchAlert.isVisible()).toBeTruthy();
});
// test("user enters address that yields autocomplete results, but doesn't select => show verification alert", async () => {
// // Arrange
// let changeEventCallbackFunction;
// autocompleteElement.addEventListener = jest
// .fn()
// .mockImplementation((eventName, callbackFunction) => {
// if (eventName == "change") {
// changeEventCallbackFunction = callbackFunction;
// }
// });
// const { wrapper } = setupMocks({
// querySelectorFunction: function (query) {
// if (query == ".pac-container .pac-item > .pac-item-query") {
// let element = document.createElement("div");
// element.textContent = "123 Test Street";
// return element;
// } else if (query == ".pac-container .pac-item > span:nth-child(3)") {
// let element = document.createElement("div");
// element.textContent = "Columbus, OH 43230";
// return element;
// }
// },
// });
// let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
// let verificationAlert = wrapper.findComponent({ ref: "alertVerificationWarning" });
// expect(noMatchAlert.exists()).toBeFalsy();
// expect(verificationAlert.exists()).toBeFalsy();
// await wrapper.vm.$nextTick();
// // Act
// changeEventCallbackFunction();
// await wrapper.vm.$nextTick();
// // Assert
// verificationAlert = wrapper.findComponent({ ref: "alertVerificationWarning" });
// expect(wrapper.vm.displayVerificationWarning).toBeTruthy();
// expect(verificationAlert.exists()).toBeTruthy();
// expect(verificationAlert.isVisible()).toBeTruthy();
// noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
// expect(wrapper.vm.displayNoMatchWarning).toBeFalsy();
// expect(noMatchAlert.exists()).toBeFalsy();
// });
describe("noMatch alert is cleared on address change", () => {
test("user sees noMatch warning and modifies street address => noMatch warning is removed", async () => {
// Arrange
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "LS",
city: "",
state: "",
zipCode: "",
},
},
});
// Initial condition to display noMatch warning
await wrapper.setData({
matchFound: false,
});
// Act
wrapper.vm.addressModel.streetAddress = "LJS";
await wrapper.vm.$nextTick();
// Assert
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
expect(noMatchAlert.exists()).toBeFalsy();
});
test("user sees noMatch warning and enters city => noMatch warning is removed", async () => {
// Arrange
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "",
city: "LS",
state: "",
zipCode: "",
},
},
});
// Initial condition to display noMatch warning
await wrapper.setData({
matchFound: false,
});
// Act
wrapper.vm.addressModel.city = "LJS";
await wrapper.vm.$nextTick();
// Assert
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
expect(noMatchAlert.exists()).toBeFalsy();
});
test("user sees noMatch warning and enters state => noMatch warning is removed", async () => {
// Arrange
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "",
city: "",
state: "LS",
zipCode: "",
},
},
});
// Initial condition to display noMatch warning
await wrapper.setData({
matchFound: false,
});
// Act
wrapper.vm.addressModel.state = "LJS";
await wrapper.vm.$nextTick();
// Assert
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
expect(noMatchAlert.exists()).toBeFalsy();
});
test("user sees noMatch warning and enters zip code => noMatch warning is removed", async () => {
// Arrange
const { wrapper } = setupMocks({
props: {
modelValue: {
streetAddress: "",
city: "",
state: "",
zipCode: "LS",
},
},
});
// Initial condition to display noMatch warning
await wrapper.setData({
matchFound: false,
});
// Act
wrapper.vm.addressModel.zipCode = "LJS";
await wrapper.vm.$nextTick();
// Assert
let noMatchAlert = wrapper.findComponent({ ref: "alertNoMatchWarning" });
expect(noMatchAlert.exists()).toBeFalsy();
});
});
});
});
function setupMocks({
mountOptions,
props,
isShallowMount = true,
querySelectorFunction,
geocoderResult = ["1234 Test Street"],
matchFound = false,
}) {
store.commit(storeMutations.RESET_STATE);
const resultingMountOptions = getMountOptions({
...mountOptions,
router: {
navigate: jest.fn(),
navigate: jest.fn(),
},
loadScript: jest.fn().mockResolvedValue(),
});
if (props) resultingMountOptions.propsData = props;
if (isShallowMount) {
resultingMountOptions.global.stubs = {
...(resultingMountOptions.global.stubs ?? {}),
textboxQuestion: {
template: `<span></span>`,
methods: {
handleChange: jest.fn(),
},
},
dropdownQuestion: {
template: `<span></span>`,
methods: {
handleChange: jest.fn(),
},
},
};
}
const wrapper = isShallowMount
? shallowMount(addressQuestions, resultingMountOptions)
: mount(addressQuestions, resultingMountOptions);
window.google = {
maps: {
event: {
addListener: jest
.fn()
.mockImplementation((element, eventName, callbackFunction) => {
function interceptedCallbackFunction(e) {
callbackFunction(e.detail);
}
// selectedPlace = "Woogly";
element.addEventListener(eventName, interceptedCallbackFunction);
}),
removeListener: jest.fn(),
clearInstanceListeners: jest.fn(),
trigger: jest.fn().mockImplementation((element, eventName) => {
wrapper.vm.matchFound = matchFound;
}),
},
places: {
Autocomplete: jest.fn().mockImplementation((el) => el),
},
Geocoder: class Geocoder {
// constructor();
geocode(request, callback) {
callback([geocoderResult], true);
}
},
GeocoderStatus: {
OK: true,
},
},
};
document.querySelector = jest.fn().mockImplementation((query) => {
let result = null;
if (query == ".pac-container") result = document.createElement("div");
else if (querySelectorFunction) {
result = querySelectorFunction(query);
}
return result ?? null;
});
return { wrapper };
}