import { act, render, screen } from '@testing-library/react' import { TLBaseShape, createShapeId } from '@tldraw/tlschema' import { TldrawEditor } from '../TldrawEditor' import { Canvas } from '../components/Canvas' import { HTMLContainer } from '../components/HTMLContainer' import { createTLStore } from '../config/createTLStore' import { Editor } from '../editor/Editor' import { BaseBoxShapeUtil } from '../editor/shapeutils/BaseBoxShapeUtil' import { BaseBoxShapeTool } from '../editor/tools/BaseBoxShapeTool/BaseBoxShapeTool' let originalFetch: typeof window.fetch beforeEach(() => { window.fetch = jest.fn().mockImplementation((...args: Parameters) => { if (args[0] === '/icons/icon/icon-names.json') { return Promise.resolve({ json: () => Promise.resolve([]) } as Response) } return originalFetch(...args) }) }) afterEach(() => { jest.restoreAllMocks() window.fetch = originalFetch }) describe('', () => { it('Renders without crashing', async () => { await act(async () => (
)) }) it('Creates its own store', async () => { let store: any render( await act(async () => ( (store = editor.store)} autoFocus>
)) ) await screen.findByTestId('canvas-1') expect(store).toBeTruthy() }) it('Renders with an external store', async () => { const store = createTLStore() render( await act(async () => ( { expect(editor.store).toBe(store) }} autoFocus >
)) ) await screen.findByTestId('canvas-1') }) it('Accepts fresh versions of store and calls `onMount` for each one', async () => { const initialStore = createTLStore({}) const onMount = jest.fn() const rendered = render(
) await screen.findByTestId('canvas-1') const initialEditor = onMount.mock.lastCall[0] jest.spyOn(initialEditor, 'dispose') expect(initialEditor.store).toBe(initialStore) // re-render with the same store: rendered.rerender(
) await screen.findByTestId('canvas-2') // not called again: expect(onMount).toHaveBeenCalledTimes(1) // re-render with a new store: const newStore = createTLStore({}) rendered.rerender(
) await screen.findByTestId('canvas-3') expect(initialEditor.dispose).toHaveBeenCalledTimes(1) expect(onMount).toHaveBeenCalledTimes(2) expect(onMount.mock.lastCall[0].store).toBe(newStore) }) it('Renders the canvas and shapes', async () => { let editor = {} as Editor render( await act(async () => ( { editor = editorApp }} >
)) ) await screen.findByTestId('canvas-1') expect(editor).toBeTruthy() await act(async () => { editor.updateInstanceState({ screenBounds: { x: 0, y: 0, w: 1080, h: 720 } }, true, true) }) const id = createShapeId() await act(async () => { editor.createShapes([ { id, type: 'geo', props: { w: 100, h: 100 }, }, ]) }) // Does the shape exist? expect(editor.getShapeById(id)).toMatchObject({ id, type: 'geo', x: 0, y: 0, opacity: 1, props: { geo: 'rectangle', w: 100, h: 100 }, }) // Is the shape's component rendering? expect(document.querySelectorAll('.tl-shape')).toHaveLength(1) expect(document.querySelectorAll('.tl-shape-indicator')).toHaveLength(0) // Select the shape await act(async () => editor.select(id)) // Is the shape's component rendering? expect(document.querySelectorAll('.tl-shape-indicator')).toHaveLength(1) // Select the eraser tool... await act(async () => editor.setSelectedTool('eraser')) // Is the editor's current tool correct? expect(editor.currentToolId).toBe('eraser') }) }) describe('Custom shapes', () => { type CardShape = TLBaseShape< 'card', { w: number h: number } > class CardUtil extends BaseBoxShapeUtil { static override type = 'card' as const override isAspectRatioLocked = (_shape: CardShape) => false override canResize = (_shape: CardShape) => true override canBind = (_shape: CardShape) => true override defaultProps(): CardShape['props'] { return { w: 300, h: 300, } } render(shape: CardShape) { const bounds = this.bounds(shape) return ( {bounds.w.toFixed()}x{bounds.h.toFixed()} ) } indicator(shape: CardShape) { return } } class CardTool extends BaseBoxShapeTool { static override id = 'card' static override initial = 'idle' override shapeType = 'card' } const tools = [CardTool] const shapes = { card: { util: CardUtil } } it('Uses custom shapes', async () => { let editor = {} as Editor render( await act(async () => ( { editor = editorApp }} >
)) ) await screen.findByTestId('canvas-1') expect(editor).toBeTruthy() await act(async () => { editor.updateInstanceState({ screenBounds: { x: 0, y: 0, w: 1080, h: 720 } }, true, true) }) expect(editor.shapeUtils.card).toBeTruthy() const id = createShapeId() await act(async () => { editor.createShapes([ { id, type: 'card', props: { w: 100, h: 100 }, }, ]) }) // Does the shape exist? expect(editor.getShapeById(id)).toMatchObject({ id, type: 'card', x: 0, y: 0, opacity: 1, props: { w: 100, h: 100 }, }) // Is the shape's component rendering? expect(await screen.findByTestId('card-shape')).toBeTruthy() // Select the shape await act(async () => editor.select(id)) // Is the shape's component rendering? expect(await screen.findByTestId('card-indicator')).toBeTruthy() // Select the tool... await act(async () => editor.setSelectedTool('card')) // Is the editor's current tool correct? expect(editor.currentToolId).toBe('card') }) })