151 lines
3.8 KiB
TypeScript
151 lines
3.8 KiB
TypeScript
import "pepjs";
|
|
|
|
import {
|
|
render,
|
|
queries,
|
|
RenderResult,
|
|
RenderOptions,
|
|
waitFor,
|
|
} from "@testing-library/react";
|
|
|
|
import * as toolQueries from "./queries/toolQueries";
|
|
import { ImportedDataState } from "../data/types";
|
|
import { STORAGE_KEYS } from "../excalidraw-app/data/localStorage";
|
|
|
|
import { SceneData } from "../types";
|
|
import { getSelectedElements } from "../scene/selection";
|
|
import { ExcalidrawElement } from "../element/types";
|
|
|
|
require("fake-indexeddb/auto");
|
|
|
|
const customQueries = {
|
|
...queries,
|
|
...toolQueries,
|
|
};
|
|
|
|
type TestRenderFn = (
|
|
ui: React.ReactElement,
|
|
options?: Omit<
|
|
RenderOptions & { localStorageData?: ImportedDataState },
|
|
"queries"
|
|
>,
|
|
) => Promise<RenderResult<typeof customQueries>>;
|
|
|
|
const renderApp: TestRenderFn = async (ui, options) => {
|
|
if (options?.localStorageData) {
|
|
initLocalStorage(options.localStorageData);
|
|
delete options.localStorageData;
|
|
}
|
|
|
|
const renderResult = render(ui, {
|
|
queries: customQueries,
|
|
...options,
|
|
});
|
|
|
|
GlobalTestState.renderResult = renderResult;
|
|
|
|
Object.defineProperty(GlobalTestState, "canvas", {
|
|
// must be a getter because at the time of ExcalidrawApp render the
|
|
// child App component isn't likely mounted yet (and thus canvas not
|
|
// present in DOM)
|
|
get() {
|
|
return renderResult.container.querySelector("canvas")!;
|
|
},
|
|
});
|
|
|
|
await waitFor(() => {
|
|
const canvas = renderResult.container.querySelector("canvas");
|
|
if (!canvas) {
|
|
throw new Error("not initialized yet");
|
|
}
|
|
});
|
|
|
|
return renderResult;
|
|
};
|
|
|
|
// re-export everything
|
|
export * from "@testing-library/react";
|
|
|
|
// override render method
|
|
export { renderApp as render };
|
|
|
|
/**
|
|
* For state-sharing across test helpers.
|
|
* NOTE: there shouldn't be concurrency issues as each test is running in its
|
|
* own process and thus gets its own instance of this module when running
|
|
* tests in parallel.
|
|
*/
|
|
export class GlobalTestState {
|
|
/**
|
|
* automatically updated on each call to render()
|
|
*/
|
|
static renderResult: RenderResult<typeof customQueries> = null!;
|
|
/**
|
|
* retrieves canvas for currently rendered app instance
|
|
*/
|
|
static get canvas(): HTMLCanvasElement {
|
|
return null!;
|
|
}
|
|
}
|
|
|
|
const initLocalStorage = (data: ImportedDataState) => {
|
|
if (data.elements) {
|
|
localStorage.setItem(
|
|
STORAGE_KEYS.LOCAL_STORAGE_ELEMENTS,
|
|
JSON.stringify(data.elements),
|
|
);
|
|
}
|
|
if (data.appState) {
|
|
localStorage.setItem(
|
|
STORAGE_KEYS.LOCAL_STORAGE_APP_STATE,
|
|
JSON.stringify(data.appState),
|
|
);
|
|
}
|
|
};
|
|
|
|
export const updateSceneData = (data: SceneData) => {
|
|
(window.collab as any).excalidrawAPI.updateScene(data);
|
|
};
|
|
|
|
const originalGetBoundingClientRect =
|
|
global.window.HTMLDivElement.prototype.getBoundingClientRect;
|
|
|
|
export const mockBoundingClientRect = () => {
|
|
// override getBoundingClientRect as by default it will always return all values as 0 even if customized in html
|
|
global.window.HTMLDivElement.prototype.getBoundingClientRect = () => ({
|
|
top: 10,
|
|
left: 20,
|
|
bottom: 10,
|
|
right: 10,
|
|
width: 200,
|
|
x: 10,
|
|
y: 20,
|
|
height: 100,
|
|
toJSON: () => {},
|
|
});
|
|
};
|
|
|
|
export const restoreOriginalGetBoundingClientRect = () => {
|
|
global.window.HTMLDivElement.prototype.getBoundingClientRect =
|
|
originalGetBoundingClientRect;
|
|
};
|
|
|
|
export const assertSelectedElements = (
|
|
...elements: (
|
|
| (ExcalidrawElement["id"] | ExcalidrawElement)[]
|
|
| ExcalidrawElement["id"]
|
|
| ExcalidrawElement
|
|
)[]
|
|
) => {
|
|
const { h } = window;
|
|
const selectedElementIds = getSelectedElements(
|
|
h.app.getSceneElements(),
|
|
h.state,
|
|
).map((el) => el.id);
|
|
const ids = elements
|
|
.flat()
|
|
.map((item) => (typeof item === "string" ? item : item.id));
|
|
expect(selectedElementIds.length).toBe(ids.length);
|
|
expect(selectedElementIds).toEqual(expect.arrayContaining(ids));
|
|
};
|