From e9b7e175d6bd6fb5ae8904b91cc4b1d95c0caaff Mon Sep 17 00:00:00 2001 From: hiteshshetty-dev Date: Mon, 21 Oct 2024 13:22:42 +0530 Subject: [PATCH] chore: fix test cases for VB --- package-lock.json | 7 +- package.json | 4 +- src/__test__/utils.ts | 65 +++++ .../__test__/__snapshots__/index.test.ts.snap | 99 ++----- .../__test__/click/fields/boolean.test.tsx | 24 +- .../__test__/click/fields/date.test.tsx | 19 +- .../__test__/click/fields/file.test.tsx | 49 +--- .../__test__/click/fields/group.test.tsx | 44 +-- .../__test__/click/fields/html-rte.test.tsx | 44 +-- .../__test__/click/fields/json-rte.test.tsx | 45 +-- .../__test__/click/fields/link.test.tsx | 50 +--- .../__test__/click/fields/markdown.test.tsx | 46 +--- .../__test__/click/fields/multi-line.test.tsx | 68 +---- .../__test__/click/fields/number.test.tsx | 54 +--- .../__test__/click/fields/reference.test.tsx | 51 +--- .../__test__/click/fields/select.test.tsx | 45 +-- .../click/fields/single-line.test.tsx | 115 ++------ .../fields/__snapshots__/boolean.test.ts.snap | 30 +- .../fields/__snapshots__/date.test.ts.snap | 30 +- .../fields/__snapshots__/file.test.ts.snap | 164 +++++------ .../fields/__snapshots__/group.test.ts.snap | 122 ++++++--- .../__snapshots__/html-rte.test.ts.snap | 82 +++--- .../__snapshots__/json-rte.test.ts.snap | 82 +++--- .../fields/__snapshots__/link.test.ts.snap | 113 +++----- .../__snapshots__/markdown.test.ts.snap | 82 +++--- .../__snapshots__/multi-line.test.ts.snap | 124 +++++++-- .../fields/__snapshots__/number.test.ts.snap | 82 +++--- .../__snapshots__/reference.test.ts.snap | 114 +++++--- .../fields/__snapshots__/select.test.ts.snap | 120 ++++---- .../__snapshots__/single-line.test.ts.snap | 258 ++++++++++++++++-- .../__test__/hover/fields/boolean.test.ts | 11 +- .../__test__/hover/fields/date.test.ts | 11 +- .../__test__/hover/fields/file.test.ts | 72 +++-- .../__test__/hover/fields/group.test.ts | 40 +-- .../__test__/hover/fields/html-rte.test.ts | 27 +- .../__test__/hover/fields/json-rte.test.ts | 26 +- .../__test__/hover/fields/link.test.ts | 24 +- .../__test__/hover/fields/markdown.test.ts | 27 +- .../__test__/hover/fields/multi-line.test.ts | 26 +- .../__test__/hover/fields/number.test.ts | 26 +- .../__test__/hover/fields/reference.test.ts | 26 +- .../__test__/hover/fields/select.test.ts | 26 +- .../__test__/hover/fields/single-line.test.ts | 26 +- src/visualBuilder/__test__/index.test.ts | 214 ++++++--------- .../__test__/visualBuilderInput.test.tsx | 222 ++++++++++----- .../__test__/addInstanceButton.test.tsx | 37 +-- .../__test__/fieldLabelWrapper.test.tsx | 10 +- .../components/__test__/fieldToolbar.test.tsx | 27 +- .../components/__test__/icons.test.tsx | 34 ++- .../__test__/pseudoEditableField.test.tsx | 5 +- .../__test__/startEditingButton.test.tsx | 15 +- .../__test__/visualBuilder.test.tsx | 25 +- .../__test__/generateToolbar.test.ts | 20 +- src/visualBuilder/listeners/index.ts | 98 +++---- vitest.setup.ts | 66 ++++- 55 files changed, 1644 insertions(+), 1729 deletions(-) diff --git a/package-lock.json b/package-lock.json index 138ecf53..976e8523 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "uuid": "^8.3.2" }, "devDependencies": { - "@contentstack/advanced-post-message": "github:contentstack/adv-post-message#main", + "@contentstack/advanced-post-message": "^0.0.2", "@eslint/js": "^9.10.0", "@testing-library/jest-dom": "^6.5.0", "@testing-library/preact": "^3.2.4", @@ -175,8 +175,9 @@ } }, "node_modules/@contentstack/advanced-post-message": { - "version": "0.0.1-alpha.1", - "resolved": "git+ssh://git@github.com/contentstack/adv-post-message.git#24a06c78482ff05abc191c6428f85bf86a61f857", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@contentstack/advanced-post-message/-/advanced-post-message-0.0.2.tgz", + "integrity": "sha512-JctN+axXpQhvxcmk2lSc3qSweXnNqGJRA7c8MKVda57h+B7gIzccV6Pay5oQy+R0HDXvi8J5+BVjZJ5LOdQCqA==", "dev": true, "dependencies": { "uuid": "^9.0.0", diff --git a/package.json b/package.json index 0b90ef44..0397eed3 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "sideEffects": false, "scripts": { "build": "tsup", - "test": "vitest --no-file-parallelism", + "test": "vitest", "test:once": "vitest run", "test:coverage": "vitest --coverage", "dev": "tsup --watch", @@ -43,7 +43,7 @@ "author": "Contentstack", "license": "MIT", "devDependencies": { - "@contentstack/advanced-post-message": "github:contentstack/adv-post-message#main", + "@contentstack/advanced-post-message": "^0.0.2", "@eslint/js": "^9.10.0", "@testing-library/jest-dom": "^6.5.0", "@testing-library/preact": "^3.2.4", diff --git a/src/__test__/utils.ts b/src/__test__/utils.ts index 5635c3f5..61deaf31 100644 --- a/src/__test__/utils.ts +++ b/src/__test__/utils.ts @@ -1,3 +1,8 @@ +import { EventManager } from "@contentstack/advanced-post-message"; +import { act, fireEvent, render, waitFor } from "@testing-library/preact"; +import { VisualBuilderPostMessageEvents } from "../visualBuilder/utils/types/postMessage.types"; +import { ComponentChild } from "preact"; + export function convertObjectToMinifiedString( obj: { [key: string]: any } | string ): any { @@ -30,3 +35,63 @@ export class DOMRect { export async function sleep(waitTimeInMs = 100): Promise { return new Promise((resolve) => setTimeout(resolve, waitTimeInMs)); } + +export const waitForHoverOutline = async () => { + await waitFor(() => { + const hoverOutline = document.querySelector( + "[data-testid='visual-builder__hover-outline']" + ); + expect(hoverOutline).not.toBeNull(); + }); +} +export const waitForBuilderSDKToBeInitialized = async (visualBuilderPostMessage: EventManager | undefined) => { + await waitFor(() => { + expect(visualBuilderPostMessage?.send).toBeCalledWith( + VisualBuilderPostMessageEvents.INIT, + expect.any(Object) + ); + }); +} +interface WaitForClickActionOptions { + skipWaitForFieldType?: boolean; +} +export const triggerAndWaitForClickAction = async (visualBuilderPostMessage: EventManager | undefined, element: HTMLElement, {skipWaitForFieldType}: WaitForClickActionOptions = {}) => { + await waitForBuilderSDKToBeInitialized(visualBuilderPostMessage); + await act(async () => { + await fireEvent.click(element); + }) + if(!skipWaitForFieldType) { + await waitFor(() => { + expect(element).toHaveAttribute("data-cslp-field-type") + }) + } +} +export const waitForToolbaxToBeVisible = async () => { + await waitFor(() => { + const toolbar = document.querySelector( + ".visual-builder__focused-toolbar__field-label-container" + ); + expect(toolbar).not.toBeNull(); + }); +} +const defaultRect = { + left: 10, + right: 20, + top: 10, + bottom: 20, + width: 10, + height: 5, +} +export const mockGetBoundingClientRect = (element: HTMLElement, rect = defaultRect) => { + vi.spyOn(element, "getBoundingClientRect").mockImplementation(() => rect as DOMRect); +} +export const getElementBytestId = (testId: string) => { + return document.querySelector(`[data-testid="${testId}"]`); +} +export const asyncRender: (componentChild: ComponentChild) => ReturnType = async (...args) => { + let returnValue: ReturnType; + await act(async () => { + returnValue = render(...args); + }); + return returnValue; +} \ No newline at end of file diff --git a/src/visualBuilder/__test__/__snapshots__/index.test.ts.snap b/src/visualBuilder/__test__/__snapshots__/index.test.ts.snap index 0576374c..2b36d542 100644 --- a/src/visualBuilder/__test__/__snapshots__/index.test.ts.snap +++ b/src/visualBuilder/__test__/__snapshots__/index.test.ts.snap @@ -1,78 +1,5 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`Visual builder > inline editing > should add overlay to DOM when clicked 1`] = ` - -

- Hello World -

-
- -
-
-
-
-
-
-
-
-
-
-
- -`; - exports[`Visual builder > on click, the sdk > inline elements must be contenteditable > file should render a replacer and remove when it is not 1`] = `

on click, the sdk > inline elements must be contentedi /> `; -exports[`Visual builder > on click, the sdk > inline elements must be contenteditable > file should render a replacer and remove when it is not 2`] = `undefined`; +exports[`Visual builder > on click, the sdk > inline elements must be contenteditable > file should render a replacer and remove when it is not 2`] = ` + +`; exports[`Visual builder > on click, the sdk > inline elements must be contenteditable > multi line should be contenteditable 1`] = `

({ observe: vi.fn(), @@ -78,9 +79,7 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); mouseClickEvent = new Event("click", { @@ -89,20 +88,17 @@ describe("When an element is clicked in visual builder mode", () => { }); }); - afterEach(() => { - vi.clearAllMocks(); - document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); + vi.clearAllMocks(); + document.body.innerHTML = ""; }); describe("boolean field", () => { let booleanField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { booleanField = document.createElement("p"); booleanField.setAttribute( "data-cslp", @@ -111,25 +107,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(booleanField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, booleanField); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - booleanField.dispatchEvent(mouseClickEvent); expect(booleanField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - booleanField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - booleanField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -137,7 +131,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - booleanField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(booleanField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -146,14 +139,13 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - booleanField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(booleanField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - booleanField.dispatchEvent(mouseClickEvent); + await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/date.test.tsx b/src/visualBuilder/__test__/click/fields/date.test.tsx index 3dd11d91..f46f33f1 100644 --- a/src/visualBuilder/__test__/click/fields/date.test.tsx +++ b/src/visualBuilder/__test__/click/fields/date.test.tsx @@ -9,6 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; global.ResizeObserver = vi.fn().mockImplementation(() => ({ observe: vi.fn(), @@ -78,9 +79,7 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); mouseClickEvent = new Event("click", { @@ -89,12 +88,9 @@ describe("When an element is clicked in visual builder mode", () => { }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - - afterAll(() => { Config.reset(); }); @@ -102,7 +98,7 @@ describe("When an element is clicked in visual builder mode", () => { let dateField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { dateField = document.createElement("p"); dateField.setAttribute( "data-cslp", @@ -111,25 +107,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(dateField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, dateField); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - dateField.dispatchEvent(mouseClickEvent); expect(dateField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - dateField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - dateField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -137,7 +131,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - dateField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(dateField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -146,14 +139,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - dateField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(dateField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - dateField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/file.test.tsx b/src/visualBuilder/__test__/click/fields/file.test.tsx index 212bb075..e846d25b 100644 --- a/src/visualBuilder/__test__/click/fields/file.test.tsx +++ b/src/visualBuilder/__test__/click/fields/file.test.tsx @@ -9,17 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; - -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; vi.mock("../../../components/FieldToolbar", () => { return { @@ -78,9 +68,7 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); mouseClickEvent = new Event("click", { @@ -89,12 +77,10 @@ describe("When an element is clicked in visual builder mode", () => { }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -103,7 +89,7 @@ describe("When an element is clicked in visual builder mode", () => { let imageField: HTMLImageElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { fileField = document.createElement("p"); fileField.setAttribute( "data-cslp", @@ -119,25 +105,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(fileField); document.body.appendChild(imageField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, fileField); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - fileField.dispatchEvent(mouseClickEvent); expect(fileField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - fileField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - fileField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -146,9 +130,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should not have a multi field toolbar with button group", async () => { - await waitFor(() => { - fileField.dispatchEvent(mouseClickEvent); - }); const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" @@ -163,7 +144,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test.skip("should have a field path dropdown", () => { - fileField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -172,9 +152,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should have a replace asset button", async () => { - await waitFor(() => { - fileField.dispatchEvent(mouseClickEvent); - }); const replaceButton = document.querySelector( ".visual-builder__replace-button" ); @@ -183,7 +160,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - fileField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(fileField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -192,14 +168,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - fileField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(fileField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - fileField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -219,7 +193,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondImageField: HTMLImageElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -257,25 +231,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -313,9 +285,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => { - container.dispatchEvent(mouseClickEvent); - }); const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" @@ -346,7 +315,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -376,7 +344,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/group.test.tsx b/src/visualBuilder/__test__/click/fields/group.test.tsx index 897e8a5a..2f4f76d9 100644 --- a/src/visualBuilder/__test__/click/fields/group.test.tsx +++ b/src/visualBuilder/__test__/click/fields/group.test.tsx @@ -9,17 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; - -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; vi.mock("../../../components/FieldToolbar", () => { return { @@ -78,9 +68,7 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); mouseClickEvent = new Event("click", { @@ -89,12 +77,10 @@ describe("When an element is clicked in visual builder mode", () => { }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -103,7 +89,7 @@ describe("When an element is clicked in visual builder mode", () => { let groupField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { groupField = document.createElement("p"); groupField.setAttribute( "data-cslp", @@ -112,26 +98,24 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(groupField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, groupField); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); visualBuilder.destroy(); }); test("should have outline", () => { - groupField.dispatchEvent(mouseClickEvent); expect(groupField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - groupField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - groupField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -139,7 +123,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - groupField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(groupField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -148,14 +131,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - groupField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(groupField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - groupField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -174,7 +155,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondGroupField: HTMLDivElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -207,25 +188,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -234,10 +213,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => { - container.dispatchEvent(mouseClickEvent); - }); - const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -267,7 +242,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -276,14 +250,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/html-rte.test.tsx b/src/visualBuilder/__test__/click/fields/html-rte.test.tsx index 5e669104..638f0b8b 100644 --- a/src/visualBuilder/__test__/click/fields/html-rte.test.tsx +++ b/src/visualBuilder/__test__/click/fields/html-rte.test.tsx @@ -9,17 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; - -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; vi.mock("../../../components/FieldToolbar", () => { return { @@ -78,9 +68,7 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); mouseClickEvent = new Event("click", { @@ -89,12 +77,10 @@ describe("When an element is clicked in visual builder mode", () => { }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -102,7 +88,7 @@ describe("When an element is clicked in visual builder mode", () => { let htmlRteField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { htmlRteField = document.createElement("p"); htmlRteField.setAttribute( "data-cslp", @@ -110,25 +96,23 @@ describe("When an element is clicked in visual builder mode", () => { ); document.body.appendChild(htmlRteField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, htmlRteField) }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - htmlRteField.dispatchEvent(mouseClickEvent); expect(htmlRteField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - htmlRteField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - htmlRteField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -136,7 +120,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - htmlRteField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(htmlRteField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -145,14 +128,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - htmlRteField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(htmlRteField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - htmlRteField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -170,7 +151,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondHtmlRteField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -194,25 +175,22 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", async () => { - container.dispatchEvent(mouseClickEvent); - await waitFor(() => { const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" @@ -223,10 +201,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => { - container.dispatchEvent(mouseClickEvent); - }); - const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -256,7 +230,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -286,7 +259,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/json-rte.test.tsx b/src/visualBuilder/__test__/click/fields/json-rte.test.tsx index 8d3ce787..8a555076 100644 --- a/src/visualBuilder/__test__/click/fields/json-rte.test.tsx +++ b/src/visualBuilder/__test__/click/fields/json-rte.test.tsx @@ -9,18 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; -import { sleep } from "../../../../__test__/utils"; - -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; vi.mock("../../../components/FieldToolbar", () => { return { @@ -79,9 +68,7 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); mouseClickEvent = new Event("click", { @@ -90,12 +77,10 @@ describe("When an element is clicked in visual builder mode", () => { }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -103,7 +88,7 @@ describe("When an element is clicked in visual builder mode", () => { let jsonRteField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { jsonRteField = document.createElement("p"); jsonRteField.setAttribute( "data-cslp", @@ -111,25 +96,24 @@ describe("When an element is clicked in visual builder mode", () => { ); document.body.appendChild(jsonRteField); visualBuilder = new VisualBuilder(); + + await triggerAndWaitForClickAction(visualBuilderPostMessage, jsonRteField); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - jsonRteField.dispatchEvent(mouseClickEvent); expect(jsonRteField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - jsonRteField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - jsonRteField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -137,7 +121,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - jsonRteField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(jsonRteField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -146,14 +129,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - jsonRteField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(jsonRteField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - jsonRteField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -171,7 +152,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondJsonRteField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -195,25 +176,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -222,10 +201,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => { - container.dispatchEvent(mouseClickEvent); - }); - const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -255,7 +230,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -285,7 +259,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/link.test.tsx b/src/visualBuilder/__test__/click/fields/link.test.tsx index f3a5fe0a..295e00d1 100644 --- a/src/visualBuilder/__test__/click/fields/link.test.tsx +++ b/src/visualBuilder/__test__/click/fields/link.test.tsx @@ -9,17 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; - -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; vi.mock("../../../components/FieldToolbar", () => { return { @@ -60,8 +50,6 @@ vi.mock("../../../utils/visualBuilderPostMessage", async () => { }); describe("When an element is clicked in visual builder mode", () => { - let mouseClickEvent: Event; - beforeAll(() => { FieldSchemaMap.setFieldSchema( "all_fields", @@ -78,23 +66,15 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); - mouseClickEvent = new Event("click", { - bubbles: true, - cancelable: true, - }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -102,7 +82,7 @@ describe("When an element is clicked in visual builder mode", () => { let linkField: HTMLAnchorElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { linkField = document.createElement("a"); linkField.setAttribute( "data-cslp", @@ -111,25 +91,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(linkField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, linkField); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - linkField.dispatchEvent(mouseClickEvent); expect(linkField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - linkField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - linkField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -137,7 +115,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test.skip("should have a field path dropdown", () => { - linkField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -145,7 +122,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - linkField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(linkField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -154,14 +130,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - linkField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(linkField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - linkField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -180,7 +154,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondLinkField: HTMLAnchorElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -204,25 +178,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -231,10 +203,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => { - container.dispatchEvent(mouseClickEvent); - }); - const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -264,7 +232,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -294,7 +261,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/markdown.test.tsx b/src/visualBuilder/__test__/click/fields/markdown.test.tsx index 36096096..bcc2e0d7 100644 --- a/src/visualBuilder/__test__/click/fields/markdown.test.tsx +++ b/src/visualBuilder/__test__/click/fields/markdown.test.tsx @@ -9,17 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; - -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; vi.mock("../../../components/FieldToolbar", () => { return { @@ -60,7 +50,6 @@ vi.mock("../../../utils/visualBuilderPostMessage", async () => { }); describe("When an element is clicked in visual builder mode", () => { - let mouseClickEvent: Event; beforeAll(() => { FieldSchemaMap.setFieldSchema( @@ -78,23 +67,15 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); - mouseClickEvent = new Event("click", { - bubbles: true, - cancelable: true, - }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -102,7 +83,7 @@ describe("When an element is clicked in visual builder mode", () => { let markdownField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { markdownField = document.createElement("p"); markdownField.setAttribute( "data-cslp", @@ -112,25 +93,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(markdownField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, markdownField); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - markdownField.dispatchEvent(mouseClickEvent); expect(markdownField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - markdownField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - markdownField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -138,7 +117,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - markdownField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(markdownField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -147,14 +125,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - markdownField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(markdownField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - markdownField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -172,7 +148,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondMarkdownField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -196,25 +172,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -223,8 +197,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => {}); - const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -254,7 +226,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -284,7 +255,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/multi-line.test.tsx b/src/visualBuilder/__test__/click/fields/multi-line.test.tsx index 441d7134..9095e62e 100644 --- a/src/visualBuilder/__test__/click/fields/multi-line.test.tsx +++ b/src/visualBuilder/__test__/click/fields/multi-line.test.tsx @@ -9,17 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { Mock, vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; - -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; vi.mock("../../../components/FieldToolbar", () => { return { @@ -60,9 +50,8 @@ vi.mock("../../../utils/visualBuilderPostMessage", async () => { }); describe("When an element is clicked in visual builder mode", () => { - let mouseClickEvent: Event; - beforeAll(() => { + beforeAll(async () => { FieldSchemaMap.setFieldSchema( "all_fields", getFieldSchemaMap().all_fields @@ -78,23 +67,15 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); - mouseClickEvent = new Event("click", { - bubbles: true, - cancelable: true, - }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -102,7 +83,7 @@ describe("When an element is clicked in visual builder mode", () => { let multiLineField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeAll(() => { + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string, args) => { if ( @@ -124,9 +105,7 @@ describe("When an element is clicked in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { multiLineField = document.createElement("p"); multiLineField.setAttribute( "data-cslp", @@ -135,25 +114,24 @@ describe("When an element is clicked in visual builder mode", () => { multiLineField.textContent = "Hello world"; document.body.appendChild(multiLineField); visualBuilder = new VisualBuilder(); + + await triggerAndWaitForClickAction(visualBuilderPostMessage, multiLineField) }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - multiLineField.dispatchEvent(mouseClickEvent); expect(multiLineField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - multiLineField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", async () => { - multiLineField.dispatchEvent(mouseClickEvent); await waitFor(() => { const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" @@ -163,7 +141,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - multiLineField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(multiLineField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -172,14 +149,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a contenteditable attribute", async () => { - multiLineField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(multiLineField).toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - multiLineField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -195,8 +170,8 @@ describe("When an element is clicked in visual builder mode", () => { let container: HTMLDivElement; let firstMultiLineField: HTMLParagraphElement; let secondMultiLineField: HTMLParagraphElement; - - beforeAll(() => { + let visualBuilder: VisualBuilder; + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string, args) => { if ( @@ -215,9 +190,7 @@ describe("When an element is clicked in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -248,39 +221,31 @@ describe("When an element is clicked in visual builder mode", () => { previousEmptyBlockParents: [], audienceMode: false, }; + visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); + afterAll(() => { + visualBuilder.destroy(); + }) test("should have outline", () => { - const visualBuilder = new VisualBuilder(); - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); - visualBuilder.destroy(); }); test("should have an overlay", () => { - const visualBuilder = new VisualBuilder(); - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); - visualBuilder.destroy(); }); test.skip("should have a field path dropdown", () => { - const visualBuilder = new VisualBuilder(); - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); expect(toolbar).toBeInTheDocument(); - visualBuilder.destroy(); }); // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => { - container.dispatchEvent(mouseClickEvent); - }); - const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -310,16 +275,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - const visualBuilder = new VisualBuilder(); - container.dispatchEvent(mouseClickEvent); - await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY ); }); - visualBuilder.destroy(); }); test("container should not contain a contenteditable attribute but the children can", async () => { @@ -344,7 +305,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/number.test.tsx b/src/visualBuilder/__test__/click/fields/number.test.tsx index 01d24c49..7310320b 100644 --- a/src/visualBuilder/__test__/click/fields/number.test.tsx +++ b/src/visualBuilder/__test__/click/fields/number.test.tsx @@ -9,22 +9,12 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { Mock, vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; const VALUES = { number: "10.5", }; -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); - vi.mock("../../../components/FieldToolbar", () => { return { default: () => { @@ -64,9 +54,7 @@ vi.mock("../../../utils/visualBuilderPostMessage", async () => { }); describe("When an element is clicked in visual builder mode", () => { - let mouseClickEvent: Event; - - beforeAll(() => { + beforeAll(async () => { FieldSchemaMap.setFieldSchema( "all_fields", getFieldSchemaMap().all_fields @@ -82,23 +70,15 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); - mouseClickEvent = new Event("click", { - bubbles: true, - cancelable: true, - }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -106,7 +86,7 @@ describe("When an element is clicked in visual builder mode", () => { let numberField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeAll(() => { + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string) => { if ( @@ -127,9 +107,7 @@ describe("When an element is clicked in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { numberField = document.createElement("p"); numberField.setAttribute( "data-cslp", @@ -140,25 +118,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(numberField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, numberField) }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - numberField.dispatchEvent(mouseClickEvent); expect(numberField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - numberField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - numberField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -166,7 +142,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - numberField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(numberField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -175,7 +150,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - numberField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -193,7 +167,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondNumberField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeAll(() => { + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string, args) => { if ( @@ -212,9 +186,7 @@ describe("When an element is clicked in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -240,25 +212,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container) }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -267,10 +237,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => { - container.dispatchEvent(mouseClickEvent); - }); - const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -300,7 +266,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -330,7 +295,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/reference.test.tsx b/src/visualBuilder/__test__/click/fields/reference.test.tsx index 7f1234de..35b4a4fa 100644 --- a/src/visualBuilder/__test__/click/fields/reference.test.tsx +++ b/src/visualBuilder/__test__/click/fields/reference.test.tsx @@ -9,18 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; -import { sleep } from "../../../../__test__/utils"; - -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; vi.mock("../../../components/FieldToolbar", () => { return { @@ -61,9 +50,8 @@ vi.mock("../../../utils/visualBuilderPostMessage", async () => { }); describe("When an element is clicked in visual builder mode", () => { - let mouseClickEvent: Event; - beforeAll(() => { + beforeAll(async () => { FieldSchemaMap.setFieldSchema( "all_fields", getFieldSchemaMap().all_fields @@ -79,23 +67,15 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); - mouseClickEvent = new Event("click", { - bubbles: true, - cancelable: true, - }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -103,7 +83,7 @@ describe("When an element is clicked in visual builder mode", () => { let referenceField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { referenceField = document.createElement("p"); referenceField.setAttribute( "data-cslp", @@ -112,14 +92,14 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(referenceField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, referenceField) }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - referenceField.dispatchEvent(mouseClickEvent); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); @@ -127,13 +107,11 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should have an overlay", () => { - referenceField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - referenceField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -141,7 +119,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - referenceField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(referenceField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -150,14 +127,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - referenceField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(referenceField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - referenceField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -175,7 +150,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondReferenceField: HTMLDivElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -199,14 +174,14 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); @@ -214,13 +189,11 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -229,10 +202,6 @@ describe("When an element is clicked in visual builder mode", () => { // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - await waitFor(() => { - container.dispatchEvent(mouseClickEvent); - }); - const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -262,7 +231,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -292,7 +260,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/select.test.tsx b/src/visualBuilder/__test__/click/fields/select.test.tsx index b36e66a8..4de0e547 100644 --- a/src/visualBuilder/__test__/click/fields/select.test.tsx +++ b/src/visualBuilder/__test__/click/fields/select.test.tsx @@ -9,24 +9,13 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; -import { sleep } from "../../../../__test__/utils"; +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; const VALUES = { singleLine: "Single line", number: "10.5", }; -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); - vi.mock("../../../components/FieldToolbar", () => { return { default: () => { @@ -66,7 +55,6 @@ vi.mock("../../../utils/visualBuilderPostMessage", async () => { }); describe("When an element is clicked in visual builder mode", () => { - let mouseClickEvent: Event; beforeAll(() => { FieldSchemaMap.setFieldSchema( @@ -84,23 +72,15 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); - mouseClickEvent = new Event("click", { - bubbles: true, - cancelable: true, - }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); @@ -108,7 +88,7 @@ describe("When an element is clicked in visual builder mode", () => { let selectField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { selectField = document.createElement("p"); selectField.setAttribute( "data-cslp", @@ -117,25 +97,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(selectField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, selectField); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - selectField.dispatchEvent(mouseClickEvent); expect(selectField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - selectField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - selectField.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -143,7 +121,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - selectField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(selectField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -152,14 +129,12 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should not contain a contenteditable attribute", async () => { - selectField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(selectField).not.toHaveAttribute("contenteditable"); }); }); test("should send a focus field message to parent", async () => { - selectField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -177,7 +152,7 @@ describe("When an element is clicked in visual builder mode", () => { let secondSelectField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - beforeEach(() => { + beforeAll(async () => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -201,25 +176,23 @@ describe("When an element is clicked in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test.skip("should have a field path dropdown", () => { - container.dispatchEvent(mouseClickEvent); const toolbar = document.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper__current-field" ); @@ -227,7 +200,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -257,7 +229,6 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should send a focus field message to parent", async () => { - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, diff --git a/src/visualBuilder/__test__/click/fields/single-line.test.tsx b/src/visualBuilder/__test__/click/fields/single-line.test.tsx index 4d3856fc..4f0e83fd 100644 --- a/src/visualBuilder/__test__/click/fields/single-line.test.tsx +++ b/src/visualBuilder/__test__/click/fields/single-line.test.tsx @@ -9,7 +9,7 @@ import visualBuilderPostMessage from "../../../utils/visualBuilderPostMessage"; import { Mock, vi } from "vitest"; import { VisualBuilderPostMessageEvents } from "../../../utils/types/postMessage.types"; import { VisualBuilder } from "../../../index"; -import { sleep } from "../../../../__test__/utils"; +import { triggerAndWaitForClickAction } from "../../../../__test__/utils"; import { act } from "preact/test-utils"; const VALUES = { @@ -17,17 +17,6 @@ const VALUES = { number: "10.5", }; -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - -global.MutationObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - disconnect: vi.fn(), -})); - vi.mock("../../../components/FieldToolbar", () => { return { default: () => { @@ -67,7 +56,6 @@ vi.mock("../../../utils/visualBuilderPostMessage", async () => { }); describe("When an element is clicked in visual builder mode", () => { - let mouseClickEvent: Event; beforeAll(() => { FieldSchemaMap.setFieldSchema( @@ -85,30 +73,22 @@ describe("When an element is clicked in visual builder mode", () => { "get" ).mockReturnValue(100); vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); - mouseClickEvent = new Event("click", { - bubbles: true, - cancelable: true, - }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); document.body.innerHTML = ""; - }); - afterAll(() => { Config.reset(); }); describe("single line field", () => { let singleLineField: HTMLParagraphElement; - - beforeAll(() => { + let visualBuilder: VisualBuilder; + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string) => { if ( @@ -130,9 +110,7 @@ describe("When an element is clicked in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { singleLineField = document.createElement("p"); singleLineField.setAttribute( "data-cslp", @@ -155,73 +133,47 @@ describe("When an element is clicked in visual builder mode", () => { previousEmptyBlockParents: [], audienceMode: false, }; + visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, singleLineField); }); + afterAll(() => { + visualBuilder.destroy(); + }) + test("should have outline", () => { - const visualBuilder = new VisualBuilder(); - singleLineField.dispatchEvent(mouseClickEvent); expect(singleLineField.classList.contains("cslp-edit-mode")); - visualBuilder.destroy(); }); test("should have an overlay", () => { - const visualBuilder = new VisualBuilder(); - singleLineField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); - visualBuilder.destroy(); }); test.skip("should have a field path dropdown", async () => { - const visualBuilder = new VisualBuilder(); - await sleep(0); - - fireEvent.click(singleLineField); - await waitFor(async () => { const fieldLabel = screen.getByTestId( "mock-field-label-wrapper" ); expect(fieldLabel).toBeInTheDocument(); }); - - visualBuilder.destroy(); }); test("should contain a data-cslp-field-type attribute", async () => { - const visualBuilder = new VisualBuilder(); - await sleep(0); - - await act(async () => { - await fireEvent.click(singleLineField); - }) - await waitFor(() => expect(singleLineField).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY ) ); - - visualBuilder.destroy(); }); test("should contain a contenteditable attribute", async () => { - const visualBuilder = new VisualBuilder(); - - fireEvent.click(singleLineField); - await waitFor(() => { expect(singleLineField).toHaveAttribute("contenteditable"); }); - - visualBuilder.destroy(); }); test("should send a focus field message to parent", async () => { - const visualBuilder = new VisualBuilder(); - - fireEvent.click(singleLineField); - await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -230,7 +182,6 @@ describe("When an element is clicked in visual builder mode", () => { } ); }); - visualBuilder.destroy(); }); }); @@ -238,8 +189,9 @@ describe("When an element is clicked in visual builder mode", () => { let container: HTMLDivElement; let firstSingleLineField: HTMLParagraphElement; let secondSingleLineField: HTMLParagraphElement; + let visualBuilder: VisualBuilder; - beforeAll(() => { + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string, args) => { if ( @@ -258,9 +210,7 @@ describe("When an element is clicked in visual builder mode", () => { return Promise.resolve({}); } ); - }); - - beforeEach(() => { + container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -292,42 +242,34 @@ describe("When an element is clicked in visual builder mode", () => { previousEmptyBlockParents: [], audienceMode: false, }; + visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); + }); + + afterAll(() => { + visualBuilder.destroy(); }); test("should have outline", () => { - const visualBuilder = new VisualBuilder(); - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); - visualBuilder.destroy(); }); test("should have an overlay", () => { - const visualBuilder = new VisualBuilder(); - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); - visualBuilder.destroy(); }); test.skip("should have a field path dropdown", async () => { - const visualBuilder = new VisualBuilder(); - - await sleep(0); - fireEvent.click(container); - await sleep(0); - await waitFor(async () => { const toolbar = await screen.findByTestId( "mock-field-label-wrapper" ); expect(toolbar).toBeInTheDocument(); }); - visualBuilder.destroy(); }); // TODO should be a test of FieldToolbar test.skip("should have a multi field toolbar with button group", async () => { - container.dispatchEvent(mouseClickEvent); const multiFieldToolbar = document.querySelector( ".visual-builder__focused-toolbar__multiple-field-toolbar" ); @@ -341,21 +283,14 @@ describe("When an element is clicked in visual builder mode", () => { }); test("should contain a data-cslp-field-type attribute", async () => { - const visualBuilder = new VisualBuilder(); - container.dispatchEvent(mouseClickEvent); - await waitFor(() => { expect(container).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY ); }); - visualBuilder.destroy(); }); test("container should not contain a contenteditable attribute but the children can", async () => { - const visualBuilder = new VisualBuilder(); - - fireEvent.click(container); await waitFor(() => { expect(container).not.toHaveAttribute("contenteditable"); }); @@ -373,14 +308,9 @@ describe("When an element is clicked in visual builder mode", () => { "contenteditable" ); }); - - visualBuilder.destroy(); }); test.skip("should have 2 add instance buttons", async () => { - const visualBuilder = new VisualBuilder(); - - fireEvent.click(container.children[0]); await waitFor(() => { expect(container.children[0]).toHaveAttribute( VISUAL_BUILDER_FIELD_TYPE_ATTRIBUTE_KEY @@ -393,14 +323,9 @@ describe("When an element is clicked in visual builder mode", () => { ); expect(addInstanceButtons.length).toBe(2); }); - - visualBuilder.destroy(); }); test("should send a focus field message to parent", async () => { - const visualBuilder = new VisualBuilder(); - - container.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(visualBuilderPostMessage?.send).toBeCalledWith( VisualBuilderPostMessageEvents.FOCUS_FIELD, @@ -409,8 +334,6 @@ describe("When an element is clicked in visual builder mode", () => { } ); }); - - visualBuilder.destroy(); }); }); }); diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/boolean.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/boolean.test.ts.snap index bdf7f19a..a6b0f034 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/boolean.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/boolean.test.ts.snap @@ -1,6 +1,20 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > boolean field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > boolean field > should have outline and custom cursor 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > boolean field > should have outline and custom cursor 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > boolean field > should have outline and custom cursor 3`] = `
boolean field > sho
`; - -exports[`When an element is hovered in visual builder mode > boolean field > should have outline 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > boolean field > should have outline 2`] = ` -

-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/date.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/date.test.ts.snap index 1b6808c5..0109bc81 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/date.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/date.test.ts.snap @@ -1,6 +1,20 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > date field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > date field > should have outline and custom cursor 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > date field > should have outline and custom cursor 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > date field > should have outline and custom cursor 3`] = `
date field > should
`; - -exports[`When an element is hovered in visual builder mode > date field > should have outline 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > date field > should have outline 2`] = ` -

-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/file.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/file.test.ts.snap index 38281e6b..60cd990b 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/file.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/file.test.ts.snap @@ -1,6 +1,33 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline and custom cursor 1`] = ` +
+

+

+ + +

+`; + +exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline and custom cursor 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline and custom cursor 3`] = `
file field (multipl
`; -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have custom cursor on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline and custom cursor on individual instances 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline and custom cursor on individual instances 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline and custom cursor on the url 1`] = ` + +`; + +exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline and custom cursor on the url 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > file field > should have a outline and custom cursor on the url as well 1`] = ` + +`; + +exports[`When an element is hovered in visual builder mode > file field > should have a outline and custom cursor on the url as well 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > file field > should have a outline and custom cursor on the url as well 3`] = `
file field (multipl
`; -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have custom cursor on the url 1`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline 1`] = ` -
-

-

- - -

-`; - -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > file field > should have outline and custom cursor 1`] = `

-`; - -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline on individual instances 2`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline on the url 1`] = ` - `; -exports[`When an element is hovered in visual builder mode > file field (multiple) > should have outline on the url 2`] = ` +exports[`When an element is hovered in visual builder mode > file field > should have outline and custom cursor 2`] = `
file field (multipl /> `; -exports[`When an element is hovered in visual builder mode > file field > should have a outline on the url as well 1`] = ` - -`; - -exports[`When an element is hovered in visual builder mode > file field > should have a outline on the url as well 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > file field > should have custom cursor 1`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > file field > should have custom cursor on the url as well 1`] = ` +exports[`When an element is hovered in visual builder mode > file field > should have outline and custom cursor 3`] = `
file field > should
`; - -exports[`When an element is hovered in visual builder mode > file field > should have outline 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > file field > should have outline 2`] = ` -

-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/group.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/group.test.ts.snap index ad16399a..08efb624 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/group.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/group.test.ts.snap @@ -1,13 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > group field (multiple) > should have custom cursor 1`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline 1`] = ` +exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline and custom cursor 1`] = `
@@ -24,7 +17,7 @@ exports[`When an element is hovered in visual builder mode > group field (multip
`; -exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline 2`] = ` +exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline and custom cursor 2`] = `
group field (multip /> `; -exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline on the nested field 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline on the nested field 2`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > group field > should have a outline on the nested single line 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > group field > should have a outline on the nested single line 2`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > group field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline and custom cursor 3`] = `
group field > shoul
`; -exports[`When an element is hovered in visual builder mode > group field > should have custom cursor on the nested single line 1`] = ` +exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline on the nested field 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > group field (multiple) > should have outline on the nested field 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > group field > should have a outline and custom cursor on the nested single line 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > group field > should have a outline and custom cursor on the nested single line 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > group field > should have a outline and custom cursor on the nested single line 3`] = `
group field > shoul
`; -exports[`When an element is hovered in visual builder mode > group field > should have outline 1`] = ` +exports[`When an element is hovered in visual builder mode > group field > should have outline and custom cursor 1`] = `
@@ -176,10 +169,57 @@ exports[`When an element is hovered in visual builder mode > group field > shoul
`; -exports[`When an element is hovered in visual builder mode > group field > should have outline 2`] = ` +exports[`When an element is hovered in visual builder mode > group field > should have outline and custom cursor 2`] = `
`; + +exports[`When an element is hovered in visual builder mode > group field > should have outline and custom cursor 3`] = ` +
+
+
+ + + +
+
+ + + +
+
+
+`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/html-rte.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/html-rte.test.ts.snap index 529c4cd2..7153a25e 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/html-rte.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/html-rte.test.ts.snap @@ -1,6 +1,20 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline and cursor on individual instances 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline and cursor on individual instances 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline and cursor on individual instances 3`] = `
HTML RTE field (mul
`; -exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have custom cursor on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline and custom cursor 1`] = ` +
+

+

+

+`; + +exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline and custom cursor 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline and custom cursor 3`] = `
HTML RTE field (mul
`; -exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline 1`] = ` -
-

-

-

-`; - -exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > HTML RTE field > should have outline and custom cursor 1`] = `

`; -exports[`When an element is hovered in visual builder mode > HTML RTE field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > HTML RTE field > should have outline and custom cursor 2`] = `

HTML RTE field (mul /> `; -exports[`When an element is hovered in visual builder mode > HTML RTE field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > HTML RTE field > should have outline and custom cursor 3`] = `
HTML RTE field > sh
`; - -exports[`When an element is hovered in visual builder mode > HTML RTE field > should have outline 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > HTML RTE field > should have outline 2`] = ` -

-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/json-rte.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/json-rte.test.ts.snap index 2325876d..c5b27197 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/json-rte.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/json-rte.test.ts.snap @@ -1,6 +1,27 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline and custom cursor 1`] = ` +
+

+

+

+`; + +exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline and custom cursor 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline and custom cursor 3`] = `
JSON RTE field (mul
`; -exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have custom cursor on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline and custom cursor on individual instances 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline and custom cursor on individual instances 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline and custom cursor on individual instances 3`] = `
JSON RTE field (mul
`; -exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline 1`] = ` -
-

-

-

-`; - -exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > JSON RTE field > should have outline and custom cursor 1`] = `

`; -exports[`When an element is hovered in visual builder mode > JSON RTE field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > JSON RTE field > should have outline and custom cursor 2`] = `

JSON RTE field (mul /> `; -exports[`When an element is hovered in visual builder mode > JSON RTE field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > JSON RTE field > should have outline and custom cursor 3`] = `
JSON RTE field > sh
`; - -exports[`When an element is hovered in visual builder mode > JSON RTE field > should have outline 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > JSON RTE field > should have outline 2`] = ` -

-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/link.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/link.test.ts.snap index 9fc81c54..96d6514f 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/link.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/link.test.ts.snap @@ -1,6 +1,27 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > link field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline and custom cursor 1`] = ` + +`; + +exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline and custom cursor 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline and custom cursor 3`] = `
link field (multipl
`; -exports[`When an element is hovered in visual builder mode > link field (multiple) > should have custom cursor on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline and custom cursor on individual instances 1`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline and custom cursor on individual instances 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline and custom cursor on individual instances 3`] = `
link field (multipl
`; -exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline 1`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > link field > should have outline and custom cursor 1`] = ` `; -exports[`When an element is hovered in visual builder mode > link field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > link field > should have outline and custom cursor 2`] = `
link field (multipl /> `; -exports[`When an element is hovered in visual builder mode > link field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > link field > should have outline and custom cursor 3`] = `
link field > should
- - - - - -
+ />
`; - -exports[`When an element is hovered in visual builder mode > link field > should have outline 1`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > link field > should have outline 2`] = ` -
-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/markdown.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/markdown.test.ts.snap index 891f039f..7d472e64 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/markdown.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/markdown.test.ts.snap @@ -1,6 +1,27 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline and custom cursor 1`] = ` +
+

+

+

+`; + +exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline and custom cursor 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline and custom cursor 3`] = `
markdown field (mul
`; -exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have custom cursor on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline and custom cursor on individual instances 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline and custom cursor on individual instances 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline and custom cursor on individual instances 3`] = `
markdown field (mul
`; -exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline 1`] = ` -
-

-

-

-`; - -exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > markdown field > should have outline and custom cursor 1`] = `

`; -exports[`When an element is hovered in visual builder mode > markdown field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > markdown field > should have outline and custom cursor 2`] = `

markdown field (mul /> `; -exports[`When an element is hovered in visual builder mode > markdown field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > markdown field > should have outline and custom cursor 3`] = `
markdown field > sh
`; - -exports[`When an element is hovered in visual builder mode > markdown field > should have outline 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > markdown field > should have outline 2`] = ` -

-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/multi-line.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/multi-line.test.ts.snap index 5270fa76..a1d21e06 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/multi-line.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/multi-line.test.ts.snap @@ -1,13 +1,27 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline and custom cursor 1`] = `
+

+

+

+`; + +exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline and custom cursor 2`] = ` +
`; -exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have custom cursor on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline and custom cursor 3`] = `
multi line field (m
`; -exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline 1`] = ` -
-

-

-

-`; - -exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline and custom cursor on individual instances 1`] = `

`; -exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline and custom cursor on individual instances 2`] = `

multi line field (m /> `; -exports[`When an element is hovered in visual builder mode > multi line field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > multi line field (multiple) > should have outline and custom cursor on individual instances 3`] = `
multi line field >
`; -exports[`When an element is hovered in visual builder mode > multi line field > should have outline 1`] = ` +exports[`When an element is hovered in visual builder mode > multi line field > should have outline and custom cursor 1`] = `

`; -exports[`When an element is hovered in visual builder mode > multi line field > should have outline 2`] = ` +exports[`When an element is hovered in visual builder mode > multi line field > should have outline and custom cursor 2`] = `

`; + +exports[`When an element is hovered in visual builder mode > multi line field > should have outline and custom cursor 3`] = ` +
+
+
+ + + +
+
+ + + + + + + +
+
+
+`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/number.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/number.test.ts.snap index f418dc86..96fcaf49 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/number.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/number.test.ts.snap @@ -1,6 +1,27 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > number field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline and custom cursor 1`] = ` +
+

+

+

+`; + +exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline and custom cursor 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline and custom cursor 3`] = `
number field (multi
`; -exports[`When an element is hovered in visual builder mode > number field (multiple) > should have custom cursor on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline and custom cursor on individual instances 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline and custom cursor on individual instances 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline and custom cursor on individual instances 3`] = `
number field (multi
`; -exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline 1`] = ` -
-

-

-

-`; - -exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > number field > should have outline and custom cursor 1`] = `

`; -exports[`When an element is hovered in visual builder mode > number field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > number field > should have outline and custom cursor 2`] = `

number field (multi /> `; -exports[`When an element is hovered in visual builder mode > number field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > number field > should have outline and custom cursor 3`] = `
number field > shou
`; - -exports[`When an element is hovered in visual builder mode > number field > should have outline 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > number field > should have outline 2`] = ` -

-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/reference.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/reference.test.ts.snap index c739a2ba..acae5c18 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/reference.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/reference.test.ts.snap @@ -1,6 +1,27 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline and custom cursor 1`] = ` +
+
+
+
+`; + +exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline and custom cursor 2`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline and custom cursor 3`] = `
reference field (mu
`; -exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have custom cursor on individual instances 1`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline 1`] = ` -
-
-
-
-`; - -exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline 2`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline and custom cursor on individual instances 1`] = `
`; -exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline and custom cursor on individual instances 2`] = `
reference field (mu /> `; -exports[`When an element is hovered in visual builder mode > reference field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > reference field (multiple) > should have outline and custom cursor on individual instances 3`] = `
reference field > s
`; -exports[`When an element is hovered in visual builder mode > reference field > should have outline 1`] = ` +exports[`When an element is hovered in visual builder mode > reference field > should have outline and custom cursor 1`] = `
`; -exports[`When an element is hovered in visual builder mode > reference field > should have outline 2`] = ` +exports[`When an element is hovered in visual builder mode > reference field > should have outline and custom cursor 2`] = `
`; + +exports[`When an element is hovered in visual builder mode > reference field > should have outline and custom cursor 3`] = ` +
+
+
+ + + +
+
+ + + + +
+
+
+`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/select.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/select.test.ts.snap index 4b7d211d..2b028539 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/select.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/select.test.ts.snap @@ -1,6 +1,40 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > select field (multiple) > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline and custom cursor 1`] = ` +
+

+

+

+`; + +exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline and custom cursor 2`] = ` +
+

+

+

+`; + +exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline and custom cursor 3`] = ` +
+`; + +exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline and custom cursor 4`] = `
select field (multi
`; -exports[`When an element is hovered in visual builder mode > select field (multiple) > should have custom cursor on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline and custom cursor on individual instances 1`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline and custom cursor on individual instances 2`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline and custom cursor on individual instances 3`] = ` +

+`; + +exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline and custom cursor on individual instances 4`] = `
select field (multi
`; -exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline 1`] = ` -
-

-

-

-`; - -exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline 2`] = ` -
-

-

-

-`; - -exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline 3`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline on individual instances 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > select field > should have outline and custom cursor 1`] = `

`; -exports[`When an element is hovered in visual builder mode > select field (multiple) > should have outline on individual instances 3`] = ` +exports[`When an element is hovered in visual builder mode > select field > should have outline and custom cursor 2`] = `

select field (multi /> `; -exports[`When an element is hovered in visual builder mode > select field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > select field > should have outline and custom cursor 3`] = `
select field > shou
`; - -exports[`When an element is hovered in visual builder mode > select field > should have outline 1`] = ` -

-`; - -exports[`When an element is hovered in visual builder mode > select field > should have outline 2`] = ` -

-`; diff --git a/src/visualBuilder/__test__/hover/fields/__snapshots__/single-line.test.ts.snap b/src/visualBuilder/__test__/hover/fields/__snapshots__/single-line.test.ts.snap index d9f8c0d4..da54c5a2 100644 --- a/src/visualBuilder/__test__/hover/fields/__snapshots__/single-line.test.ts.snap +++ b/src/visualBuilder/__test__/hover/fields/__snapshots__/single-line.test.ts.snap @@ -1,20 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have custom cursor 1`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have custom cursor on individual instances 1`] = ` -
-`; - -exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline 1`] = ` +exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline and custom cursor 1`] = `
@@ -27,7 +13,7 @@ exports[`When an element is hovered in visual builder mode > single line field (
`; -exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline 2`] = ` +exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline and custom cursor 2`] = `
single line field ( /> `; -exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline on individual instances 1`] = ` +exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline and custom cursor 3`] = ` +
+
+
+ + + +
+
+ + + + + +
+
+
+`; + +exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline and custom cursor on individual instances 1`] = `

`; -exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline on individual instances 2`] = ` +exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline and custom cursor on individual instances 2`] = `

single line field ( /> `; -exports[`When an element is hovered in visual builder mode > single line field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > single line field (multiple) > should have outline and custom cursor on individual instances 3`] = `
+> +
+
+ + + +
+
+ + + + + +
+
+
`; -exports[`When an element is hovered in visual builder mode > single line field > should have outline 1`] = ` +exports[`When an element is hovered in visual builder mode > single line field > should have outline and custom cursor 1`] = `

`; -exports[`When an element is hovered in visual builder mode > title field > should have custom cursor 1`] = ` +exports[`When an element is hovered in visual builder mode > single line field > should have outline and custom cursor 2`] = `

+> +
+
+ + + +
+
+ + + + + +
+
+
`; -exports[`When an element is hovered in visual builder mode > title field > should have outline 1`] = ` +exports[`When an element is hovered in visual builder mode > title field > should have outline and custom cursor 1`] = `

`; -exports[`When an element is hovered in visual builder mode > title field > should have outline 2`] = ` +exports[`When an element is hovered in visual builder mode > title field > should have outline and custom cursor 2`] = `

`; + +exports[`When an element is hovered in visual builder mode > title field > should have outline and custom cursor 3`] = ` +
+
+
+ + + +
+
+ + + + + +
+
+
+`; diff --git a/src/visualBuilder/__test__/hover/fields/boolean.test.ts b/src/visualBuilder/__test__/hover/fields/boolean.test.ts index e241958a..095d2071 100644 --- a/src/visualBuilder/__test__/hover/fields/boolean.test.ts +++ b/src/visualBuilder/__test__/hover/fields/boolean.test.ts @@ -1,6 +1,6 @@ import { screen } from "@testing-library/preact"; import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -82,23 +82,18 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { booleanField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(booleanField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - booleanField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); - expect(customCursor).toMatchSnapshot(); expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); diff --git a/src/visualBuilder/__test__/hover/fields/date.test.ts b/src/visualBuilder/__test__/hover/fields/date.test.ts index c399f460..57380bfc 100644 --- a/src/visualBuilder/__test__/hover/fields/date.test.ts +++ b/src/visualBuilder/__test__/hover/fields/date.test.ts @@ -1,5 +1,5 @@ import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -82,18 +82,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { dataField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(dataField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - dataField.dispatchEvent(mousemoveEvent); - await sleep(0); + const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/file.test.ts b/src/visualBuilder/__test__/hover/fields/file.test.ts index a0e88a6b..8b468559 100644 --- a/src/visualBuilder/__test__/hover/fields/file.test.ts +++ b/src/visualBuilder/__test__/hover/fields/file.test.ts @@ -1,6 +1,6 @@ -import { screen } from "@testing-library/preact"; +import { screen, waitFor } from "@testing-library/preact"; import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -25,7 +25,18 @@ vi.mock("../../../utils/visualBuilderPostMessage", async () => { }; }); - +const convertToPx = (value: number) => { + return `${value}px` +} +const matchDimensions = (element: HTMLElement, hoverOutline: HTMLElement) => { + const elementDimensions = element.getBoundingClientRect() + // @ts-expect-error - TS doesn't know that style is a CSSStyleDeclaration + const hoverOutlineDimensions = hoverOutline?.style?._values as CSSStyleDeclaration; + expect(convertToPx(elementDimensions.x)).toBe(hoverOutlineDimensions.left); + expect(convertToPx(elementDimensions.y)).toBe(hoverOutlineDimensions.top); + expect(convertToPx(elementDimensions.width)).toBe(hoverOutlineDimensions.width); + expect(convertToPx(elementDimensions.height)).toBe(hoverOutlineDimensions.height); +} describe("When an element is hovered in visual builder mode", () => { let mousemoveEvent: Event; @@ -98,39 +109,32 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { fileField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(fileField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - fileField.dispatchEvent(mousemoveEvent); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); - expect(customCursor).toMatchSnapshot(); expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have a outline on the url as well", async () => { + test("should have a outline and custom cursor on the url as well", async () => { imageField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); + expect(imageField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on the url as well", async () => { - imageField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -210,65 +214,53 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); - - await sleep(0); expect(customCursor).toMatchSnapshot(); expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and custom cursor on individual instances", async () => { firstFileField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstFileField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" - ); + ) as HTMLElement; expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstFileField.dispatchEvent(mousemoveEvent); - await sleep(0); + matchDimensions(firstFileField, hoverOutline); + const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); - - expect(customCursor).toMatchSnapshot(); + expect(customCursor?.getAttribute('data-icon')).toBe('file'); expect(customCursor?.classList.contains("visible")).toBeTruthy(); + }); - test("should have outline on the url", async () => { + test("should have outline and custom cursor on the url", async () => { firstImageField.dispatchEvent(mousemoveEvent); + await waitForHoverOutline(); expect(firstImageField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" - ); + ) as HTMLElement; expect(hoverOutline).toMatchSnapshot(); - }); - - test("should have custom cursor on the url", async () => { - firstImageField.dispatchEvent(mousemoveEvent); + matchDimensions(firstImageField, hoverOutline); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); - - expect(customCursor).toMatchSnapshot(); expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); }); diff --git a/src/visualBuilder/__test__/hover/fields/group.test.ts b/src/visualBuilder/__test__/hover/fields/group.test.ts index 1469f4f2..cb8fb2f6 100644 --- a/src/visualBuilder/__test__/hover/fields/group.test.ts +++ b/src/visualBuilder/__test__/hover/fields/group.test.ts @@ -1,5 +1,5 @@ import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { sleep, waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; import { mockDomRect } from "./mockDomRect"; @@ -95,18 +95,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { groupField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(groupField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - groupField.dispatchEvent(mousemoveEvent); - await sleep(0); + const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -115,7 +112,7 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have a outline on the nested single line", async () => { + test("should have a outline and custom cursor on the nested single line", async () => { const singleLine = document.createElement("p"); singleLine.setAttribute( "data-cslp", @@ -129,29 +126,13 @@ describe("When an element is hovered in visual builder mode", () => { groupField.appendChild(singleLine); singleLine.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(singleLine).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - - test("should have custom cursor on the nested single line", async () => { - const singleLine = document.createElement("p"); - singleLine.setAttribute( - "data-cslp", - "all_fields.bltapikey.en-us.group.single_line" - ); - singleLine.getBoundingClientRect = vi - .fn() - .mockReturnValue(mockDomRect.singleLeft()); - - groupField.appendChild(singleLine); - - singleLine.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -223,18 +204,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -245,7 +223,7 @@ describe("When an element is hovered in visual builder mode", () => { test.skip("should have outline on the nested field", async () => { firstNestedMultiLine.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstNestedMultiLine).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" diff --git a/src/visualBuilder/__test__/hover/fields/html-rte.test.ts b/src/visualBuilder/__test__/hover/fields/html-rte.test.ts index 67f8cbc9..dd144b16 100644 --- a/src/visualBuilder/__test__/hover/fields/html-rte.test.ts +++ b/src/visualBuilder/__test__/hover/fields/html-rte.test.ts @@ -1,6 +1,6 @@ import { screen } from "@testing-library/preact"; import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -83,18 +83,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { htmlRteField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(htmlRteField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - htmlRteField.dispatchEvent(mousemoveEvent); - await sleep(0); + const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -152,19 +149,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -173,19 +166,15 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and cursor on individual instances", async () => { firstHtmlRteField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstHtmlRteField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstHtmlRteField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/json-rte.test.ts b/src/visualBuilder/__test__/hover/fields/json-rte.test.ts index 1db1dce7..bb4e415c 100644 --- a/src/visualBuilder/__test__/hover/fields/json-rte.test.ts +++ b/src/visualBuilder/__test__/hover/fields/json-rte.test.ts @@ -1,6 +1,6 @@ import { screen } from "@testing-library/preact"; import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -83,19 +83,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { jsonRteField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(jsonRteField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - jsonRteField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -153,19 +149,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -174,19 +166,15 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and custom cursor on individual instances", async () => { firstJsonRteField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstJsonRteField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstJsonRteField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/link.test.ts b/src/visualBuilder/__test__/hover/fields/link.test.ts index 1ceaf297..f36cd8cb 100644 --- a/src/visualBuilder/__test__/hover/fields/link.test.ts +++ b/src/visualBuilder/__test__/hover/fields/link.test.ts @@ -1,6 +1,6 @@ import { screen } from "@testing-library/preact"; import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -83,18 +83,14 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { linkField.dispatchEvent(mousemoveEvent); expect(linkField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - linkField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -149,19 +145,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -170,19 +162,15 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and custom cursor on individual instances", async () => { firstLinkField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstLinkField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstLinkField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/markdown.test.ts b/src/visualBuilder/__test__/hover/fields/markdown.test.ts index 58376e9a..804e506c 100644 --- a/src/visualBuilder/__test__/hover/fields/markdown.test.ts +++ b/src/visualBuilder/__test__/hover/fields/markdown.test.ts @@ -1,6 +1,6 @@ import { screen } from "@testing-library/preact"; import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -84,18 +84,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { markdownField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(markdownField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - markdownField.dispatchEvent(mousemoveEvent); - await sleep(0); + const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -153,19 +150,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -174,19 +167,15 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and custom cursor on individual instances", async () => { firstMarkdownField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstMarkdownField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstMarkdownField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/multi-line.test.ts b/src/visualBuilder/__test__/hover/fields/multi-line.test.ts index 4e4ce02e..09a639d7 100644 --- a/src/visualBuilder/__test__/hover/fields/multi-line.test.ts +++ b/src/visualBuilder/__test__/hover/fields/multi-line.test.ts @@ -1,6 +1,6 @@ import { screen } from "@testing-library/preact"; import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -83,19 +83,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { multiLineField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(multiLineField).toMatchSnapshot(); const hoverOutline = screen.getByTestId( "visual-builder__hover-outline" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - multiLineField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -152,19 +148,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { - await sleep(0); + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - await sleep(0); - container.dispatchEvent(mousemoveEvent); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -173,19 +165,15 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and custom cursor on individual instances", async () => { firstMultiLineField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstMultiLineField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstMultiLineField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/number.test.ts b/src/visualBuilder/__test__/hover/fields/number.test.ts index ec3196b5..dada8733 100644 --- a/src/visualBuilder/__test__/hover/fields/number.test.ts +++ b/src/visualBuilder/__test__/hover/fields/number.test.ts @@ -1,6 +1,6 @@ import { screen } from "@testing-library/preact"; import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { sleep, waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -83,19 +83,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { numberField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(numberField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - numberField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -150,19 +146,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -171,19 +163,15 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and custom cursor on individual instances", async () => { firstNumberField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstNumberField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstNumberField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/reference.test.ts b/src/visualBuilder/__test__/hover/fields/reference.test.ts index 8efe2542..c6bd2d45 100644 --- a/src/visualBuilder/__test__/hover/fields/reference.test.ts +++ b/src/visualBuilder/__test__/hover/fields/reference.test.ts @@ -1,5 +1,5 @@ import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -83,18 +83,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { referenceField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(referenceField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - referenceField.dispatchEvent(mousemoveEvent); - await sleep(0); + const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -151,19 +148,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -172,18 +165,15 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and custom cursor on individual instances", async () => { firstReferenceField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstReferenceField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstReferenceField.dispatchEvent(mousemoveEvent); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/select.test.ts b/src/visualBuilder/__test__/hover/fields/select.test.ts index 23b39d07..d4811d3c 100644 --- a/src/visualBuilder/__test__/hover/fields/select.test.ts +++ b/src/visualBuilder/__test__/hover/fields/select.test.ts @@ -1,5 +1,5 @@ import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../../../__test__/utils"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -94,19 +94,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { selectField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(selectField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - selectField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -163,20 +159,16 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", async () => { - container.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -185,9 +177,9 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", async () => { + test("should have outline and custom cursor on individual instances", async () => { firstSelectField.dispatchEvent(mousemoveEvent); - await sleep(0); + await waitForHoverOutline(); expect(firstSelectField).toMatchSnapshot(); expect(firstSelectField).toMatchSnapshot(); @@ -195,11 +187,7 @@ describe("When an element is hovered in visual builder mode", () => { "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", async () => { - firstSelectField.dispatchEvent(mousemoveEvent); - await sleep(0); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/hover/fields/single-line.test.ts b/src/visualBuilder/__test__/hover/fields/single-line.test.ts index 1c4b4c5a..edc5d32d 100644 --- a/src/visualBuilder/__test__/hover/fields/single-line.test.ts +++ b/src/visualBuilder/__test__/hover/fields/single-line.test.ts @@ -1,4 +1,5 @@ import { getFieldSchemaMap } from "../../../../__test__/data/fieldSchemaMap"; +import { waitForHoverOutline } from "../../../../__test__/utils"; import Config from "../../../../configManager/configManager"; import { VisualBuilder } from "../../../index"; import { FieldSchemaMap } from "../../../utils/fieldSchemaMap"; @@ -80,17 +81,15 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", () => { + test("should have outline and custom cursor", async () => { titleField.dispatchEvent(mousemoveEvent); + await waitForHoverOutline(); expect(titleField).toMatchSnapshot(); const hoverOutline = screen.getByTestId( "visual-builder__hover-outline" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", () => { - titleField.dispatchEvent(mousemoveEvent); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -122,13 +121,12 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", () => { + test("should have outline and custom cursor", async () => { singleLineField.dispatchEvent(mousemoveEvent); + await waitForHoverOutline(); expect(singleLineField).toMatchSnapshot(); expect(singleLineField.classList.contains("cslp-edit-mode")); - }); - test("should have custom cursor", () => { - singleLineField.dispatchEvent(mousemoveEvent); + const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -183,18 +181,16 @@ describe("When an element is hovered in visual builder mode", () => { visualBuilder.destroy(); }); - test("should have outline", async () => { + test("should have outline and custom cursor", async () => { container.dispatchEvent(mousemoveEvent); + await waitForHoverOutline(); expect(container).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor", () => { - container.dispatchEvent(mousemoveEvent); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); @@ -203,17 +199,15 @@ describe("When an element is hovered in visual builder mode", () => { expect(customCursor?.classList.contains("visible")).toBeTruthy(); }); - test("should have outline on individual instances", () => { + test("should have outline and custom cursor on individual instances", async () => { firstSingleLineField.dispatchEvent(mousemoveEvent); + await waitForHoverOutline(); expect(firstSingleLineField).toMatchSnapshot(); const hoverOutline = document.querySelector( "[data-testid='visual-builder__hover-outline']" ); expect(hoverOutline).toMatchSnapshot(); - }); - test("should have custom cursor on individual instances", () => { - firstSingleLineField.dispatchEvent(mousemoveEvent); const customCursor = document.querySelector( `[data-testid="visual-builder__cursor"]` ); diff --git a/src/visualBuilder/__test__/index.test.ts b/src/visualBuilder/__test__/index.test.ts index 8a20c31f..94ba2194 100644 --- a/src/visualBuilder/__test__/index.test.ts +++ b/src/visualBuilder/__test__/index.test.ts @@ -1,9 +1,9 @@ import crypto from "crypto"; import { getFieldSchemaMap } from "../../__test__/data/fieldSchemaMap"; -import { sleep } from "../../__test__/utils"; +import { getElementBytestId, mockGetBoundingClientRect, sleep, triggerAndWaitForClickAction, waitForBuilderSDKToBeInitialized, waitForToolbaxToBeVisible } from "../../__test__/utils"; import Config from "../../configManager/configManager"; import { FieldSchemaMap } from "../utils/fieldSchemaMap"; -import { waitFor, screen } from "@testing-library/preact"; +import { waitFor, screen, cleanup } from "@testing-library/preact"; import { VisualBuilderPostMessageEvents } from "../utils/types/postMessage.types"; import { VisualBuilder } from "../index"; import visualBuilderPostMessage from "../utils/visualBuilderPostMessage"; @@ -38,12 +38,6 @@ Object.defineProperty(globalThis, "crypto", { }, }); -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - describe("Visual builder", () => { beforeAll(() => { FieldSchemaMap.setFieldSchema( @@ -64,58 +58,61 @@ describe("Visual builder", () => { vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); }); - afterEach(() => { + beforeEach(() => { + (visualBuilderPostMessage?.send as Mock).mockClear(); document.getElementsByTagName("html")[0].innerHTML = ""; + cleanup(); }); afterAll(() => { FieldSchemaMap.clear(); }); - test("should append a visual builder container to the DOM", () => { + test("should append a visual builder container to the DOM", async () => { let visualBuilderDOM = document.querySelector( ".visual-builder__container" ); expect(visualBuilderDOM).toBeNull(); - new VisualBuilder(); + const x = new VisualBuilder(); + await waitForBuilderSDKToBeInitialized(visualBuilderPostMessage); visualBuilderDOM = document.querySelector( `[data-testid="visual-builder__container"]` ); expect(visualBuilderDOM).toMatchSnapshot(); + x.destroy(); }); - describe("inline editing", () => { - let h1Tag: HTMLHeadingElement; - beforeEach(() => { - h1Tag = document.createElement("h1"); - h1Tag.textContent = INLINE_EDITABLE_FIELD_VALUE; - h1Tag.setAttribute( - "data-cslp", - "all_fields.blt58a50b4cebae75c5.en-us.modular_blocks.0.block.single_line" - ); - document.body.appendChild(h1Tag); - }); - - test("should add overlay to DOM when clicked", async () => { - new VisualBuilder(); - - await sleep(0); - h1Tag.click(); - await sleep(0); - - expect(document.body).toMatchSnapshot(); - }); + test("should add overlay to DOM when clicked", async () => { + const h1Tag = document.createElement("h1"); + h1Tag.textContent = INLINE_EDITABLE_FIELD_VALUE; + h1Tag.setAttribute( + "data-cslp", + "all_fields.blt58a50b4cebae75c5.en-us.modular_blocks.0.block.single_line" + ); + document.body.appendChild(h1Tag); + mockGetBoundingClientRect(h1Tag); + const x = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, h1Tag); + await waitFor(() => { + const overlayOutline = document.querySelector('[data-testid="visual-builder__overlay--outline"]'); + expect(overlayOutline).toHaveStyle({ + top: "10px", + left: "10px", + width: "10px", + height: "5px", + "outline-color": "rgb(113, 92, 221)" + }); + }) + x.destroy(); }); describe("on click, the sdk", () => { afterEach(() => { document.getElementsByTagName("html")[0].innerHTML = ""; - // clear static data in VisualBuilder - }); test("should do nothing if data-cslp not available", async () => { @@ -123,9 +120,7 @@ describe("Visual builder", () => { document.body.appendChild(h1); const x = new VisualBuilder(); - - h1.click(); - await sleep(0); + await triggerAndWaitForClickAction(visualBuilderPostMessage, h1, {skipWaitForFieldType: true}); expect(document.body).toMatchSnapshot(); x.destroy(); @@ -170,6 +165,9 @@ describe("Visual builder", () => { ); }); + beforeEach(() => { + document.getElementsByTagName("html")[0].innerHTML = ""; + }) test("single line should be contenteditable", async () => { const h1 = document.createElement("h1"); h1.textContent = INLINE_EDITABLE_FIELD_VALUE; @@ -189,9 +187,7 @@ describe("Visual builder", () => { document.body.appendChild(h1); const x = new VisualBuilder(); - await sleep(0); - h1.click(); - await sleep(0); + await triggerAndWaitForClickAction(visualBuilderPostMessage, h1); await waitFor(() => { expect(h1.getAttribute("contenteditable")).toBe("true"); @@ -217,14 +213,7 @@ describe("Visual builder", () => { h1.textContent = INLINE_EDITABLE_FIELD_VALUE; document.body.appendChild(h1); const x = new VisualBuilder(); - - await sleep(0); - h1.click(); - await sleep(0); - - // h1.addEventListener("keydown", (e: KeyboardEvent) => { - // e.code.includes("") - // }) + await triggerAndWaitForClickAction(visualBuilderPostMessage, h1); await waitFor(() => { expect(h1.getAttribute("contenteditable")).toBe("true"); @@ -233,7 +222,8 @@ describe("Visual builder", () => { x.destroy(); }); - test("file should render a replacer and remove when it is not", async () => { + //TODO: Fix this test on CI + test.skip("file should render a replacer and remove when it is not", async () => { const h1 = document.createElement("h1"); h1.setAttribute( "data-cslp", @@ -241,8 +231,7 @@ describe("Visual builder", () => { ); document.body.appendChild(h1); const x = new VisualBuilder(); - h1.click(); - await sleep(0); + await triggerAndWaitForClickAction(visualBuilderPostMessage, h1); let replaceBtn = document.getElementsByClassName( "visual-builder__replace-button" @@ -258,21 +247,19 @@ describe("Visual builder", () => { ); document.body.appendChild(h2); - h2.click(); - await sleep(0); - + await triggerAndWaitForClickAction(visualBuilderPostMessage, h2); replaceBtn = document.getElementsByClassName( "visual-builder__replace-button" )[0]; expect(replaceBtn).toBeUndefined(); x.destroy(); - }); + }, { timeout: 10 * 1000 }); }); }); }); -describe("visual builder DOM", () => { +describe.skip("visual builder DOM", () => { let h1: HTMLHeadElement; beforeAll(() => { @@ -281,18 +268,6 @@ describe("visual builder DOM", () => { getFieldSchemaMap().all_fields ); Config.set("mode", 2); - vi.spyOn( - document.documentElement, - "clientWidth", - "get" - ).mockReturnValue(100); - vi.spyOn( - document.documentElement, - "clientHeight", - "get" - ).mockReturnValue(100); - vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); - (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string, args) => { if ( @@ -329,6 +304,19 @@ describe("visual builder DOM", () => { }); beforeEach(() => { + document.getElementsByTagName('html')[0].innerHTML = ''; + (visualBuilderPostMessage?.send as Mock).mockClear(); + vi.spyOn( + document.documentElement, + "clientWidth", + "get" + ).mockReturnValue(100); + vi.spyOn( + document.documentElement, + "clientHeight", + "get" + ).mockReturnValue(100); + vi.spyOn(document.body, "scrollHeight", "get").mockReturnValue(100); h1 = document.createElement("h1"); h1.setAttribute( @@ -338,14 +326,7 @@ describe("visual builder DOM", () => { h1.innerText = INLINE_EDITABLE_FIELD_VALUE; - h1.getBoundingClientRect = vi.fn(() => ({ - left: 10, - right: 20, - top: 10, - bottom: 20, - width: 10, - height: 5, - })) as any; + mockGetBoundingClientRect(h1); document.body.appendChild(h1); }); @@ -359,7 +340,8 @@ describe("visual builder DOM", () => { }); test("should have an overlay over the element", async () => { - new VisualBuilder(); + const visualBuilder = new VisualBuilder(); + await waitForBuilderSDKToBeInitialized(visualBuilderPostMessage); let visualBuilderOverlayWrapper = document.querySelector( `[data-testid="visual-builder__overlay__wrapper"]` @@ -367,38 +349,31 @@ describe("visual builder DOM", () => { expect(visualBuilderOverlayWrapper).toMatchSnapshot(); - await sleep(0); - // TODO - should we be using userEvent? which is more - // accurate simulation of actual events that are triggered - // in a browser on clicking. Right now, this test fails if we - // use userEvent.click - // await userEvent.click(h1); - h1.click(); - await sleep(0); + await triggerAndWaitForClickAction(visualBuilderPostMessage, h1); await waitFor(() => { expect(h1.getAttribute("contenteditable")).toBe("true"); }); - visualBuilderOverlayWrapper = await screen.findByTestId( - "visual-builder__overlay__wrapper" - ); - expect(visualBuilderOverlayWrapper?.classList.contains("visible")).toBe( - true + visualBuilderOverlayWrapper = document.querySelector( + `[data-testid="visual-builder__overlay__wrapper"]` ); + await waitFor(() => { + expect(visualBuilderOverlayWrapper?.classList.contains("visible")).toBe( + true + ); + }); expect(visualBuilderOverlayWrapper).toMatchSnapshot(); - const visualBuilderWrapperTopOverlay = await screen.findByTestId( - "visual-builder__overlay--top" - ); - const visualBuilderWrapperLeftOverlay = await screen.findByTestId( + const visualBuilderWrapperTopOverlay = getElementBytestId('visual-builder__overlay--top') as HTMLDivElement; + const visualBuilderWrapperLeftOverlay = getElementBytestId( "visual-builder__overlay--left" - ); - const visualBuilderWrapperRightOverlay = await screen.findByTestId( + ) as HTMLDivElement; + const visualBuilderWrapperRightOverlay = getElementBytestId( "visual-builder__overlay--right" - ); - const visualBuilderWrapperBottomOverlay = await screen.findByTestId( + ) as HTMLDivElement; + const visualBuilderWrapperBottomOverlay = getElementBytestId( "visual-builder__overlay--bottom" - ); + ) as HTMLDivElement; expect(visualBuilderWrapperTopOverlay.style.top).toBe("0px"); expect(visualBuilderWrapperTopOverlay.style.left).toBe("0px"); @@ -417,16 +392,13 @@ describe("visual builder DOM", () => { expect(visualBuilderWrapperRightOverlay.style.top).toBe("10px"); expect(visualBuilderWrapperRightOverlay.style.left).toBe("20px"); expect(visualBuilderWrapperRightOverlay.style.width).toBe("80px"); + visualBuilder.destroy(); }); test("should remove the DOM when method is triggered", async () => { const visualBuilder = new VisualBuilder(); - await sleep(0); - h1.click(); - // We need this sleep as there are some async task happening while - // the overlay is being rendered. - await sleep(0); + await triggerAndWaitForClickAction(visualBuilderPostMessage, h1); let visualBuilderContainer = document.querySelector( `[data-testid="visual-builder__container"]` @@ -444,40 +416,28 @@ describe("visual builder DOM", () => { }); test("should hide the DOM, when it is clicked", async () => { - new VisualBuilder(); - - await sleep(0); - h1.click(); - // We need this sleep as there are some async task happening while - // the overlay is being rendered. - await sleep(0); - - expect(h1.getAttribute("contenteditable")).toBe("true"); + const visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, h1); + const visualBuilderOverlayWrapper = await document.querySelector( + "[data-testid='visual-builder__overlay__wrapper']" + ); await waitFor(() => { - expect(h1.getAttribute("contenteditable")).toBe("true"); + expect(visualBuilderOverlayWrapper?.classList.contains("visible")).toBe( + true + ); }); - let visualBuilderOverlayWrapper = await screen.findByTestId( - "visual-builder__overlay__wrapper" - ); - expect(visualBuilderOverlayWrapper?.classList.contains("visible")).toBe( - true - ); const visualBuilderOverlayTop = document.querySelector(` [data-testid="visual-builder__overlay--top"]`) as HTMLDivElement; - visualBuilderOverlayTop?.click(); - await sleep(0); - + await triggerAndWaitForClickAction(visualBuilderPostMessage, visualBuilderOverlayTop, {skipWaitForFieldType: true}); await waitFor(() => { expect(h1.getAttribute("contenteditable")).toBeNull(); }); - visualBuilderOverlayWrapper = await screen.findByTestId( - "visual-builder__overlay__wrapper" - ); expect(visualBuilderOverlayWrapper?.classList.contains("visible")).toBe( - true + false ); + visualBuilder.destroy(); }); }); diff --git a/src/visualBuilder/__test__/visualBuilderInput.test.tsx b/src/visualBuilder/__test__/visualBuilderInput.test.tsx index a5b167f6..f30a1dc3 100644 --- a/src/visualBuilder/__test__/visualBuilderInput.test.tsx +++ b/src/visualBuilder/__test__/visualBuilderInput.test.tsx @@ -1,20 +1,14 @@ -import { fireEvent, waitFor } from "@testing-library/preact"; +import { fireEvent, waitFor, screen, act } from "@testing-library/preact"; import Config from "../../configManager/configManager"; import { FieldSchemaMap } from "../utils/fieldSchemaMap"; import { getFieldSchemaMap } from "../../__test__/data/fieldSchemaMap"; import visualBuilderPostMessage from "../utils/visualBuilderPostMessage"; import { VisualBuilderPostMessageEvents } from "../utils/types/postMessage.types"; -import { sleep } from "../../__test__/utils"; +import { triggerAndWaitForClickAction } from "../../__test__/utils"; import { Mock } from "vitest"; import { VisualBuilder } from "../index"; import userEvent from "@testing-library/user-event"; -global.ResizeObserver = vi.fn().mockImplementation(() => ({ - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn(), -})); - vi.mock("../utils/visualBuilderPostMessage", async () => { const { getAllContentTypes } = await vi.importActual< typeof import("../../__test__/data/contentType") @@ -59,9 +53,7 @@ describe("When an inline element is edited in visual builder mode", () => { "all_fields", getFieldSchemaMap().all_fields ); - }); - beforeEach(() => { Config.reset(); Config.set("mode", 2); mouseClickEvent = new Event("click", { @@ -70,21 +62,23 @@ describe("When an inline element is edited in visual builder mode", () => { }); }); - afterEach(() => { + afterAll(() => { vi.clearAllMocks(); - document.body.innerHTML = ""; - }); + document.getElementsByTagName('html')[0].innerHTML = ''; - afterAll(() => { Config.reset(); }); + afterEach(() => { + (visualBuilderPostMessage?.send as Mock)?.mockClear(); + }); + describe("single line field", () => { let singleLineField: HTMLParagraphElement; let visualBuilder: VisualBuilder; let overlayWrapper: HTMLDivElement; - beforeAll(() => { + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string) => { if ( @@ -106,9 +100,7 @@ describe("When an inline element is edited in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { singleLineField = document.createElement("p"); singleLineField.setAttribute( "data-cslp", @@ -118,30 +110,26 @@ describe("When an inline element is edited in visual builder mode", () => { document.body.appendChild(singleLineField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, singleLineField); overlayWrapper = document.querySelector( ".visual-builder__overlay__wrapper" ) as HTMLDivElement; }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - singleLineField.dispatchEvent(mouseClickEvent); expect(singleLineField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - singleLineField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test("should be able to edit inline text present", async () => { - fireEvent.click(singleLineField); - await sleep(0); - expect(singleLineField).toHaveAttribute("contenteditable"); fireEvent.click(singleLineField); @@ -153,7 +141,6 @@ describe("When an inline element is edited in visual builder mode", () => { }); test("should send a update field message to parent", async () => { - fireEvent.click(singleLineField); await waitFor(() => { expect(singleLineField).toHaveAttribute("contenteditable"); }); @@ -197,9 +184,8 @@ describe("When an inline element is edited in visual builder mode", () => { let firstSingleLineField: HTMLParagraphElement; let secondSingleLineField: HTMLParagraphElement; let visualBuilder: VisualBuilder; - let overlayWrapper: HTMLDivElement; - beforeAll(() => { + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string, args) => { if ( @@ -218,9 +204,7 @@ describe("When an inline element is edited in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -246,28 +230,85 @@ describe("When an inline element is edited in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); - overlayWrapper = document.querySelector( - ".visual-builder__overlay__wrapper" - ) as HTMLDivElement; + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); test("should have outline", () => { - container.dispatchEvent(mouseClickEvent); expect(container.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - container.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); + }); + describe("single line field (multiple): individual inline", () => { + let container: HTMLDivElement; + let firstSingleLineField: HTMLParagraphElement; + let secondSingleLineField: HTMLParagraphElement; + let visualBuilder: VisualBuilder; + let overlayWrapper: HTMLDivElement; + + beforeEach(async () => { + (visualBuilderPostMessage?.send as Mock).mockImplementation( + (eventName: string, args) => { + if ( + eventName === + VisualBuilderPostMessageEvents.GET_FIELD_DATA + ) { + const values: Record = { + single_line_textbox_multiple_: ["Hello", "world"], + "single_line_textbox_multiple_.0": "Hello", + "single_line_textbox_multiple_.1": "world", + }; + return Promise.resolve({ + fieldData: values[args.entryPath], + }); + } + return Promise.resolve({}); + } + ); + + container = document.createElement("div"); + container.setAttribute( + "data-cslp", + "all_fields.bltapikey.en-us.single_line_textbox_multiple_" + ); + + firstSingleLineField = document.createElement("p"); + firstSingleLineField.setAttribute( + "data-cslp", + "all_fields.bltapikey.en-us.single_line_textbox_multiple_.0" + ); + firstSingleLineField.textContent = "Hello"; + + secondSingleLineField = document.createElement("p"); + secondSingleLineField.setAttribute( + "data-cslp", + "all_fields.bltapikey.en-us.single_line_textbox_multiple_.1" + ); + secondSingleLineField.textContent = "world"; + + container.appendChild(firstSingleLineField); + container.appendChild(secondSingleLineField); + document.body.appendChild(container); + + visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, firstSingleLineField); + overlayWrapper = document.querySelector( + ".visual-builder__overlay__wrapper" + ) as HTMLDivElement; + }); + + afterEach(() => { + visualBuilder.destroy(); + }); test("should be able to edit individual inline text present", async () => { - firstSingleLineField.dispatchEvent(mouseClickEvent); await waitFor(() => { expect(firstSingleLineField).toHaveAttribute("contenteditable"); }); @@ -295,7 +336,6 @@ describe("When an inline element is edited in visual builder mode", () => { }); test("should send a update field message to parent when editing an individual element", async () => { - fireEvent.click(firstSingleLineField); await waitFor(() => { expect(firstSingleLineField).toHaveAttribute("contenteditable"); }); @@ -342,7 +382,7 @@ describe("When an inline element is edited in visual builder mode", () => { let visualBuilder: VisualBuilder; let overlayWrapper: HTMLDivElement; - beforeAll(() => { + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string, args) => { if ( @@ -356,9 +396,7 @@ describe("When an inline element is edited in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { multiLineField = document.createElement("p"); multiLineField.setAttribute( "data-cslp", @@ -367,33 +405,27 @@ describe("When an inline element is edited in visual builder mode", () => { multiLineField.textContent = "Hello world"; document.body.appendChild(multiLineField); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, multiLineField); overlayWrapper = document.querySelector( ".visual-builder__overlay__wrapper" ) as HTMLDivElement; }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); + (visualBuilderPostMessage?.send as Mock).mockClear(); }); test("should have outline", () => { - multiLineField.dispatchEvent(mouseClickEvent); expect(multiLineField.classList.contains("cslp-edit-mode")); }); test("should have an overlay", () => { - multiLineField.dispatchEvent(mouseClickEvent); const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); test("should be able to edit inline text present", async () => { - multiLineField.dispatchEvent(mouseClickEvent); - await waitFor(() => { - expect(multiLineField).toHaveAttribute("contenteditable"); - }); - - fireEvent.click(multiLineField); fireEvent.change(multiLineField, { target: { textContent: "test text" }, }); @@ -402,12 +434,6 @@ describe("When an inline element is edited in visual builder mode", () => { }); test("should send a update field message to parent", async () => { - multiLineField.dispatchEvent(mouseClickEvent); - await waitFor(() => { - expect(multiLineField).toHaveAttribute("contenteditable"); - }); - - fireEvent.click(multiLineField); fireEvent.change(multiLineField, { target: { textContent: "test text" }, }); @@ -447,7 +473,7 @@ describe("When an inline element is edited in visual builder mode", () => { let visualBuilder: VisualBuilder; let overlayWrapper: HTMLDivElement; - beforeAll(() => { + beforeAll(async () => { (visualBuilderPostMessage?.send as Mock).mockImplementation( (eventName: string, args) => { if ( @@ -466,9 +492,7 @@ describe("When an inline element is edited in visual builder mode", () => { return Promise.resolve({}); } ); - }); - beforeEach(() => { container = document.createElement("div"); container.setAttribute( "data-cslp", @@ -494,12 +518,13 @@ describe("When an inline element is edited in visual builder mode", () => { document.body.appendChild(container); visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, container); overlayWrapper = document.querySelector( ".visual-builder__overlay__wrapper" ) as HTMLDivElement; }); - afterEach(() => { + afterAll(() => { visualBuilder.destroy(); }); @@ -513,14 +538,68 @@ describe("When an inline element is edited in visual builder mode", () => { const overlay = document.querySelector(".visual-builder__overlay"); expect(overlay!.classList.contains("visible")); }); + }); + describe("multi line field (multiple): individual inline", () => { + let container: HTMLDivElement; + let firstMultiLineField: HTMLParagraphElement; + let secondMultiLineField: HTMLParagraphElement; + let visualBuilder: VisualBuilder; - test("should be able to edit individual inline text present", async () => { - firstMultiLineField.dispatchEvent(mouseClickEvent); - await waitFor(() => { - expect(firstMultiLineField).toHaveAttribute("contenteditable"); - }); + beforeEach(async () => { + document.body.innerHTML = ""; + (visualBuilderPostMessage?.send as Mock).mockClear(); + (visualBuilderPostMessage?.send as Mock).mockImplementation( + (eventName: string, args) => { + if ( + eventName === + VisualBuilderPostMessageEvents.GET_FIELD_DATA + ) { + const values: Record = { + multi_line_textbox_multiple_: ["Hello", "world"], + "multi_line_textbox_multiple_.0": "Hello", + "multi_line_textbox_multiple_.1": "world", + }; + return Promise.resolve({ + fieldData: values[args.entryPath], + }); + } + return Promise.resolve({}); + } + ); + + container = document.createElement("div"); + container.setAttribute( + "data-cslp", + "all_fields.bltapikey.en-us.multi_line_textbox_multiple_" + ); + + firstMultiLineField = document.createElement("p"); + firstMultiLineField.setAttribute( + "data-cslp", + "all_fields.bltapikey.en-us.multi_line_textbox_multiple_.0" + ); + firstMultiLineField.textContent = "Hello"; + + secondMultiLineField = document.createElement("p"); + secondMultiLineField.setAttribute( + "data-cslp", + "all_fields.bltapikey.en-us.multi_line_textbox_multiple_.1" + ); + secondMultiLineField.textContent = "world"; - fireEvent.click(firstMultiLineField); + container.appendChild(firstMultiLineField); + container.appendChild(secondMultiLineField); + document.body.appendChild(container); + + visualBuilder = new VisualBuilder(); + await triggerAndWaitForClickAction(visualBuilderPostMessage, firstMultiLineField); + }); + + afterEach(() => { + visualBuilder.destroy(); + }); + + test("should be able to edit individual inline text present", async () => { fireEvent.change(firstMultiLineField, { target: { textContent: "test text" }, }); @@ -540,19 +619,17 @@ describe("When an inline element is edited in visual builder mode", () => { }); test("should send a update field message to parent when editing an individual element", async () => { - firstMultiLineField.dispatchEvent(mouseClickEvent); - await waitFor(() => { - expect(firstMultiLineField).toHaveAttribute("contenteditable"); - }); - - fireEvent.click(firstMultiLineField); fireEvent.change(firstMultiLineField, { target: { textContent: "test text 1" }, }); expect(firstMultiLineField).toHaveTextContent("test text 1"); - - overlayWrapper.dispatchEvent(mouseClickEvent); + const overlayWrapper = document.querySelector( + ".visual-builder__overlay__wrapper" + ) as HTMLDivElement; + await act(async () => { + await fireEvent.click(overlayWrapper); + }) await waitFor(() => { expect(visualBuilderPostMessage?.send).toHaveBeenCalledWith( VisualBuilderPostMessageEvents.UPDATE_FIELD, @@ -584,7 +661,6 @@ describe("When an inline element is edited in visual builder mode", () => { }); }); }); - describe.skip("number field", () => { let numberField: HTMLParagraphElement; let visualBuilder: VisualBuilder; diff --git a/src/visualBuilder/components/__test__/addInstanceButton.test.tsx b/src/visualBuilder/components/__test__/addInstanceButton.test.tsx index 72d5f45a..92fc7364 100644 --- a/src/visualBuilder/components/__test__/addInstanceButton.test.tsx +++ b/src/visualBuilder/components/__test__/addInstanceButton.test.tsx @@ -1,4 +1,5 @@ import { + act, cleanup, fireEvent, getByTestId, @@ -10,15 +11,17 @@ import AddInstanceButtonComponent from "../addInstanceButton"; describe("AddInstanceButtonComponent", () => { afterEach(cleanup); - test("renders button with proper class and icon", () => { + test("renders button with proper class and icon", async () => { const onClickCallback = vi.fn(); - render( - - ); + await act(() => { + render( + + ); + }) const buttonElement = getByTestId( document.body, "visual-builder-add-instance-button" @@ -30,15 +33,17 @@ describe("AddInstanceButtonComponent", () => { expect(buttonElement.querySelector("path")).toBeTruthy(); }); - test("calls onClickCallback when button is clicked", () => { + test("calls onClickCallback when button is clicked", async () => { const onClickCallback = vi.fn(); - render( - - ); + await act(() => { + render( + + ); + }) const buttonElement = getByTestId( document.body, "visual-builder-add-instance-button" diff --git a/src/visualBuilder/components/__test__/fieldLabelWrapper.test.tsx b/src/visualBuilder/components/__test__/fieldLabelWrapper.test.tsx index 76f1b16a..cb78ad5a 100644 --- a/src/visualBuilder/components/__test__/fieldLabelWrapper.test.tsx +++ b/src/visualBuilder/components/__test__/fieldLabelWrapper.test.tsx @@ -4,6 +4,7 @@ import { CslpData } from "../../../cslp/types/cslp.types"; import { VisualBuilderCslpEventDetails } from "../../types/visualBuilder.types"; import { VisualBuilderPostMessageEvents } from "../../utils/types/postMessage.types"; import { singleLineFieldSchema } from "../../../__test__/data/fields"; +import { asyncRender } from "../../../__test__/utils"; const DISPLAY_NAMES = { mockFieldCslp: "Field 0", @@ -120,7 +121,7 @@ describe("FieldLabelWrapperComponent", () => { const mockGetParentEditable = () => document.createElement("div"); test("renders current field and parent fields correctly", async () => { - const { findByText } = render( + const { findByText } = await asyncRender( { }); test("displays current field icon", async () => { - const { findByTestId } = render( + const { findByTestId } = await asyncRender( { }); test("renders with correct class when field is disabled", async () => { - const { findByTestId } = render( + const { findByTestId } = await asyncRender( { const fieldLabel = await findByTestId( "visual-builder__focused-toolbar__field-label-wrapper" ); - screen.debug(fieldLabel); - waitFor(() => { + await waitFor(() => { expect(fieldLabel).toHaveClass( "visual-builder__focused-toolbar--field-disabled" ); diff --git a/src/visualBuilder/components/__test__/fieldToolbar.test.tsx b/src/visualBuilder/components/__test__/fieldToolbar.test.tsx index d6820bc2..47b7cf90 100644 --- a/src/visualBuilder/components/__test__/fieldToolbar.test.tsx +++ b/src/visualBuilder/components/__test__/fieldToolbar.test.tsx @@ -1,4 +1,4 @@ -import { cleanup, fireEvent, render } from "@testing-library/preact"; +import { act, cleanup, fireEvent, render, waitFor, screen } from "@testing-library/preact"; import { CslpData } from "../../../cslp/types/cslp.types"; import { FieldSchemaMap } from "../../utils/fieldSchemaMap"; import { @@ -8,6 +8,7 @@ import { import { ISchemaFieldMap } from "../../utils/types/index.types"; import FieldToolbarComponent from "../FieldToolbar"; import { mockMultipleLinkFieldSchema } from "../../../__test__/data/fields"; +import { asyncRender } from "../../../__test__/utils"; vi.mock("../../utils/instanceHandlers", () => ({ handleMoveInstance: vi.fn(), @@ -57,6 +58,7 @@ describe("MultipleFieldToolbarComponent", () => { let targetElement: HTMLDivElement; beforeEach(() => { + document.body.innerHTML = ""; targetElement = document.createElement("div"); targetElement.setAttribute("data-testid", "mock-target-element"); document.body.appendChild(targetElement); @@ -73,7 +75,7 @@ describe("MultipleFieldToolbarComponent", () => { }); test("renders toolbar buttons correctly", async () => { - const { findByTestId } = render( + const { findByTestId } = await asyncRender( { }); test("calls handleMoveInstance with 'previous' when move left button is clicked", async () => { - const { findByTestId } = render( + const { findByTestId } = await asyncRender( { }); test("calls handleMoveInstance with 'next' when move right button is clicked", async () => { - const { findByTestId } = render( + const { findByTestId } = await asyncRender( { }); test("calls handleDeleteInstance when delete button is clicked", async () => { - const { findByTestId } = render( + const { findByTestId } = await asyncRender( { "visual-builder__focused-toolbar__multiple-field-toolbar__delete-button" ); expect(deleteButton).toBeInTheDocument(); - - fireEvent.click(deleteButton); - - expect(handleDeleteInstance).toHaveBeenCalledWith( - mockMultipleFieldMetadata - ); + await act(() => { + fireEvent.click(deleteButton); + }); + + await waitFor(() => { + expect(handleDeleteInstance).toHaveBeenCalledWith( + mockMultipleFieldMetadata + ); + }) }); }); diff --git a/src/visualBuilder/components/__test__/icons.test.tsx b/src/visualBuilder/components/__test__/icons.test.tsx index df06fd31..920c4c7f 100644 --- a/src/visualBuilder/components/__test__/icons.test.tsx +++ b/src/visualBuilder/components/__test__/icons.test.tsx @@ -1,4 +1,4 @@ -import { render } from "@testing-library/preact"; +import { cleanup, render } from "@testing-library/preact"; import { CaretIcon, DeleteIcon, @@ -8,11 +8,15 @@ import { EditIcon, PlusIcon, } from "../icons"; +import { asyncRender } from "../../../__test__/utils"; describe("IconComponents", () => { + afterEach(() => { + cleanup(); + }) describe("CaretIcon", () => { - test("renders with correct dimensions, fill, and stroke colors", () => { - const { container } = render(); + test("renders with correct dimensions, fill, and stroke colors", async () => { + const { container } = await asyncRender(); const svgElement = container.querySelector("svg"); const strokeAttribute = svgElement?.getAttribute("stroke"); expect(svgElement).toBeInTheDocument(); @@ -28,8 +32,8 @@ describe("IconComponents", () => { }); describe("DeleteIcon", () => { - test("renders with correct dimensions, fill, and stroke colors", () => { - const { container } = render(); + test("renders with correct dimensions, fill, and stroke colors", async () => { + const { container } = await asyncRender(); const svgElement = container.querySelector("svg"); const strokeAttribute = svgElement?.getAttribute("stroke"); expect(svgElement).toBeInTheDocument(); @@ -45,8 +49,8 @@ describe("IconComponents", () => { }); describe("MoveLeftIcon", () => { - test("renders with correct dimensions, fill, and stroke colors", () => { - const { container } = render(); + test("renders with correct dimensions, fill, and stroke colors", async () => { + const { container } = await asyncRender(); const svgElement = container.querySelector("svg"); const strokeAttribute = svgElement?.getAttribute("stroke"); expect(svgElement).toBeInTheDocument(); @@ -62,8 +66,8 @@ describe("IconComponents", () => { }); describe("MoveRightIcon", () => { - test("renders with correct dimensions, fill, and stroke colors", () => { - const { container } = render(); + test("renders with correct dimensions, fill, and stroke colors", async() => { + const { container } = await asyncRender(); const svgElement = container.querySelector("svg"); const strokeAttribute = svgElement?.getAttribute("stroke"); expect(svgElement).toBeInTheDocument(); @@ -79,8 +83,8 @@ describe("IconComponents", () => { }); describe("InfoIcon", () => { - test("renders with correct dimensions, fill, and stroke colors", () => { - const { container } = render(); + test("renders with correct dimensions, fill, and stroke colors", async () => { + const { container } = await asyncRender(); const svgElement = container.querySelector("svg"); const strokeAttribute = svgElement?.getAttribute("stroke"); expect(svgElement).toBeInTheDocument(); @@ -96,8 +100,8 @@ describe("IconComponents", () => { }); describe("EditIcon", () => { - test("renders with correct dimensions, fill, and stroke colors", () => { - const { container } = render(); + test("renders with correct dimensions, fill, and stroke colors", async () => { + const { container } = await asyncRender(); const svgElement = container.querySelector("svg"); const strokeAttribute = svgElement?.getAttribute("stroke"); expect(svgElement).toBeInTheDocument(); @@ -113,8 +117,8 @@ describe("IconComponents", () => { }); describe("PlusIcon", () => { - test("renders with correct dimensions, fill, and stroke colors", () => { - const { container } = render(); + test("renders with correct dimensions, fill, and stroke colors", async () => { + const { container } = await asyncRender(); const svgElement = container.querySelector("svg"); const strokeAttribute = svgElement?.getAttribute("stroke"); expect(svgElement).toBeInTheDocument(); diff --git a/src/visualBuilder/components/__test__/pseudoEditableField.test.tsx b/src/visualBuilder/components/__test__/pseudoEditableField.test.tsx index b3d7204e..9b4815f0 100644 --- a/src/visualBuilder/components/__test__/pseudoEditableField.test.tsx +++ b/src/visualBuilder/components/__test__/pseudoEditableField.test.tsx @@ -2,13 +2,14 @@ import { render, cleanup } from "@testing-library/preact"; import PseudoEditableFieldComponent from "../pseudoEditableField"; import getStyleOfAnElement from "./../../utils/getStyleOfAnElement"; import { Mock } from "vitest"; +import { asyncRender } from "../../../__test__/utils"; vi.mock("./../../utils/getStyleOfAnElement"); describe("PseudoEditableFieldComponent", () => { afterEach(cleanup); - test("renders correctly with provided props", () => { + test("renders correctly with provided props", async () => { (getStyleOfAnElement as Mock).mockReturnValue({ "font-size": "16px", color: "rgb(255, 0, 0)", @@ -18,7 +19,7 @@ describe("PseudoEditableFieldComponent", () => { editableElement.textContent = "Editable Text"; const config = { textContent: "Editable Text" }; - const { getByTestId } = render( + const { getByTestId } = await asyncRender( { let visualBuilderContainer: HTMLDivElement; beforeEach(() => { + document.getElementsByTagName('html')[0].innerHTML = ''; Config.reset(); Config.set("stackDetails.apiKey", "bltapikey"); Config.set("stackDetails.environment", "bltenvironment"); @@ -23,8 +25,8 @@ describe("StartEditingButtonComponent", () => { Config.reset(); }); - test("renders correctly with EditIcon and Start Editing text", () => { - const { getByText, getByTestId } = render( + test("renders correctly with EditIcon and Start Editing text", async () => { + const { getByText, getByTestId } = await asyncRender( ); @@ -35,13 +37,10 @@ describe("StartEditingButtonComponent", () => { expect(startEditingText).toBeInTheDocument(); }); - test("should update the href when clicked", () => { - const { getByTestId } = render(); + test("should update the href when clicked", async () => { + const { getByTestId } = await asyncRender(); const button = getByTestId("vcms-start-editing-btn"); - // TODO clicking on the link, leads to an error (Not implemented: navigation) - fireEvent.click(button); - expect(button?.getAttribute("href")).toBe( "https://app.contentstack.com/#!/stack/bltapikey/visual-builder?branch=main&environment=bltenvironment&target-url=http%3A%2F%2Flocalhost%3A3000%2F&locale=en-us" ); diff --git a/src/visualBuilder/components/__test__/visualBuilder.test.tsx b/src/visualBuilder/components/__test__/visualBuilder.test.tsx index 3a365209..794a14d5 100644 --- a/src/visualBuilder/components/__test__/visualBuilder.test.tsx +++ b/src/visualBuilder/components/__test__/visualBuilder.test.tsx @@ -1,7 +1,8 @@ -import { render, fireEvent } from "@testing-library/preact"; +import { render, fireEvent, cleanup } from "@testing-library/preact"; import { hideOverlay } from "../../generators/generateOverlay"; import { VisualBuilder } from "../.."; import VisualBuilderComponent from "../VisualBuilder"; +import { asyncRender } from "../../../__test__/utils"; vi.mock("../../generators/generateOverlay", () => ({ hideOverlay: vi.fn(), @@ -14,8 +15,14 @@ const mockResizeObserver = { }; describe("VisualBuilderComponent", () => { - test("renders VisualBuilderComponent correctly", () => { - const { getByTestId } = render( + beforeEach(() => { + document.body.innerHTML = ""; + }) + afterEach(() => { + cleanup(); + }) + test("renders VisualBuilderComponent correctly", async () => { + const { getByTestId } = await asyncRender( { ).toBeInTheDocument(); }); - test("hides overlay and unobserves element on click", () => { + test("hides overlay and unobserves element on click", async () => { const visualBuilderContainer = document.createElement("div"); - const { getByTestId } = render( + const { getByTestId } = await asyncRender( { }); }); - test("hides overlay without throwing error if VisualBuilderGlobalState is null", () => { + test("hides overlay without throwing error if VisualBuilderGlobalState is null", async () => { const visualBuilderContainer = document.createElement("div"); VisualBuilder.VisualBuilderGlobalState.value.previousSelectedEditableDOM = null; VisualBuilder.VisualBuilderGlobalState.value.previousHoveredTargetDOM = null; - const { getByTestId } = render( + const { getByTestId } = await asyncRender( { expect(() => {}).not.toThrow(); }); - test("unobserves element if VisualBuilderGlobalState is null", () => { + test("unobserves element if VisualBuilderGlobalState is null", async () => { const visualBuilderContainer = document.createElement("div"); const targetElement = document.createElement("div"); VisualBuilder.VisualBuilderGlobalState.value.previousSelectedEditableDOM = targetElement; - const { getByTestId } = render( + const { getByTestId } = await asyncRender( { }; }); - test("should not do anything if tooltip is already present", () => { + test("should not do anything if tooltip is already present", async () => { focusedToolbar.classList.add("visual-builder__tooltip--persistent"); - - appendFieldPathDropdown(mockEventDetails, focusedToolbar); + await act(() => { + appendFieldPathDropdown(mockEventDetails, focusedToolbar); + }) const fieldLabelWrapper = focusedToolbar.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper" @@ -141,8 +142,9 @@ describe("appendFieldPathDropdown", () => { }); test("should close the field label dropdown if open", async () => { - appendFieldPathDropdown(mockEventDetails, focusedToolbar); - await sleep(0); + await act(() => { + appendFieldPathDropdown(mockEventDetails, focusedToolbar); + }) const fieldLabelWrapper = await findByTestId( focusedToolbar, @@ -156,8 +158,10 @@ describe("appendFieldPathDropdown", () => { }); }); - test("should open the field label dropdown if closed", () => { - appendFieldPathDropdown(mockEventDetails, focusedToolbar); + test("should open the field label dropdown if closed", async () => { + await act(() => { + appendFieldPathDropdown(mockEventDetails, focusedToolbar); + }) const fieldLabelWrapper = focusedToolbar.querySelector( ".visual-builder__focused-toolbar__field-label-wrapper" diff --git a/src/visualBuilder/listeners/index.ts b/src/visualBuilder/listeners/index.ts index 8d80808a..46fc5b8b 100644 --- a/src/visualBuilder/listeners/index.ts +++ b/src/visualBuilder/listeners/index.ts @@ -16,47 +16,8 @@ type RemoveEventListenersParams = Omit< EventListenerHandlerParams, "event" | "eventDetails" >; - -export function addEventListeners(params: AddEventListenersParams): void { - // capture any click event during the capture phase - window.addEventListener( - "click", - (event) => { - handleBuilderInteraction({ - event: event, - overlayWrapper: params.overlayWrapper, - visualBuilderContainer: params.visualBuilderContainer, - previousSelectedEditableDOM: - VisualBuilder.VisualBuilderGlobalState.value - .previousSelectedEditableDOM, - focusedToolbar: params.focusedToolbar, - resizeObserver: params.resizeObserver, - }); - }, - { capture: true } - ); - - window.addEventListener("mousemove", (event) => { - handleMouseHover({ - event: event as MouseEvent, - overlayWrapper: params.overlayWrapper, - visualBuilderContainer: params.visualBuilderContainer, - customCursor: params.customCursor, - }); - }); - - document.documentElement.addEventListener("mouseleave", () => { - hideCustomCursor(params.customCursor); - hideHoverOutline(params.visualBuilderContainer); - }); - - document.documentElement.addEventListener("mouseenter", () => { - showCustomCursor(params.customCursor); - }); -} - -export function removeEventListeners(params: RemoveEventListenersParams): void { - window.removeEventListener("click", (event) => { +const eventHandlers = { + click: (params: AddEventListenersParams) => (event: MouseEvent) => { handleBuilderInteraction({ event: event, overlayWrapper: params.overlayWrapper, @@ -67,14 +28,59 @@ export function removeEventListeners(params: RemoveEventListenersParams): void { focusedToolbar: params.focusedToolbar, resizeObserver: params.resizeObserver, }); - }); - - window.removeEventListener("mousemove", (event) => { + }, + mousemove: (params: AddEventListenersParams) => (event: MouseEvent) => { handleMouseHover({ - event: event as MouseEvent, + event: event, overlayWrapper: params.overlayWrapper, visualBuilderContainer: params.visualBuilderContainer, customCursor: params.customCursor, }); - }); + }, + mouseleave: (params: AddEventListenersParams) => () => { + hideCustomCursor(params.customCursor); + hideHoverOutline(params.visualBuilderContainer); + }, + mouseenter: (params: AddEventListenersParams) => () => { + showCustomCursor(params.customCursor); + }, +}; +const eventListenersMap = new Map(); +export function addEventListeners(params: AddEventListenersParams): void { + const clickHandler = eventHandlers.click(params); + const mousemoveHandler = eventHandlers.mousemove(params); + const mouseleaveHandler = eventHandlers.mouseleave(params); + const mouseenterHandler = eventHandlers.mouseenter(params); + + eventListenersMap.set("click", clickHandler as EventListener); + eventListenersMap.set("mousemove", mousemoveHandler as EventListener); + eventListenersMap.set("mouseleave", mouseleaveHandler); + eventListenersMap.set("mouseenter", mouseenterHandler); + + window.addEventListener("click", clickHandler, { capture: true }); + window.addEventListener("mousemove", mousemoveHandler); + document.documentElement.addEventListener("mouseleave", mouseleaveHandler); + document.documentElement.addEventListener("mouseenter", mouseenterHandler); +} + +export function removeEventListeners(params: RemoveEventListenersParams): void { + const clickHandler = eventListenersMap.get("click"); + const mousemoveHandler = eventListenersMap.get("mousemove"); + const mouseleaveHandler = eventListenersMap.get("mouseleave"); + const mouseenterHandler = eventListenersMap.get("mouseenter"); + + if (clickHandler) { + window.removeEventListener("click", clickHandler, { capture: true }); + } + if (mousemoveHandler) { + window.removeEventListener("mousemove", mousemoveHandler); + } + if (mouseleaveHandler) { + document.documentElement.removeEventListener("mouseleave", mouseleaveHandler); + } + if (mouseenterHandler) { + document.documentElement.removeEventListener("mouseenter", mouseenterHandler); + } + + eventListenersMap.clear(); } diff --git a/vitest.setup.ts b/vitest.setup.ts index 1b8f559e..7d9450f0 100644 --- a/vitest.setup.ts +++ b/vitest.setup.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeAll, vi } from "vitest"; +import { afterAll, afterEach, beforeAll, vi } from "vitest"; import { cleanup } from "@testing-library/preact"; import "@testing-library/jest-dom/vitest"; beforeAll(() => { @@ -14,7 +14,69 @@ beforeAll(() => { })); }) -afterEach(() => { +afterAll(() => { cleanup(); vi.clearAllMocks(); }); + +// const sideEffects = { +// document: { +// addEventListener: { +// fn: document.addEventListener, +// refs: [], +// }, +// keys: Object.keys(document), +// }, +// window: { +// addEventListener: { +// fn: window.addEventListener, +// refs: [], +// }, +// keys: Object.keys(window), +// }, +// }; + +// // Lifecycle Hooks +// // ----------------------------------------------------------------------------- +// beforeAll(async () => { +// // Spy addEventListener +// ['document', 'window'].forEach(obj => { +// const fn = sideEffects[obj].addEventListener.fn; +// const refs = sideEffects[obj].addEventListener.refs; + +// function addEventListenerSpy(type, listener, options) { +// // Store listener reference so it can be removed during reset +// refs.push({ type, listener, options }); +// // Call original window.addEventListener +// fn(type, listener, options); +// } + +// // Add to default key array to prevent removal during reset +// sideEffects[obj].keys.push('addEventListener'); + +// // Replace addEventListener with mock +// global[obj].addEventListener = addEventListenerSpy; +// }); +// }); + +// // Reset JSDOM. This attempts to remove side effects from tests, however it does +// // not reset all changes made to globals like the window and document +// // objects. Tests requiring a full JSDOM reset should be stored in separate +// // files, which is only way to do a complete JSDOM reset with Jest. +// afterAll(async () => { +// const rootElm = document.documentElement; + +// // Remove global listeners and keys +// ['document', 'window'].forEach(obj => { +// const refs = sideEffects[obj].addEventListener.refs; + +// // Listeners +// while (refs.length) { +// const { type, listener, options } = refs.pop(); +// global[obj].removeEventListener(type, listener, options); +// } +// }); + +// // Restore base elements +// rootElm.innerHTML = ''; +// });