diff --git a/src/digital-components/modal/ux-components/modal-button-main/modal-button-main.spec.js b/src/digital-components/modal/ux-components/modal-button-main/modal-button-main.spec.js
index f212d8ec3..24cb8e546 100644
--- a/src/digital-components/modal/ux-components/modal-button-main/modal-button-main.spec.js
+++ b/src/digital-components/modal/ux-components/modal-button-main/modal-button-main.spec.js
@@ -36,48 +36,6 @@ describe("modal-button-main.vue", () => {
expect(button.attributes()["aria-disabled"]).toEqual("true");
});
- it("Should return loader color", async () => {
- // Arrange
- const wrapper = shallowMount(
- modalButtonMain,
- setupMocks({
- propsData: {
- loaderColor: "blue",
- loaderEnabled: true,
- },
- })
- );
-
- // Act
- wrapper.vm.clicked();
- await nextTick();
-
- // Assert
- const loader = wrapper.find("loader-stub");
- expect(loader.attributes("class")).toContain("blue");
- });
-
- it("Should return loader position", async () => {
- // Arrange
- const wrapper = shallowMount(
- modalButtonMain,
- setupMocks({
- propsData: {
- loaderPosition: "right",
- loaderEnabled: true,
- },
- })
- );
-
- // Act
- wrapper.vm.clicked();
- await nextTick();
-
- // Assert
- const loader = wrapper.find("loader-stub");
- expect(loader.attributes("class")).toContain("right");
- });
-
it("Should set 'isLoaderDisplayed' to false when calling 'removeLoader'", async () => {
// Arrange
const wrapper = shallowMount(
diff --git a/src/digital-components/modal/ux-components/modal-button-main/modal-button-main.vue b/src/digital-components/modal/ux-components/modal-button-main/modal-button-main.vue
index c12dfe498..a2991dcea 100644
--- a/src/digital-components/modal/ux-components/modal-button-main/modal-button-main.vue
+++ b/src/digital-components/modal/ux-components/modal-button-main/modal-button-main.vue
@@ -13,7 +13,8 @@
+ :loaderColor="loaderColor"
+ :loaderPosition="loaderPosition" />
diff --git a/src/fmg-components/nav-bar/nav-bar.spec.js b/src/fmg-components/nav-bar/nav-bar.spec.js
index 68b9f6c8c..c7ed0e934 100644
--- a/src/fmg-components/nav-bar/nav-bar.spec.js
+++ b/src/fmg-components/nav-bar/nav-bar.spec.js
@@ -33,21 +33,15 @@ describe("nav-bar.vue", () => {
expect(wrapper.componentVM.customButtontext).toBe("newText");
});
- test("should run removeLoader fn on buttonMain and return false for onkeydown fn", async () => {
- // Arrange
+ test("should run removeLoader on buttonMain", async () => {
const wrapper = mount(navbar, {
mixins: [mockMixin],
});
- // Act
wrapper.vm.$refs.buttonMain.removeLoader = jest.fn();
wrapper.vm.removeLoader();
- const spy = jest.spyOn(document, "onkeydown");
- document.onkeydown();
- // Assert
expect(wrapper.vm.$refs.buttonMain.removeLoader).toHaveBeenCalled();
- expect(spy).toReturnWith(true);
});
});
diff --git a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
index dda3f9281..f16c3536b 100644
--- a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
+++ b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue
@@ -27,7 +27,7 @@
diff --git a/src/ux-components/button-main/button-main.spec.js b/src/ux-components/button-main/button-main.spec.js
index 76e9afe28..9324726a0 100644
--- a/src/ux-components/button-main/button-main.spec.js
+++ b/src/ux-components/button-main/button-main.spec.js
@@ -36,48 +36,6 @@ describe("buttonMain.vue", () => {
expect(button.attributes()["aria-disabled"]).toEqual("true");
});
- it("Should return loader color", async () => {
- // Arrange
- const wrapper = shallowMount(
- buttonMain,
- setupMocks({
- propsData: {
- loaderColor: "blue",
- loaderEnabled: true,
- },
- })
- );
-
- // Act
- wrapper.vm.clicked();
- await nextTick();
-
- // Assert
- const loader = wrapper.find("loader-stub");
- expect(loader.attributes("class")).toContain("blue");
- });
-
- it("Should return loader position", async () => {
- // Arrange
- const wrapper = shallowMount(
- buttonMain,
- setupMocks({
- propsData: {
- loaderPosition: "right",
- loaderEnabled: true,
- },
- })
- );
-
- // Act
- wrapper.vm.clicked();
- await nextTick();
-
- // Assert
- const loader = wrapper.find("loader-stub");
- expect(loader.attributes("class")).toContain("right");
- });
-
it("Should set 'isLoaderDisplayed' to false when calling 'removeLoader'", async () => {
// Arrange
const wrapper = shallowMount(
diff --git a/src/ux-components/intercept-overlay/intercept-overlay.spec.js b/src/ux-components/intercept-overlay/intercept-overlay.spec.js
index 0a282b93d..e43fc884d 100644
--- a/src/ux-components/intercept-overlay/intercept-overlay.spec.js
+++ b/src/ux-components/intercept-overlay/intercept-overlay.spec.js
@@ -1,4 +1,4 @@
-import { shallowMount } from "@vue/test-utils";
+import { mount, shallowMount } from "@vue/test-utils";
import interceptOverlay from "./intercept-overlay";
describe("intercept-overlay.vue", () => {
@@ -43,4 +43,30 @@ describe("intercept-overlay.vue", () => {
wrapper.unmount();
});
});
+
+ describe("click interception", () => {
+ test("captureClick prevents default and stops propagation", () => {
+ const wrapper = shallowMount(interceptOverlay);
+ const event = { preventDefault: jest.fn(), stopPropagation: jest.fn() };
+ wrapper.vm.captureClick(event);
+ expect(event.preventDefault).toHaveBeenCalled();
+ expect(event.stopPropagation).toHaveBeenCalled();
+ wrapper.unmount();
+ });
+
+ test("clicking the overlay does not propagate to document listeners", async () => {
+ const documentClickFn = jest.fn();
+ document.addEventListener("click", documentClickFn);
+
+ const wrapper = mount(interceptOverlay, { attachTo: document.body });
+
+ const overlay = wrapper.find(".intercept-overlay");
+ await overlay.trigger("click");
+
+ expect(documentClickFn).not.toHaveBeenCalled();
+
+ document.removeEventListener("click", documentClickFn);
+ wrapper.unmount();
+ });
+ });
});
diff --git a/src/ux-components/list-button/list-button.spec.js b/src/ux-components/list-button/list-button.spec.js
index 721ef8a43..a3de44080 100644
--- a/src/ux-components/list-button/list-button.spec.js
+++ b/src/ux-components/list-button/list-button.spec.js
@@ -31,59 +31,6 @@ describe("list-button.vue", () => {
expect(loader.exists()).toBe(true);
});
- it("Should return loader color", async () => {
- // Arrange
- const { wrapper } = setupMocks({
- mockData: {
- global: {
- mocks: {
- $route: { query: { fmgPage: "page-name" } },
- GaActions: GaActions,
- pushEventToGA: jest.fn(),
- },
- },
- propsData: {
- loaderColor: "blue",
- selectingInitiatesLoad: true,
- },
- },
- });
-
- // Act
- wrapper.vm.selectedValue = "something";
- await wrapper.vm.$nextTick();
-
- // Assert
- const loader = wrapper.findComponent({ name: "loader" });
- expect(loader.attributes("class")).toContain("blue");
- });
-
- it("Should return loader position", async () => {
- // Act
- const { wrapper } = setupMocks({
- mockData: {
- global: {
- mocks: {
- $route: { query: { fmgPage: "page-name" } },
- GaActions: GaActions,
- pushEventToGA: jest.fn(),
- },
- },
- propsData: {
- loaderPosition: "right",
- selectingInitiatesLoad: true,
- },
- },
- });
-
- // Act
- wrapper.vm.selectedValue = "something";
- await wrapper.vm.$nextTick();
-
- // Assert
- const loader = wrapper.findComponent({ name: "loader" });
- expect(loader.attributes("class")).toContain("right");
- });
});
describe("baseInputButton checks", () => {
diff --git a/src/ux-components/list-button/list-button.vue b/src/ux-components/list-button/list-button.vue
index df71f9800..5ca26f738 100644
--- a/src/ux-components/list-button/list-button.vue
+++ b/src/ux-components/list-button/list-button.vue
@@ -18,7 +18,8 @@
+ :loaderColor="loaderColor"
+ :loaderPosition="loaderPosition" />
diff --git a/src/ux-components/loader/loader.spec.js b/src/ux-components/loader/loader.spec.js
index d56c4e0ed..4b79efb36 100644
--- a/src/ux-components/loader/loader.spec.js
+++ b/src/ux-components/loader/loader.spec.js
@@ -3,18 +3,16 @@ import loader from "./loader";
describe("loader.vue", () => {
test("if it rendered the HTML element with class", () => {
- // Arrange/Act
const wrapper = shallowMount(loader, {
props: {},
});
- // Assert
expect(wrapper.find("div").exists()).toBeTruthy();
expect(wrapper.find(".loader").exists()).toBeTruthy();
+ wrapper.unmount();
});
- test("if it correctly passed props", () => {
- // Arrange/Act
+ test("applies loaderColor and loaderPosition as CSS classes on the loader element", () => {
const wrapper = shallowMount(loader, {
props: {
loaderColor: "blue",
@@ -22,64 +20,95 @@ describe("loader.vue", () => {
},
});
- // Assert
- expect(wrapper.props()).toMatchObject({
- loaderColor: "blue",
- loaderPosition: "left",
- });
+ const loaderElement = wrapper.find(".loader");
+ expect(loaderElement.classes()).toContain("blue");
+ expect(loaderElement.classes()).toContain("left");
+ wrapper.unmount();
});
describe("Blocking interaction on page", () => {
- test("Does capture clicks if enabled (default)", async () => {
- // Arrange
- const div = document.createElement("div");
- div.id = "parent";
- document.body.appendChild(div);
+ let parent;
- const parentClickFn = jest.fn();
-
- div.addEventListener("click", parentClickFn);
-
- const wrapper = shallowMount(loader, {
- props: {},
- attachTo: "#parent",
- });
-
- // Act
- await wrapper.trigger("click");
-
- // Assert
- expect(parentClickFn).not.toBeCalled();
-
- // Cleanup
- document.body.removeChild(div);
+ beforeEach(() => {
+ parent = document.createElement("div");
+ parent.id = "loader-test-parent";
+ document.body.appendChild(parent);
});
- test("Does not capture clicks if disabled", async () => {
- // Arrange
- const div = document.createElement("div");
- div.id = "parent";
- document.body.appendChild(div);
+ afterEach(() => {
+ document.body.querySelectorAll(".intercept-overlay").forEach((el) => el.remove());
+ if (parent?.parentNode) {
+ parent.parentNode.removeChild(parent);
+ }
+ });
- const parentClickFn = jest.fn();
+ test("teleports intercept overlay to document.body when blocking is enabled", () => {
+ const wrapper = mount(loader, {
+ props: {},
+ attachTo: "#loader-test-parent",
+ });
- div.addEventListener("click", parentClickFn);
+ const overlayInBody = document.body.querySelector(".intercept-overlay");
+ const overlayInParent = parent.querySelector(".intercept-overlay");
- const wrapper = shallowMount(loader, {
+ expect(overlayInBody).toBeTruthy();
+ expect(overlayInParent).toBeNull();
+ expect(wrapper.find(".intercept-overlay").exists()).toBe(false);
+
+ wrapper.unmount();
+ });
+
+ test("does not render intercept overlay when allowPageInteraction is true", () => {
+ const wrapper = mount(loader, {
props: {
allowPageInteraction: true,
},
- attachTo: "#parent",
+ attachTo: "#loader-test-parent",
});
- // Act
- await wrapper.trigger("click");
+ expect(document.body.querySelector(".intercept-overlay")).toBeNull();
+ expect(wrapper.find(".loader").exists()).toBe(true);
- // Assert
- expect(parentClickFn).toBeCalled();
+ wrapper.unmount();
+ });
- // Cleanup
- document.body.removeChild(div);
+ test("clicking the teleported overlay does not propagate to document listeners", async () => {
+ const documentClickFn = jest.fn();
+ document.addEventListener("click", documentClickFn);
+
+ const wrapper = mount(loader, {
+ props: {},
+ attachTo: "#loader-test-parent",
+ });
+
+ const overlay = document.body.querySelector(".intercept-overlay");
+ expect(overlay).toBeTruthy();
+
+ overlay.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
+
+ expect(documentClickFn).not.toHaveBeenCalled();
+
+ document.removeEventListener("click", documentClickFn);
+ wrapper.unmount();
+ });
+
+ test("teleports overlay to body even when loader is mounted inside a button", async () => {
+ const button = document.createElement("button");
+ button.type = "button";
+ parent.appendChild(button);
+
+ const wrapper = mount(loader, {
+ props: {},
+ attachTo: button,
+ });
+
+ const overlayInBody = document.body.querySelector(".intercept-overlay");
+ const overlayInButton = button.querySelector(".intercept-overlay");
+
+ expect(overlayInBody).toBeTruthy();
+ expect(overlayInButton).toBeNull();
+
+ wrapper.unmount();
});
});
});