refactor: move excalidraw-app outside src (#6987)

* refactor: move excalidraw-app outside src

* move some tests to excal app and fix some

* fix tests

* fix

* port remaining tests

* fix

* update snap

* move tests inside test folder

* fix

* fix
This commit is contained in:
Aakansha Doshi 2023-09-21 09:28:48 +05:30 committed by GitHub
parent 0a588a880b
commit 741d5f1a18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
63 changed files with 638 additions and 415 deletions

View File

@ -1,14 +1,14 @@
import { useEffect, useState } from "react";
import { debounce, getVersion, nFormatter } from "../utils";
import { debounce, getVersion, nFormatter } from "../src/utils";
import {
getElementsStorageSize,
getTotalStorageSize,
} from "./data/localStorage";
import { DEFAULT_VERSION } from "../constants";
import { t } from "../i18n";
import { copyTextToSystemClipboard } from "../clipboard";
import { NonDeletedExcalidrawElement } from "../element/types";
import { UIAppState } from "../types";
import { DEFAULT_VERSION } from "../src/constants";
import { t } from "../src/i18n";
import { copyTextToSystemClipboard } from "../src/clipboard";
import { NonDeletedExcalidrawElement } from "../src/element/types";
import { UIAppState } from "../src/types";
type StorageSizes = { scene: number; total: number };

View File

@ -1,23 +1,23 @@
import throttle from "lodash.throttle";
import { PureComponent } from "react";
import { ExcalidrawImperativeAPI } from "../../types";
import { ErrorDialog } from "../../components/ErrorDialog";
import { APP_NAME, ENV, EVENT } from "../../constants";
import { ImportedDataState } from "../../data/types";
import { ExcalidrawImperativeAPI } from "../../src/types";
import { ErrorDialog } from "../../src/components/ErrorDialog";
import { APP_NAME, ENV, EVENT } from "../../src/constants";
import { ImportedDataState } from "../../src/data/types";
import {
ExcalidrawElement,
InitializedExcalidrawImageElement,
} from "../../element/types";
} from "../../src/element/types";
import {
getSceneVersion,
restoreElements,
} from "../../packages/excalidraw/index";
import { Collaborator, Gesture } from "../../types";
} from "../../src/packages/excalidraw/index";
import { Collaborator, Gesture } from "../../src/types";
import {
preventUnload,
resolvablePromise,
withBatchedUpdates,
} from "../../utils";
} from "../../src/utils";
import {
CURSOR_SYNC_TIMEOUT,
FILE_UPLOAD_MAX_BYTES,
@ -48,25 +48,25 @@ import {
} from "../data/localStorage";
import Portal from "./Portal";
import RoomDialog from "./RoomDialog";
import { t } from "../../i18n";
import { UserIdleState } from "../../types";
import { IDLE_THRESHOLD, ACTIVE_THRESHOLD } from "../../constants";
import { t } from "../../src/i18n";
import { UserIdleState } from "../../src/types";
import { IDLE_THRESHOLD, ACTIVE_THRESHOLD } from "../../src/constants";
import {
encodeFilesForUpload,
FileManager,
updateStaleImageStatuses,
} from "../data/FileManager";
import { AbortError } from "../../errors";
import { AbortError } from "../../src/errors";
import {
isImageElement,
isInitializedImageElement,
} from "../../element/typeChecks";
import { newElementWith } from "../../element/mutateElement";
} from "../../src/element/typeChecks";
import { newElementWith } from "../../src/element/mutateElement";
import {
ReconciledElements,
reconcileElements as _reconcileElements,
} from "./reconciliation";
import { decryptData } from "../../data/encryption";
import { decryptData } from "../../src/data/encryption";
import { resetBrowserStateVersions } from "../data/tabSync";
import { LocalData } from "../data/LocalData";
import { atom, useAtom } from "jotai";

View File

@ -6,19 +6,19 @@ import {
import { TCollabClass } from "./Collab";
import { ExcalidrawElement } from "../../element/types";
import { ExcalidrawElement } from "../../src/element/types";
import {
WS_EVENTS,
FILE_UPLOAD_TIMEOUT,
WS_SCENE_EVENT_TYPES,
} from "../app_constants";
import { UserIdleState } from "../../types";
import { trackEvent } from "../../analytics";
import { UserIdleState } from "../../src/types";
import { trackEvent } from "../../src/analytics";
import throttle from "lodash.throttle";
import { newElementWith } from "../../element/mutateElement";
import { newElementWith } from "../../src/element/mutateElement";
import { BroadcastedExcalidrawElement } from "./reconciliation";
import { encryptData } from "../../data/encryption";
import { PRECEDING_ELEMENT_KEY } from "../../constants";
import { encryptData } from "../../src/data/encryption";
import { PRECEDING_ELEMENT_KEY } from "../../src/constants";
class Portal {
collab: TCollabClass;

View File

@ -1,4 +1,4 @@
@import "../../css/variables.module";
@import "../../src/css/variables.module";
.excalidraw {
.RoomDialog {

View File

@ -1,13 +1,13 @@
import { useRef, useState } from "react";
import * as Popover from "@radix-ui/react-popover";
import { copyTextToSystemClipboard } from "../../clipboard";
import { trackEvent } from "../../analytics";
import { getFrame } from "../../utils";
import { useI18n } from "../../i18n";
import { KEYS } from "../../keys";
import { copyTextToSystemClipboard } from "../../src/clipboard";
import { trackEvent } from "../../src/analytics";
import { getFrame } from "../../src/utils";
import { useI18n } from "../../src/i18n";
import { KEYS } from "../../src/keys";
import { Dialog } from "../../components/Dialog";
import { Dialog } from "../../src/components/Dialog";
import {
copyIcon,
playerPlayIcon,
@ -16,11 +16,11 @@ import {
shareIOS,
shareWindows,
tablerCheckIcon,
} from "../../components/icons";
import { TextField } from "../../components/TextField";
import { FilledButton } from "../../components/FilledButton";
} from "../../src/components/icons";
import { TextField } from "../../src/components/TextField";
import { FilledButton } from "../../src/components/FilledButton";
import { ReactComponent as CollabImage } from "../../assets/lock.svg";
import { ReactComponent as CollabImage } from "../../src/assets/lock.svg";
import "./RoomDialog.scss";
const getShareIcon = () => {

View File

@ -1,7 +1,7 @@
import { PRECEDING_ELEMENT_KEY } from "../../constants";
import { ExcalidrawElement } from "../../element/types";
import { AppState } from "../../types";
import { arrayToMapWithIndex } from "../../utils";
import { PRECEDING_ELEMENT_KEY } from "../../src/constants";
import { ExcalidrawElement } from "../../src/element/types";
import { AppState } from "../../src/types";
import { arrayToMapWithIndex } from "../../src/utils";
export type ReconciledElements = readonly ExcalidrawElement[] & {
_brand: "reconciledElements";

View File

@ -1,5 +1,5 @@
import React from "react";
import { Footer } from "../../packages/excalidraw/index";
import { Footer } from "../../src/packages/excalidraw/index";
import { EncryptedIcon } from "./EncryptedIcon";
import { ExcalidrawPlusAppLink } from "./ExcalidrawPlusAppLink";
import { isExcalidrawPlusSignedUser } from "../app_constants";

View File

@ -1,6 +1,6 @@
import React from "react";
import { PlusPromoIcon } from "../../components/icons";
import { MainMenu } from "../../packages/excalidraw/index";
import { PlusPromoIcon } from "../../src/components/icons";
import { MainMenu } from "../../src/packages/excalidraw/index";
import { LanguageList } from "./LanguageList";
export const AppMainMenu: React.FC<{

View File

@ -1,9 +1,9 @@
import React from "react";
import { PlusPromoIcon } from "../../components/icons";
import { useI18n } from "../../i18n";
import { WelcomeScreen } from "../../packages/excalidraw/index";
import { PlusPromoIcon } from "../../src/components/icons";
import { useI18n } from "../../src/i18n";
import { WelcomeScreen } from "../../src/packages/excalidraw/index";
import { isExcalidrawPlusSignedUser } from "../app_constants";
import { POINTER_EVENTS } from "../../constants";
import { POINTER_EVENTS } from "../../src/constants";
export const AppWelcomeScreen: React.FC<{
setCollabDialogShown: (toggle: boolean) => any;

View File

@ -1,6 +1,6 @@
import { shield } from "../../components/icons";
import { Tooltip } from "../../components/Tooltip";
import { useI18n } from "../../i18n";
import { shield } from "../../src/components/icons";
import { Tooltip } from "../../src/components/Tooltip";
import { useI18n } from "../../src/i18n";
export const EncryptedIcon = () => {
const { t } = useI18n();

View File

@ -1,20 +1,20 @@
import React from "react";
import { Card } from "../../components/Card";
import { ToolButton } from "../../components/ToolButton";
import { serializeAsJSON } from "../../data/json";
import { Card } from "../../src/components/Card";
import { ToolButton } from "../../src/components/ToolButton";
import { serializeAsJSON } from "../../src/data/json";
import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase";
import { FileId, NonDeletedExcalidrawElement } from "../../element/types";
import { AppState, BinaryFileData, BinaryFiles } from "../../types";
import { FileId, NonDeletedExcalidrawElement } from "../../src/element/types";
import { AppState, BinaryFileData, BinaryFiles } from "../../src/types";
import { nanoid } from "nanoid";
import { useI18n } from "../../i18n";
import { encryptData, generateEncryptionKey } from "../../data/encryption";
import { isInitializedImageElement } from "../../element/typeChecks";
import { useI18n } from "../../src/i18n";
import { encryptData, generateEncryptionKey } from "../../src/data/encryption";
import { isInitializedImageElement } from "../../src/element/typeChecks";
import { FILE_UPLOAD_MAX_BYTES } from "../app_constants";
import { encodeFilesForUpload } from "../data/FileManager";
import { MIME_TYPES } from "../../constants";
import { trackEvent } from "../../analytics";
import { getFrame } from "../../utils";
import { ExcalidrawLogo } from "../../components/ExcalidrawLogo";
import { MIME_TYPES } from "../../src/constants";
import { trackEvent } from "../../src/analytics";
import { getFrame } from "../../src/utils";
import { ExcalidrawLogo } from "../../src/components/ExcalidrawLogo";
export const exportToExcalidrawPlus = async (
elements: readonly NonDeletedExcalidrawElement[],

View File

@ -1,7 +1,7 @@
import oc from "open-color";
import React from "react";
import { THEME } from "../../constants";
import { Theme } from "../../element/types";
import { THEME } from "../../src/constants";
import { Theme } from "../../src/element/types";
// https://github.com/tholman/github-corners
export const GitHubCorner = React.memo(

View File

@ -1,8 +1,8 @@
import { useSetAtom } from "jotai";
import React from "react";
import { appLangCodeAtom } from "..";
import { useI18n } from "../../i18n";
import { languages } from "../../i18n";
import { useI18n } from "../../src/i18n";
import { languages } from "../../src/i18n";
export const LanguageList = ({ style }: { style?: React.CSSProperties }) => {
const { t, langCode } = useI18n();

View File

@ -1,19 +1,19 @@
import { compressData } from "../../data/encode";
import { newElementWith } from "../../element/mutateElement";
import { isInitializedImageElement } from "../../element/typeChecks";
import { compressData } from "../../src/data/encode";
import { newElementWith } from "../../src/element/mutateElement";
import { isInitializedImageElement } from "../../src/element/typeChecks";
import {
ExcalidrawElement,
ExcalidrawImageElement,
FileId,
InitializedExcalidrawImageElement,
} from "../../element/types";
import { t } from "../../i18n";
} from "../../src/element/types";
import { t } from "../../src/i18n";
import {
BinaryFileData,
BinaryFileMetadata,
ExcalidrawImperativeAPI,
BinaryFiles,
} from "../../types";
} from "../../src/types";
export class FileManager {
/** files being fetched */

View File

@ -11,11 +11,11 @@
*/
import { createStore, entries, del, getMany, set, setMany } from "idb-keyval";
import { clearAppStateForLocalStorage } from "../../appState";
import { clearElementsForLocalStorage } from "../../element";
import { ExcalidrawElement, FileId } from "../../element/types";
import { AppState, BinaryFileData, BinaryFiles } from "../../types";
import { debounce } from "../../utils";
import { clearAppStateForLocalStorage } from "../../src/appState";
import { clearElementsForLocalStorage } from "../../src/element";
import { ExcalidrawElement, FileId } from "../../src/element/types";
import { AppState, BinaryFileData, BinaryFiles } from "../../src/types";
import { debounce } from "../../src/utils";
import { SAVE_TO_LOCAL_STORAGE_TIMEOUT, STORAGE_KEYS } from "../app_constants";
import { FileManager } from "./FileManager";
import { Locker } from "./Locker";

View File

@ -1,20 +1,20 @@
import { ExcalidrawElement, FileId } from "../../element/types";
import { getSceneVersion } from "../../element";
import { ExcalidrawElement, FileId } from "../../src/element/types";
import { getSceneVersion } from "../../src/element";
import Portal from "../collab/Portal";
import { restoreElements } from "../../data/restore";
import { restoreElements } from "../../src/data/restore";
import {
AppState,
BinaryFileData,
BinaryFileMetadata,
DataURL,
} from "../../types";
} from "../../src/types";
import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants";
import { decompressData } from "../../data/encode";
import { encryptData, decryptData } from "../../data/encryption";
import { MIME_TYPES } from "../../constants";
import { decompressData } from "../../src/data/encode";
import { encryptData, decryptData } from "../../src/data/encryption";
import { MIME_TYPES } from "../../src/constants";
import { reconcileElements } from "../collab/reconciliation";
import { getSyncableElements, SyncableExcalidrawElement } from ".";
import { ResolutionType } from "../../utility-types";
import { ResolutionType } from "../../src/utility-types";
// private
// -----------------------------------------------------------------------------

View File

@ -1,23 +1,23 @@
import { compressData, decompressData } from "../../data/encode";
import { compressData, decompressData } from "../../src/data/encode";
import {
decryptData,
generateEncryptionKey,
IV_LENGTH_BYTES,
} from "../../data/encryption";
import { serializeAsJSON } from "../../data/json";
import { restore } from "../../data/restore";
import { ImportedDataState } from "../../data/types";
import { isInvisiblySmallElement } from "../../element/sizeHelpers";
import { isInitializedImageElement } from "../../element/typeChecks";
import { ExcalidrawElement, FileId } from "../../element/types";
import { t } from "../../i18n";
} from "../../src/data/encryption";
import { serializeAsJSON } from "../../src/data/json";
import { restore } from "../../src/data/restore";
import { ImportedDataState } from "../../src/data/types";
import { isInvisiblySmallElement } from "../../src/element/sizeHelpers";
import { isInitializedImageElement } from "../../src/element/typeChecks";
import { ExcalidrawElement, FileId } from "../../src/element/types";
import { t } from "../../src/i18n";
import {
AppState,
BinaryFileData,
BinaryFiles,
UserIdleState,
} from "../../types";
import { bytesToHexString } from "../../utils";
} from "../../src/types";
import { bytesToHexString } from "../../src/utils";
import {
DELETED_ELEMENT_TIMEOUT,
FILE_UPLOAD_MAX_BYTES,

View File

@ -1,12 +1,12 @@
import { ExcalidrawElement } from "../../element/types";
import { AppState } from "../../types";
import { ExcalidrawElement } from "../../src/element/types";
import { AppState } from "../../src/types";
import {
clearAppStateForLocalStorage,
getDefaultAppState,
} from "../../appState";
import { clearElementsForLocalStorage } from "../../element";
} from "../../src/appState";
import { clearElementsForLocalStorage } from "../../src/element";
import { STORAGE_KEYS } from "../app_constants";
import { ImportedDataState } from "../../data/types";
import { ImportedDataState } from "../../src/data/types";
export const saveUsernameToLocalStorage = (username: string) => {
try {

View File

@ -1,31 +1,31 @@
import polyfill from "../polyfill";
import polyfill from "../src/polyfill";
import LanguageDetector from "i18next-browser-languagedetector";
import { useEffect, useRef, useState } from "react";
import { trackEvent } from "../analytics";
import { getDefaultAppState } from "../appState";
import { ErrorDialog } from "../components/ErrorDialog";
import { TopErrorBoundary } from "../components/TopErrorBoundary";
import { trackEvent } from "../src/analytics";
import { getDefaultAppState } from "../src/appState";
import { ErrorDialog } from "../src/components/ErrorDialog";
import { TopErrorBoundary } from "../src/components/TopErrorBoundary";
import {
APP_NAME,
EVENT,
THEME,
TITLE_TIMEOUT,
VERSION_TIMEOUT,
} from "../constants";
import { loadFromBlob } from "../data/blob";
} from "../src/constants";
import { loadFromBlob } from "../src/data/blob";
import {
ExcalidrawElement,
FileId,
NonDeletedExcalidrawElement,
Theme,
} from "../element/types";
import { useCallbackRefState } from "../hooks/useCallbackRefState";
import { t } from "../i18n";
} from "../src/element/types";
import { useCallbackRefState } from "../src/hooks/useCallbackRefState";
import { t } from "../src/i18n";
import {
Excalidraw,
defaultLang,
LiveCollaborationTrigger,
} from "../packages/excalidraw/index";
} from "../src/packages/excalidraw/index";
import {
AppState,
LibraryItems,
@ -33,7 +33,7 @@ import {
BinaryFiles,
ExcalidrawInitialDataState,
UIAppState,
} from "../types";
} from "../src/types";
import {
debounce,
getVersion,
@ -43,7 +43,7 @@ import {
ResolvablePromise,
resolvablePromise,
isRunningInIframe,
} from "../utils";
} from "../src/utils";
import {
FIREBASE_STORAGE_PREFIXES,
STORAGE_KEYS,
@ -68,33 +68,40 @@ import {
importUsernameFromLocalStorage,
} from "./data/localStorage";
import CustomStats from "./CustomStats";
import { restore, restoreAppState, RestoredDataState } from "../data/restore";
import {
restore,
restoreAppState,
RestoredDataState,
} from "../src/data/restore";
import {
ExportToExcalidrawPlus,
exportToExcalidrawPlus,
} from "./components/ExportToExcalidrawPlus";
import { updateStaleImageStatuses } from "./data/FileManager";
import { newElementWith } from "../element/mutateElement";
import { isInitializedImageElement } from "../element/typeChecks";
import { newElementWith } from "../src/element/mutateElement";
import { isInitializedImageElement } from "../src/element/typeChecks";
import { loadFilesFromFirebase } from "./data/firebase";
import { LocalData } from "./data/LocalData";
import { isBrowserStorageStateNewer } from "./data/tabSync";
import clsx from "clsx";
import { reconcileElements } from "./collab/reconciliation";
import { parseLibraryTokensFromUrl, useHandleLibrary } from "../data/library";
import {
parseLibraryTokensFromUrl,
useHandleLibrary,
} from "../src/data/library";
import { AppMainMenu } from "./components/AppMainMenu";
import { AppWelcomeScreen } from "./components/AppWelcomeScreen";
import { AppFooter } from "./components/AppFooter";
import { atom, Provider, useAtom, useAtomValue } from "jotai";
import { useAtomWithInitialValue } from "../jotai";
import { useAtomWithInitialValue } from "../src/jotai";
import { appJotaiStore } from "./app-jotai";
import "./index.scss";
import { ResolutionType } from "../utility-types";
import { ShareableLinkDialog } from "../components/ShareableLinkDialog";
import { openConfirmModal } from "../components/OverwriteConfirm/OverwriteConfirmState";
import { OverwriteConfirmDialog } from "../components/OverwriteConfirm/OverwriteConfirm";
import Trans from "../components/Trans";
import { ResolutionType } from "../src/utility-types";
import { ShareableLinkDialog } from "../src/components/ShareableLinkDialog";
import { openConfirmModal } from "../src/components/OverwriteConfirm/OverwriteConfirmState";
import { OverwriteConfirmDialog } from "../src/components/OverwriteConfirm/OverwriteConfirm";
import Trans from "../src/components/Trans";
polyfill();

View File

@ -0,0 +1,29 @@
import { defaultLang } from "../../src/i18n";
import { UI } from "../../src/tests/helpers/ui";
import { screen, fireEvent, waitFor, render } from "../../src/tests/test-utils";
import ExcalidrawApp from "../../excalidraw-app";
describe("Test LanguageList", () => {
it("rerenders UI on language change", async () => {
await render(<ExcalidrawApp />);
// select rectangle tool to show properties menu
UI.clickTool("rectangle");
// english lang should display `thin` label
expect(screen.queryByTitle(/thin/i)).not.toBeNull();
fireEvent.click(document.querySelector(".dropdown-menu-button")!);
fireEvent.change(document.querySelector(".dropdown-select__language")!, {
target: { value: "de-DE" },
});
// switching to german, `thin` label should no longer exist
await waitFor(() => expect(screen.queryByTitle(/thin/i)).toBeNull());
// reset language
fireEvent.change(document.querySelector(".dropdown-select__language")!, {
target: { value: defaultLang.code },
});
// switching back to English
await waitFor(() => expect(screen.queryByTitle(/thin/i)).not.toBeNull());
});
});

View File

@ -1,11 +1,11 @@
import ExcalidrawApp from "../excalidraw-app";
import ExcalidrawApp from "../../excalidraw-app";
import {
mockBoundingClientRect,
render,
restoreOriginalGetBoundingClientRect,
} from "./test-utils";
} from "../../src/tests/test-utils";
import { UI } from "./helpers/ui";
import { UI } from "../../src/tests/helpers/ui";
describe("Test MobileMenu", () => {
const { h } = window;

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
import { vi } from "vitest";
import { render, updateSceneData, waitFor } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { API } from "./helpers/api";
import { createUndoAction } from "../actions/actionHistory";
import { render, updateSceneData, waitFor } from "../../src/tests/test-utils";
import ExcalidrawApp from "../../excalidraw-app";
import { API } from "../../src/tests/helpers/api";
import { createUndoAction } from "../../src/actions/actionHistory";
const { h } = window;
Object.defineProperty(window, "crypto", {
@ -16,7 +16,7 @@ Object.defineProperty(window, "crypto", {
},
});
vi.mock("../excalidraw-app/data/index.ts", async (importActual) => {
vi.mock("../../excalidraw-app/data/index.ts", async (importActual) => {
const module = (await importActual()) as any;
return {
__esmodule: true,
@ -27,7 +27,7 @@ vi.mock("../excalidraw-app/data/index.ts", async (importActual) => {
};
});
vi.mock("../excalidraw-app/data/firebase.ts", () => {
vi.mock("../../excalidraw-app/data/firebase.ts", () => {
const loadFromFirebase = async () => null;
const saveToFirebase = () => {};
const isSavedToFirebase = () => true;

View File

@ -1,13 +1,13 @@
import { expect } from "chai";
import { PRECEDING_ELEMENT_KEY } from "../constants";
import { ExcalidrawElement } from "../element/types";
import { PRECEDING_ELEMENT_KEY } from "../../src/constants";
import { ExcalidrawElement } from "../../src/element/types";
import {
BroadcastedExcalidrawElement,
ReconciledElements,
reconcileElements,
} from "../excalidraw-app/collab/reconciliation";
import { randomInteger } from "../random";
import { AppState } from "../types";
} from "../../excalidraw-app/collab/reconciliation";
import { randomInteger } from "../../src/random";
import { AppState } from "../../src/types";
type Id = string;
type ElementLike = {

View File

@ -203,7 +203,6 @@ describe("duplicating multiple elements", () => {
);
clonedArrows.forEach((arrow) => {
// console.log(arrow);
expect(
clonedRectangle.boundElements!.find((e) => e.id === arrow.id),
).toEqual(

View File

@ -1,5 +1,5 @@
import ReactDOM from "react-dom";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { GlobalTestState, render, screen } from "../tests/test-utils";
import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
import { CODES, KEYS } from "../keys";
@ -41,7 +41,7 @@ describe("textWysiwyg", () => {
describe("start text editing", () => {
const { h } = window;
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
h.elements = [];
});
@ -243,7 +243,7 @@ describe("textWysiwyg", () => {
});
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
//@ts-ignore
h.app.refreshDeviceState(h.app.excalidrawContainerRef.current!);
@ -477,7 +477,7 @@ describe("textWysiwyg", () => {
const { h } = window;
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
h.elements = [];
rectangle = UI.createElement("rectangle", {
@ -1511,7 +1511,7 @@ describe("textWysiwyg", () => {
});
it("should bump the version of labelled arrow when label updated", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
const arrow = UI.createElement("arrow", {
width: 300,
height: 0,

View File

@ -1,9 +1,9 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import ExcalidrawApp from "./excalidraw-app";
import ExcalidrawApp from "../excalidraw-app";
import { registerSW } from "virtual:pwa-register";
import "./excalidraw-app/sentry";
import "../excalidraw-app/sentry";
window.__EXCALIDRAW_SHA__ = import.meta.env.VITE_APP_GIT_SHA;
const rootElement = document.getElementById("root")!;
const root = createRoot(rootElement);

View File

@ -3,7 +3,7 @@ import * as Renderer from "../renderer/renderScene";
import { reseed } from "../random";
import { render, queryByTestId } from "../tests/test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { vi } from "vitest";
const renderStaticScene = vi.spyOn(Renderer, "renderStaticScene");
@ -35,7 +35,7 @@ describe("Test <App/>", () => {
};
};
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
expect(
queryByTestId(
document.querySelector(".excalidraw-modal-container")!,

View File

@ -0,0 +1,50 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Test <App/> > should show error modal when using brave and measureText API is not working 1`] = `
<div
data-testid="brave-measure-text-error"
>
<p>
Looks like you are using Brave browser with the
<span
style="font-weight: 600;"
>
Aggressively Block Fingerprinting
</span>
setting enabled.
</p>
<p>
This could result in breaking the
<span
style="font-weight: 600;"
>
Text Elements
</span>
in your drawings.
</p>
<p>
We strongly recommend disabling this setting. You can follow
<a
href="http://docs.excalidraw.com/docs/@excalidraw/excalidraw/faq#turning-off-aggresive-block-fingerprinting-in-brave-browser"
>
these steps
</a>
on how to do so.
</p>
<p>
If disabling this setting doesn't fix the display of text elements, please open an
<a
href="https://github.com/excalidraw/excalidraw/issues/new"
>
issue
</a>
on our GitHub, or write us on
<a
href="https://discord.gg/UexuTaE"
>
Discord
.
</a>
</p>
</div>
`;

View File

@ -13089,126 +13089,6 @@ exports[`regression tests > pinch-to-zoom works > [end of test] number of elemen
exports[`regression tests > pinch-to-zoom works > [end of test] number of renders 1`] = `7`;
exports[`regression tests > rerenders UI on language change > [end of test] appState 1`] = `
{
"activeEmbeddable": null,
"activeTool": {
"customType": null,
"lastActiveTool": null,
"locked": false,
"type": "rectangle",
},
"collaborators": Map {},
"contextMenu": null,
"currentChartType": "bar",
"currentItemBackgroundColor": "transparent",
"currentItemEndArrowhead": "arrow",
"currentItemFillStyle": "hachure",
"currentItemFontFamily": 1,
"currentItemFontSize": 20,
"currentItemOpacity": 100,
"currentItemRoughness": 1,
"currentItemRoundness": "round",
"currentItemStartArrowhead": null,
"currentItemStrokeColor": "#1e1e1e",
"currentItemStrokeStyle": "solid",
"currentItemStrokeWidth": 1,
"currentItemTextAlign": "left",
"cursorButton": "up",
"defaultSidebarDockedPreference": false,
"draggingElement": null,
"editingElement": null,
"editingFrame": null,
"editingGroupId": null,
"editingLinearElement": null,
"elementsToHighlight": null,
"errorMessage": null,
"exportBackground": true,
"exportEmbedScene": false,
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 768,
"isBindingEnabled": true,
"isLoading": false,
"isResizing": false,
"isRotating": false,
"lastPointerDownWith": "mouse",
"multiElement": null,
"name": "Untitled-201933152653",
"offsetLeft": 0,
"offsetTop": 0,
"openDialog": null,
"openMenu": "canvas",
"openPopup": null,
"openSidebar": null,
"pasteDialog": {
"data": null,
"shown": false,
},
"penDetected": false,
"penMode": false,
"pendingImageElementId": null,
"previousSelectedElementIds": {},
"resizingElement": null,
"scrollX": 0,
"scrollY": 0,
"scrolledOutside": false,
"selectedElementIds": {},
"selectedElementsAreBeingDragged": false,
"selectedGroupIds": {},
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
"startBoundElement": null,
"suggestedBindings": [],
"theme": "light",
"toast": null,
"viewBackgroundColor": "#ffffff",
"viewModeEnabled": false,
"width": 1024,
"zenModeEnabled": false,
"zoom": {
"value": 1,
},
}
`;
exports[`regression tests > rerenders UI on language change > [end of test] history 1`] = `
{
"recording": false,
"redoStack": [],
"stateHistory": [
{
"appState": {
"editingGroupId": null,
"editingLinearElement": null,
"name": "Untitled-201933152653",
"selectedElementIds": {},
"selectedGroupIds": {},
"viewBackgroundColor": "#ffffff",
},
"elements": [],
},
],
}
`;
exports[`regression tests > rerenders UI on language change > [end of test] number of elements 1`] = `0`;
exports[`regression tests > rerenders UI on language change > [end of test] number of renders 1`] = `5`;
exports[`regression tests > shift click on selected element should deselect it on pointer up > [end of test] appState 1`] = `
{
"activeEmbeddable": null,

View File

@ -1,4 +1,4 @@
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { CODES } from "../keys";
import { API } from "../tests/helpers/api";
import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
@ -9,7 +9,7 @@ import {
screen,
togglePopover,
} from "../tests/test-utils";
import { copiedStyles } from "./actionStyles";
import { copiedStyles } from "../actions/actionStyles";
const { h } = window;
@ -17,7 +17,7 @@ const mouse = new Pointer("mouse");
describe("actionStyles", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
});
afterEach(async () => {

View File

@ -1,6 +1,6 @@
import ReactDOM from "react-dom";
import { render } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../../src/packages/excalidraw/index";
import { defaultLang, setLanguage } from "../i18n";
import { UI, Pointer, Keyboard } from "./helpers/ui";
import { API } from "./helpers/api";
@ -60,7 +60,7 @@ describe("aligning", () => {
mouse.reset();
await setLanguage(defaultLang);
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
});
it("aligns two objects correctly to the top", () => {

View File

@ -1,6 +1,6 @@
import { queryByTestId, render, waitFor } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { API } from "./helpers/api";
import { getDefaultAppState } from "../appState";
import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants";
@ -14,14 +14,17 @@ describe("appState", () => {
const defaultAppState = getDefaultAppState();
const exportBackground = !defaultAppState.exportBackground;
await render(<ExcalidrawApp />, {
localStorageData: {
appState: {
exportBackground,
viewBackgroundColor: "#F00",
},
},
});
await render(
<Excalidraw
initialData={{
appState: {
exportBackground,
viewBackgroundColor: "#F00",
},
}}
/>,
{},
);
await waitFor(() => {
expect(h.state.exportBackground).toBe(exportBackground);
@ -53,13 +56,15 @@ describe("appState", () => {
});
it("changing fontSize with text tool selected (no element created yet)", async () => {
const { container } = await render(<ExcalidrawApp />, {
localStorageData: {
appState: {
currentItemFontSize: 30,
},
},
});
const { container } = await render(
<Excalidraw
initialData={{
appState: {
currentItemFontSize: 30,
},
}}
/>,
);
UI.clickTool("text");

View File

@ -1,5 +1,5 @@
import { fireEvent, render } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../../src/packages/excalidraw/index";
import { UI, Pointer, Keyboard } from "./helpers/ui";
import { getTransformHandles } from "../element/transformHandles";
import { API } from "./helpers/api";
@ -12,7 +12,7 @@ const mouse = new Pointer("mouse");
describe("element binding", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
});
it("should create valid binding if duplicate start/end points", async () => {

View File

@ -7,7 +7,7 @@ import {
createPasteEvent,
} from "./test-utils";
import { Pointer, Keyboard } from "./helpers/ui";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { KEYS } from "../keys";
import {
getDefaultLineHeight,
@ -79,8 +79,13 @@ beforeEach(async () => {
mouse.reset();
await render(<ExcalidrawApp />);
h.app.setAppState({ zoom: { value: 1 as NormalizedZoomValue } });
await render(
<Excalidraw
autoFocus={true}
handleKeyboardGlobally={true}
initialData={{ appState: { zoom: { value: 1 as NormalizedZoomValue } } }}
/>,
);
setClipboardText("");
Object.assign(document, {
elementFromPoint: () => GlobalTestState.canvas,
@ -91,7 +96,6 @@ describe("general paste behavior", () => {
it("should randomize seed on paste", async () => {
const rectangle = API.createElement({ type: "rectangle" });
const clipboardJSON = (await copyToClipboard([rectangle], null))!;
pasteWithCtrlCmdV(clipboardJSON);
await waitFor(() => {

View File

@ -11,7 +11,7 @@ import {
waitFor,
togglePopover,
} from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import * as Renderer from "../renderer/renderScene";
import { reseed } from "../random";
import { UI, Pointer, Keyboard } from "./helpers/ui";
@ -20,7 +20,6 @@ import { ShortcutName } from "../actions/shortcuts";
import { copiedStyles } from "../actions/actionStyles";
import { API } from "./helpers/api";
import { setDateTimeForTests } from "../utils";
import { LibraryItem } from "../types";
import { vi } from "vitest";
const checkpoint = (name: string) => {
@ -56,7 +55,7 @@ describe("contextMenu element", () => {
reseed(7);
setDateTimeForTests("201933152653");
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
});
beforeAll(() => {
@ -394,11 +393,9 @@ describe("contextMenu element", () => {
const contextMenu = UI.queryContextMenu();
fireEvent.click(queryByText(contextMenu!, "Add to library")!);
await waitFor(() => {
const library = localStorage.getItem("excalidraw-library");
expect(library).not.toBeNull();
const addedElement = JSON.parse(library!)[0] as LibraryItem;
expect(addedElement.elements[0]).toEqual(h.elements[0]);
await waitFor(async () => {
const libraryItems = await h.app.library.getLatestLibrary();
expect(libraryItems[0].elements[0]).toEqual(h.elements[0]);
});
});

View File

@ -1,5 +1,5 @@
import ReactDOM from "react-dom";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import * as Renderer from "../renderer/renderScene";
import { KEYS } from "../keys";
import {
@ -30,7 +30,7 @@ const { h } = window;
describe("Test dragCreate", () => {
describe("add element to the scene when pointer dragging long enough", () => {
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("rectangle");
fireEvent.click(tool);
@ -62,7 +62,7 @@ describe("Test dragCreate", () => {
});
it("ellipse", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("ellipse");
fireEvent.click(tool);
@ -95,7 +95,7 @@ describe("Test dragCreate", () => {
});
it("diamond", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("diamond");
fireEvent.click(tool);
@ -127,7 +127,7 @@ describe("Test dragCreate", () => {
});
it("arrow", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("arrow");
fireEvent.click(tool);
@ -163,7 +163,7 @@ describe("Test dragCreate", () => {
});
it("line", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("line");
fireEvent.click(tool);
@ -207,7 +207,7 @@ describe("Test dragCreate", () => {
});
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("rectangle");
fireEvent.click(tool);
@ -227,7 +227,7 @@ describe("Test dragCreate", () => {
});
it("ellipse", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("ellipse");
fireEvent.click(tool);
@ -247,7 +247,7 @@ describe("Test dragCreate", () => {
});
it("diamond", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("diamond");
fireEvent.click(tool);
@ -267,7 +267,9 @@ describe("Test dragCreate", () => {
});
it("arrow", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(
<Excalidraw handleKeyboardGlobally={true} />,
);
// select tool
const tool = getByToolName("arrow");
fireEvent.click(tool);
@ -292,7 +294,9 @@ describe("Test dragCreate", () => {
});
it("line", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(
<Excalidraw handleKeyboardGlobally={true} />,
);
// select tool
const tool = getByToolName("line");
fireEvent.click(tool);

View File

@ -1,5 +1,5 @@
import ReactDOM from "react-dom";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { render } from "../tests/test-utils";
import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
import { KEYS } from "../keys";
@ -15,7 +15,7 @@ const h = window.h;
describe("element locking", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
h.elements = [];
});

View File

@ -1,5 +1,5 @@
import { render, waitFor } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { API } from "./helpers/api";
import {
encodePngMetadata,
@ -42,7 +42,7 @@ Object.defineProperty(window, "TextDecoder", {
describe("export", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
});
it("export embedded png and reimport", async () => {

View File

@ -1,14 +1,14 @@
import { render } from "./test-utils";
import { API } from "./helpers/api";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { vi } from "vitest";
const { h } = window;
describe("fitToContent", () => {
it("should zoom to fit the selected element", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
h.state.width = 10;
h.state.height = 10;
@ -30,7 +30,7 @@ describe("fitToContent", () => {
});
it("should zoom to fit multiple elements", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
const topLeft = API.createElement({
width: 20,
@ -61,7 +61,7 @@ describe("fitToContent", () => {
});
it("should scroll the viewport to the selected element", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
h.state.width = 10;
h.state.height = 10;
@ -106,7 +106,7 @@ describe("fitToContent animated", () => {
});
it("should ease scroll the viewport to the selected element", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
h.state.width = 10;
h.state.height = 10;
@ -142,7 +142,7 @@ describe("fitToContent animated", () => {
});
it("should animate the scroll but not the zoom", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
h.state.width = 50;
h.state.height = 50;

View File

@ -19,7 +19,7 @@ import {
FileId,
} from "../element/types";
import { newLinearElement } from "../element";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { mutateElement } from "../element/mutateElement";
import { NormalizedZoomValue } from "../types";
import { ROUNDNESS } from "../constants";
@ -52,7 +52,7 @@ beforeEach(async () => {
Object.assign(document, {
elementFromPoint: () => GlobalTestState.canvas,
});
await render(<ExcalidrawApp />);
await render(<Excalidraw autoFocus={true} handleKeyboardGlobally={true} />);
h.setState({
zoom: {
value: 1 as NormalizedZoomValue,

View File

@ -1,5 +1,5 @@
import { assertSelectedElements, render } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { Keyboard, Pointer, UI } from "./helpers/ui";
import { API } from "./helpers/api";
import { getDefaultAppState } from "../appState";
@ -13,14 +13,16 @@ const mouse = new Pointer("mouse");
describe("history", () => {
it("initializing scene should end up with single history entry", async () => {
await render(<ExcalidrawApp />, {
localStorageData: {
elements: [API.createElement({ type: "rectangle", id: "A" })],
appState: {
zenModeEnabled: true,
},
},
});
await render(
<Excalidraw
initialData={{
elements: [API.createElement({ type: "rectangle", id: "A" })],
appState: {
zenModeEnabled: true,
},
}}
/>,
);
await waitFor(() => expect(h.state.zenModeEnabled).toBe(true));
await waitFor(() =>
@ -60,14 +62,16 @@ describe("history", () => {
});
it("scene import via drag&drop should create new history entry", async () => {
await render(<ExcalidrawApp />, {
localStorageData: {
elements: [API.createElement({ type: "rectangle", id: "A" })],
appState: {
viewBackgroundColor: "#FFF",
},
},
});
await render(
<Excalidraw
initialData={{
elements: [API.createElement({ type: "rectangle", id: "A" })],
appState: {
viewBackgroundColor: "#FFF",
},
}}
/>,
);
await waitFor(() => expect(h.state.viewBackgroundColor).toBe("#FFF"));
await waitFor(() =>
@ -113,7 +117,7 @@ describe("history", () => {
});
it("undo/redo works properly with groups", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
const rect1 = API.createElement({ type: "rectangle", groupIds: ["A"] });
const rect2 = API.createElement({ type: "rectangle", groupIds: ["A"] });

View File

@ -2,7 +2,7 @@ import { vi } from "vitest";
import { fireEvent, render, waitFor } from "./test-utils";
import { queryByTestId } from "@testing-library/react";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { API } from "./helpers/api";
import { MIME_TYPES } from "../constants";
import { LibraryItem, LibraryItems } from "../types";
@ -42,7 +42,7 @@ vi.mock("../data/filesystem.ts", async (importOriginal) => {
describe("library", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
h.app.library.resetLibrary();
});
@ -189,7 +189,7 @@ describe("library", () => {
describe("library menu", () => {
it("should load library from file picker", async () => {
const { container } = await render(<ExcalidrawApp />);
const { container } = await render(<Excalidraw />);
const latestLibrary = await h.app.library.getLatestLibrary();
expect(latestLibrary.length).toBe(0);

View File

@ -5,7 +5,7 @@ import {
ExcalidrawTextElementWithContainer,
FontString,
} from "../element/types";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { centerPoint } from "../math";
import { reseed } from "../random";
import * as Renderer from "../renderer/renderScene";
@ -43,7 +43,7 @@ describe("Test Linear Elements", () => {
renderInteractiveScene.mockClear();
renderStaticScene.mockClear();
reseed(7);
const comp = await render(<ExcalidrawApp />);
const comp = await render(<Excalidraw handleKeyboardGlobally={true} />);
h.state.width = 1000;
h.state.height = 1000;
container = comp.container;

View File

@ -1,7 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
import { render, fireEvent } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import * as Renderer from "../renderer/renderScene";
import { reseed } from "../random";
import { bindOrUnbindLinearElement } from "../element/binding";
@ -31,7 +31,7 @@ const { h } = window;
describe("move element", () => {
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
const canvas = container.querySelector("canvas.interactive")!;
{
@ -67,7 +67,7 @@ describe("move element", () => {
});
it("rectangles with binding arrow", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
// create elements
const rectA = UI.createElement("rectangle", { size: 100 });
@ -119,7 +119,7 @@ describe("move element", () => {
describe("duplicate element on move when ALT is clicked", () => {
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
const canvas = container.querySelector("canvas.interactive")!;
{

View File

@ -5,7 +5,7 @@ import {
mockBoundingClientRect,
restoreOriginalGetBoundingClientRect,
} from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import * as Renderer from "../renderer/renderScene";
import { KEYS } from "../keys";
import { ExcalidrawLinearElement } from "../element/types";
@ -29,7 +29,7 @@ const { h } = window;
describe("remove shape in non linear elements", () => {
beforeAll(() => {
mockBoundingClientRect();
mockBoundingClientRect({ width: 1000, height: 1000 });
});
afterAll(() => {
@ -37,12 +37,13 @@ describe("remove shape in non linear elements", () => {
});
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("rectangle");
fireEvent.click(tool);
const canvas = container.querySelector("canvas.interactive")!;
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerUp(canvas, { clientX: 30, clientY: 30 });
@ -52,7 +53,7 @@ describe("remove shape in non linear elements", () => {
});
it("ellipse", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("ellipse");
fireEvent.click(tool);
@ -67,7 +68,7 @@ describe("remove shape in non linear elements", () => {
});
it("diamond", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("diamond");
fireEvent.click(tool);
@ -84,7 +85,7 @@ describe("remove shape in non linear elements", () => {
describe("multi point mode in linear elements", () => {
it("arrow", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("arrow");
fireEvent.click(tool);
@ -109,8 +110,8 @@ describe("multi point mode in linear elements", () => {
key: KEYS.ENTER,
});
expect(renderInteractiveScene).toHaveBeenCalledTimes(10);
expect(renderStaticScene).toHaveBeenCalledTimes(11);
expect(renderInteractiveScene).toHaveBeenCalledTimes(9);
expect(renderStaticScene).toHaveBeenCalledTimes(10);
expect(h.elements.length).toEqual(1);
const element = h.elements[0] as ExcalidrawLinearElement;
@ -128,7 +129,7 @@ describe("multi point mode in linear elements", () => {
});
it("line", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("line");
fireEvent.click(tool);
@ -153,8 +154,8 @@ describe("multi point mode in linear elements", () => {
key: KEYS.ENTER,
});
expect(renderInteractiveScene).toHaveBeenCalledTimes(10);
expect(renderStaticScene).toHaveBeenCalledTimes(11);
expect(renderInteractiveScene).toHaveBeenCalledTimes(9);
expect(renderStaticScene).toHaveBeenCalledTimes(10);
expect(h.elements.length).toEqual(1);
const element = h.elements[0] as ExcalidrawLinearElement;

View File

@ -1,7 +1,7 @@
import ReactDOM from "react-dom";
import { ExcalidrawElement } from "../element/types";
import { CODES, KEYS } from "../keys";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { reseed } from "../random";
import * as Renderer from "../renderer/renderScene";
import { setDateTimeForTests } from "../utils";
@ -13,9 +13,7 @@ import {
render,
screen,
togglePopover,
waitFor,
} from "./test-utils";
import { defaultLang } from "../i18n";
import { FONT_FAMILY } from "../constants";
import { vi } from "vitest";
@ -56,7 +54,7 @@ beforeEach(async () => {
finger1.reset();
finger2.reset();
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
h.setState({ height: 768, width: 1024 });
});
@ -443,26 +441,6 @@ describe("regression tests", () => {
expect(h.state.zoom.value).toBe(1);
});
it("rerenders UI on language change", async () => {
// select rectangle tool to show properties menu
UI.clickTool("rectangle");
// english lang should display `thin` label
expect(screen.queryByTitle(/thin/i)).not.toBeNull();
fireEvent.click(document.querySelector(".dropdown-menu-button")!);
fireEvent.change(document.querySelector(".dropdown-select__language")!, {
target: { value: "de-DE" },
});
// switching to german, `thin` label should no longer exist
await waitFor(() => expect(screen.queryByTitle(/thin/i)).toBeNull());
// reset language
fireEvent.change(document.querySelector(".dropdown-select__language")!, {
target: { value: defaultLang.code },
});
// switching back to English
await waitFor(() => expect(screen.queryByTitle(/thin/i)).not.toBeNull());
});
it("make a group and duplicate it", () => {
UI.clickTool("rectangle");
mouse.down(10, 10);

View File

@ -6,7 +6,7 @@ import { reseed } from "../random";
import { UI, Keyboard } from "./helpers/ui";
import { resize } from "./utils";
import { ExcalidrawTextElement } from "../element/types";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { API } from "./helpers/api";
import { KEYS } from "../keys";
import { vi } from "vitest";
@ -126,7 +126,7 @@ describe("resize rectangle ellipses and diamond elements", () => {
describe("Test text element", () => {
it("should update font size via keyboard", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw handleKeyboardGlobally={true} />);
const textElement = API.createElement({
type: "text",

View File

@ -8,7 +8,6 @@ import { Excalidraw } from "../packages/excalidraw/index";
import { API } from "./helpers/api";
import { Keyboard } from "./helpers/ui";
import { KEYS } from "../keys";
import ExcalidrawApp from "../excalidraw-app";
const { h } = window;
@ -56,7 +55,7 @@ describe("appState", () => {
it("moving by page up/down/left/right", async () => {
mockBoundingClientRect();
await render(<ExcalidrawApp />, {});
await render(<Excalidraw handleKeyboardGlobally={true} />, {});
const scrollTest = () => {
const initialScrollY = h.state.scrollY;

View File

@ -6,7 +6,7 @@ import {
restoreOriginalGetBoundingClientRect,
assertSelectedElements,
} from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import * as Renderer from "../renderer/renderScene";
import { KEYS } from "../keys";
import { reseed } from "../random";
@ -34,7 +34,7 @@ const mouse = new Pointer("mouse");
describe("box-selection", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
});
it("should allow adding to selection via box-select when holding shift", async () => {
@ -102,7 +102,7 @@ describe("box-selection", () => {
describe("inner box-selection", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
});
it("selecting elements visually nested inside another", async () => {
const rect1 = API.createElement({
@ -218,7 +218,7 @@ describe("inner box-selection", () => {
describe("selection element", () => {
it("create selection element on pointer down", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("selection");
fireEvent.click(tool);
@ -239,7 +239,7 @@ describe("selection element", () => {
});
it("resize selection element on pointer move", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("selection");
fireEvent.click(tool);
@ -261,7 +261,7 @@ describe("selection element", () => {
});
it("remove selection element on pointer up", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(<Excalidraw />);
// select tool
const tool = getByToolName("selection");
fireEvent.click(tool);
@ -287,7 +287,9 @@ describe("select single element on the scene", () => {
});
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(
<Excalidraw handleKeyboardGlobally={true} />,
);
const canvas = container.querySelector("canvas.interactive")!;
{
// create element
@ -317,7 +319,9 @@ describe("select single element on the scene", () => {
});
it("diamond", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(
<Excalidraw handleKeyboardGlobally={true} />,
);
const canvas = container.querySelector("canvas.interactive")!;
{
// create element
@ -347,7 +351,9 @@ describe("select single element on the scene", () => {
});
it("ellipse", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(
<Excalidraw handleKeyboardGlobally={true} />,
);
const canvas = container.querySelector("canvas.interactive")!;
{
// create element
@ -377,7 +383,9 @@ describe("select single element on the scene", () => {
});
it("arrow", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(
<Excalidraw handleKeyboardGlobally={true} />,
);
const canvas = container.querySelector("canvas.interactive")!;
{
// create element
@ -419,7 +427,9 @@ describe("select single element on the scene", () => {
});
it("arrow escape", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const { getByToolName, container } = await render(
<Excalidraw handleKeyboardGlobally={true} />,
);
const canvas = container.querySelector("canvas.interactive")!;
{
// create element
@ -464,7 +474,7 @@ describe("select single element on the scene", () => {
describe("tool locking & selection", () => {
it("should not select newly created element while tool is locked", async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
UI.clickTool("lock");
expect(h.state.activeTool.locked).toBe(true);
@ -480,7 +490,7 @@ describe("tool locking & selection", () => {
describe("selectedElementIds stability", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
});
it("box-selection should be stable when not changing selection", () => {

View File

@ -11,7 +11,7 @@ import {
import * as toolQueries from "./queries/toolQueries";
import { ImportedDataState } from "../data/types";
import { STORAGE_KEYS } from "../excalidraw-app/app_constants";
import { STORAGE_KEYS } from "../../excalidraw-app/app_constants";
import { SceneData } from "../types";
import { getSelectedElements } from "../scene/selection";

View File

@ -1,5 +1,5 @@
import { render, GlobalTestState } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { KEYS } from "../keys";
import { Keyboard, Pointer, UI } from "./helpers/ui";
import { CURSOR_TYPE } from "../constants";
@ -12,7 +12,7 @@ const pointerTypes = [mouse, touch, pen];
describe("view mode", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
});
it("after switching to view mode cursor type should be pointer", async () => {

View File

@ -1,6 +1,6 @@
import ReactDOM from "react-dom";
import { render } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { Excalidraw } from "../packages/excalidraw/index";
import { reseed } from "../random";
import {
actionSendBackward,
@ -121,7 +121,6 @@ const assertZindex = ({
operations: [Actions, string[]][];
}) => {
const selectedElementIds = populateElements(elements, appState);
operations.forEach(([action, expected]) => {
h.app.actionManager.executeAction(action);
expect(h.elements.map((element) => element.id)).toEqual(expected);
@ -131,7 +130,7 @@ const assertZindex = ({
describe("z-index manipulation", () => {
beforeEach(async () => {
await render(<ExcalidrawApp />);
await render(<Excalidraw />);
});
it("send back", () => {

View File

@ -96,9 +96,9 @@ const getTargetIndexAccountingForBinding = (
if (direction === "left") {
return elements.indexOf(nextElement);
}
const boundTextElement =
Scene.getScene(nextElement)!.getElement(boundElementId);
if (boundTextElement) {
return elements.indexOf(boundTextElement);
}

View File

@ -16,6 +16,6 @@
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"include": ["src", "excalidraw-app"],
"exclude": ["src/packages/excalidraw/types"]
}