Skip to content
Closed
4 changes: 2 additions & 2 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ jobs:
- name: "Install Node"
uses: actions/setup-node@v4
with:
node-version: "21.x"
node-version: "22.x"
- name: "Install Deps"
run: npm install
- name: "Test"
run: npx vitest --coverage.enabled true
run: npx vitest run --coverage.enabled true --reporter=verbose
- name: "Report Coverage"
# Set if: always() to also generate the report if tests are failing
# Only works if you set `reportOnFailure: true` in your vite config as specified above
Expand Down
1,494 changes: 825 additions & 669 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
"@types/react": "^18.2.57",
"@types/react-dom": "^18.2.19",
"@types/uuid": "^8.3.1",
"@vitest/coverage-v8": "^2.1.2",
"@vitest/ui": "^2.1.2",
"@vitest/coverage-v8": "^4.0.8",
"@vitest/ui": "^4.0.8",
"auto-changelog": "^2.5.0",
"esbuild-plugin-file-path-extensions": "^2.1.0",
"eslint": "^8.57.1",
Expand All @@ -77,7 +77,7 @@
"typedoc": "^0.25.13",
"typescript": "^5.4.5",
"typescript-eslint": "^8.5.0",
"vitest": "^2.1.0"
"vitest": "^4.0.8"
},
"repository": {
"type": "git",
Expand Down
49 changes: 31 additions & 18 deletions src/__test__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,55 +43,68 @@ export const waitForHoverOutline = async () => {
);
expect(hoverOutline).not.toBeNull();
});
}
export const waitForBuilderSDKToBeInitialized = async (visualBuilderPostMessage: EventManager | undefined) => {
};
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 = {}) => {
export const triggerAndWaitForClickAction = async (
visualBuilderPostMessage: EventManager | undefined,
element: HTMLElement,
{ skipWaitForFieldType }: WaitForClickActionOptions = {}
) => {
await waitForBuilderSDKToBeInitialized(visualBuilderPostMessage);
await act(async () => {
await fireEvent.click(element);
})
if(!skipWaitForFieldType) {
});
if (!skipWaitForFieldType) {
await waitFor(() => {
expect(element).toHaveAttribute("data-cslp-field-type")
})
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 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<typeof render> = async (...args) => {
let returnValue: ReturnType<typeof render>;
};
export const asyncRender: (
componentChild: ComponentChild
) => Promise<ReturnType<typeof render>> = async (...args) => {
let returnValue!: ReturnType<typeof render>;
await act(async () => {
returnValue = render(...args);
});
return returnValue;
}
};
100 changes: 74 additions & 26 deletions src/livePreview/__test__/live-preview.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
import { act, fireEvent, waitFor } from "@testing-library/preact";
import crypto from "crypto";
import { vi } from "vitest";
import { sleep } from "../../__test__/utils";
import { getDefaultConfig } from "../../configManager/config.default";
import Config from "../../configManager/configManager";
import { PublicLogger } from "../../logger/logger";
import { ILivePreviewWindowType } from "../../types/types";
import { addLivePreviewQueryTags } from '../../utils/addLivePreviewQueryTags';
import { addLivePreviewQueryTags } from "../../utils/addLivePreviewQueryTags";
import livePreviewPostMessage from "../eventManager/livePreviewEventManager";
import { LIVE_PREVIEW_POST_MESSAGE_EVENTS } from "../eventManager/livePreviewEventManager.constant";
import {
Expand Down Expand Up @@ -43,7 +42,6 @@ vi.mock("../../visualBuilder/utils/visualBuilderPostMessage", async () => {
};
});


Object.defineProperty(globalThis, "crypto", {
value: {
getRandomValues: (arr: Array<any>) => crypto.randomBytes(arr.length),
Expand Down Expand Up @@ -349,13 +347,27 @@ describe("incoming postMessage", () => {
});

livePreviewPostMessage?.destroy({ soft: true });

// Track when INIT completes
let initCompleted = false;
livePreviewPostMessage?.on(
LIVE_PREVIEW_POST_MESSAGE_EVENTS.INIT,
mockLivePreviewInitEventListener
() => {
const result = mockLivePreviewInitEventListener();
initCompleted = true;
return result;
}
);

const livePreview = new LivePreview();
await sleep();

// Wait for INIT event to complete and event listeners to be registered
await waitFor(
() => {
expect(initCompleted).toBe(true);
},
{ timeout: 3000 }
);

// set user onChange function
const userOnChange = vi.fn();
Expand Down Expand Up @@ -386,7 +398,13 @@ describe("incoming postMessage", () => {
}

new LivePreview();
await sleep();

// Wait for async init event to be processed
await waitFor(() => {
expect(Config.get().stackDetails.contentTypeUid).toBe(
"contentTypeUid"
);
});

expect(Config.get().stackDetails).toMatchObject({
apiKey: "",
Expand All @@ -397,42 +415,69 @@ describe("incoming postMessage", () => {
});

test("should navigate forward, backward and reload page on history call", async () => {
// Track when INIT completes
let initCompleted = false;
livePreviewPostMessage?.destroy({ soft: true });
livePreviewPostMessage?.on(
LIVE_PREVIEW_POST_MESSAGE_EVENTS.INIT,
() => {
const result = mockLivePreviewInitEventListener();
initCompleted = true;
return result;
}
);

new LivePreview();
await sleep();

// Wait for INIT to complete and event listeners to be registered
await waitFor(
() => {
expect(initCompleted).toBe(true);
},
{ timeout: 3000 }
);

vi.spyOn(window.history, "forward");
vi.spyOn(window.history, "back");
vi.spyOn(window.history, "go").mockImplementation(() => {});

// for forward
livePreviewPostMessage?.send(LIVE_PREVIEW_POST_MESSAGE_EVENTS.HISTORY, {
type: "forward",
} as HistoryLivePreviewPostMessageEventData);
await sleep(0);
await livePreviewPostMessage?.send(
LIVE_PREVIEW_POST_MESSAGE_EVENTS.HISTORY,
{
type: "forward",
} as HistoryLivePreviewPostMessageEventData
);

expect(window.history.forward).toHaveBeenCalled();

// for back
livePreviewPostMessage?.send(LIVE_PREVIEW_POST_MESSAGE_EVENTS.HISTORY, {
type: "backward",
} as HistoryLivePreviewPostMessageEventData);
await livePreviewPostMessage?.send(
LIVE_PREVIEW_POST_MESSAGE_EVENTS.HISTORY,
{
type: "backward",
} as HistoryLivePreviewPostMessageEventData
);

await sleep(0);
expect(window.history.back).toHaveBeenCalled();

// for reload
livePreviewPostMessage?.send(LIVE_PREVIEW_POST_MESSAGE_EVENTS.HISTORY, {
type: "reload",
} as HistoryLivePreviewPostMessageEventData);
await livePreviewPostMessage?.send(
LIVE_PREVIEW_POST_MESSAGE_EVENTS.HISTORY,
{
type: "reload",
} as HistoryLivePreviewPostMessageEventData
);

await sleep(0);
expect(window.history.go).toHaveBeenCalled();
});
});

describe("testing window event listeners", () => {
let addEventListenerMock: any;
const sendInitEvent = vi.fn().mockImplementation(mockLivePreviewInitEventListener);
const sendInitEvent = vi
.fn()
.mockImplementation(mockLivePreviewInitEventListener);
let livePreviewInstance: LivePreview;

beforeEach(() => {
Expand Down Expand Up @@ -473,7 +518,9 @@ describe("testing window event listeners", () => {
});

test("should attach a load event to call requestDataSync if document is not yet loaded", () => {
const readyState = vi.spyOn(document, 'readyState', 'get').mockReturnValue('loading');
const readyState = vi
.spyOn(document, "readyState", "get")
.mockReturnValue("loading");

Config.replace({
enable: true,
Expand All @@ -488,7 +535,6 @@ describe("testing window event listeners", () => {
readyState.mockRestore();
});
test("should handle link click event if ssr is set to true", async () => {

Config.replace({
enable: true,
ssr: true,
Expand All @@ -500,14 +546,16 @@ describe("testing window event listeners", () => {

document.body.appendChild(targetElement);
await act(async () => {
livePreviewInstance = new LivePreview();
livePreviewInstance = new LivePreview();
});
await waitFor(() => {
expect(sendInitEvent).toBeCalled();
})
});
await waitFor(() => {
expect(Config.get().stackDetails.contentTypeUid).toBe('contentTypeUid');
})
expect(Config.get().stackDetails.contentTypeUid).toBe(
"contentTypeUid"
);
});
await act(async () => {
fireEvent.click(targetElement);
});
Expand Down
Loading
Loading