671 lines
26 KiB
JavaScript
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 };
|
|
}
|