import { act } from '@testing-library/react'
import { Editor, GeoShapeGeoStyle } from '@tldraw/editor'
import { GeoShapeUtil } from '../lib/shapes/geo/GeoShapeUtil'
import { PathBuilder } from '../lib/shapes/shared/PathBuilder'
import { Tldraw } from '../lib/Tldraw'
import { renderTldrawComponentWithEditor } from './testutils/renderTldrawComponent'
let editor: Editor
function pressedToolValues() {
const els = document.querySelectorAll(
'.tlui-main-toolbar__tools [data-value][aria-pressed="true"]'
)
return [...els].map((el) => el.getAttribute('data-value')!)
}
beforeEach(async () => {
;({ editor } = await renderTldrawComponentWithEditor((onMount) => , {
waitForPatterns: false,
}))
})
it('keeps only the originating tool highlighted while the zoom tool masks itself', async () => {
await act(async () => {
editor.setCurrentTool('draw')
})
expect(pressedToolValues()).toEqual(['draw'])
await act(async () => {
editor.setCurrentTool('zoom', { onInteractionEnd: 'draw.idle' })
})
expect(pressedToolValues()).toEqual(['draw'])
})
it('keeps only the originating geo variant highlighted while the zoom tool masks itself', async () => {
await act(async () => {
editor.setStyleForNextShapes(GeoShapeGeoStyle, 'ellipse')
editor.setCurrentTool('geo')
})
expect(pressedToolValues()).toEqual(['ellipse'])
// Tools with no geo variant used to match the zoom tool's empty shared styles and all light up
await act(async () => {
editor.setCurrentTool('zoom', { onInteractionEnd: 'geo.idle' })
})
expect(pressedToolValues()).toEqual(['ellipse'])
})
// The toolbar builds a button per GeoShapeGeoStyle value, and GeoShapeUtil.configure() adds the
// custom types to that style. Reading their label used to dereference a message declared only for
// the built-ins, so a single custom type threw while the toolbar built and took the editor down
// with it — the canvas never mounted. The examples e2e caught it; nothing here did.
it('still mounts with a geo type added through configure()', async () => {
const builtins = [...GeoShapeGeoStyle.values]
const Configured = GeoShapeUtil.configure({
customGeoTypes: {
'rounded-rect': {
getPath: (w: number, h: number) =>
new PathBuilder()
.moveTo(0, 0, { geometry: { isFilled: true } })
.lineTo(w, 0)
.lineTo(w, h)
.lineTo(0, h)
.close(),
snapType: 'polygon' as const,
icon: 'geo-rectangle' as const,
},
},
})
try {
const { editor: configured } = await renderTldrawComponentWithEditor(
(onMount) => ,
{ waitForPatterns: false }
)
try {
expect(configured.getShapeUtil('geo')).toBeTruthy()
expect(document.querySelectorAll('.tl-canvas').length).toBeGreaterThan(0)
} finally {
configured.dispose()
}
} finally {
// configure() mutates GeoShapeGeoStyle.values globally, so clean up or it leaks to other files.
const added = GeoShapeGeoStyle.values.filter((v) => !builtins.includes(v))
if (added.length) GeoShapeGeoStyle.removeValues(...added)
}
})