diff --git a/apps/examples/e2e/tests/export-snapshots.spec.ts b/apps/examples/e2e/tests/export-snapshots.spec.ts
index e883f60ff..237cead9f 100644
--- a/apps/examples/e2e/tests/export-snapshots.spec.ts
+++ b/apps/examples/e2e/tests/export-snapshots.spec.ts
@@ -1,14 +1,14 @@
-import test from '@playwright/test'
-import { TLShapeId, TLShapePartial } from 'tldraw'
+import { Page, expect } from '@playwright/test'
+import assert from 'assert'
+import { rename, writeFile } from 'fs/promises'
+import { Editor, TLShapeId, TLShapePartial } from 'tldraw'
+import { setup } from '../shared-e2e'
+import test, { ApiFixture } from './fixtures/fixtures'
-// import test, { Page, expect } from '@playwright/test'
-// import assert from 'assert'
-// import { rename, writeFile } from 'fs/promises'
-// import { setupPage } from '../shared-e2e'
-// import { Editor, TLShapeId, TLShapePartial } from 'tldraw'
-
-// declare const editor: Editor
+declare const editor: Editor
+// hi steve. please don't comment these out. they stop us getting bugs. u can just ask if they're
+// holding u up <3
test.describe('Export snapshots', () => {
const snapshots = {
'Exports geo text with leading line breaks': [
@@ -189,50 +189,50 @@ test.describe('Export snapshots', () => {
]
}
- // const snapshotsToTest = Object.entries(snapshots)
- // const filteredSnapshots = snapshotsToTest // maybe we filter these down, there are a lot of them
+ const snapshotsToTest = Object.entries(snapshots)
+ const filteredSnapshots = snapshotsToTest // maybe we filter these down, there are a lot of them
- // for (const [name, shapes] of filteredSnapshots) {
- // test(`Exports with ${name} in dark mode`, async ({ browser }) => {
- // const page = await browser.newPage()
- // await setupPage(page)
- // await page.evaluate((shapes) => {
- // editor.user.updateUserPreferences({ isDarkMode: true })
- // editor
- // .updateInstanceState({ exportBackground: false })
- // .selectAll()
- // .deleteShapes(editor.getSelectedShapeIds())
- // .createShapes(shapes)
- // }, shapes as any)
+ test.beforeEach(setup)
- // await snapshotTest(page)
- // })
- // }
+ for (const [name, shapes] of filteredSnapshots) {
+ test(`Exports with ${name} in dark mode`, async ({ page, api }) => {
+ await page.evaluate((shapes) => {
+ editor.user.updateUserPreferences({ isDarkMode: true })
+ editor
+ .updateInstanceState({ exportBackground: false })
+ .selectAll()
+ .deleteShapes(editor.getSelectedShapeIds())
+ .createShapes(shapes)
+ }, shapes as any)
- // async function snapshotTest(page: Page) {
- // const downloadAndSnapshot = page.waitForEvent('download').then(async (download) => {
- // const path = (await download.path()) as string
- // assert(path)
- // await rename(path, path + '.svg')
- // await writeFile(
- // path + '.html',
- // `
- //
- //
- //
- //
- // `,
- // 'utf-8'
- // )
+ await snapshotTest(page, api)
+ })
+ }
- // await page.goto(`file://${path}.html`)
- // const clip = await page.$eval('img', (img) => img.getBoundingClientRect())
- // await expect(page).toHaveScreenshot({
- // omitBackground: true,
- // clip,
- // })
- // })
- // await page.evaluate(() => (window as any)['tldraw-export']())
- // await downloadAndSnapshot
- // }
+ async function snapshotTest(page: Page, api: ApiFixture) {
+ const downloadAndSnapshot = page.waitForEvent('download').then(async (download) => {
+ const path = (await download.path()) as string
+ assert(path)
+ await rename(path, path + '.svg')
+ await writeFile(
+ path + '.html',
+ `
+
+
+
+
+ `,
+ 'utf-8'
+ )
+
+ await page.goto(`file://${path}.html`)
+ const clip = await page.$eval('img', (img) => img.getBoundingClientRect())
+ await expect(page).toHaveScreenshot({
+ omitBackground: true,
+ clip,
+ })
+ })
+ await api.exportAsSvg()
+ await downloadAndSnapshot
+ }
})
diff --git a/apps/examples/e2e/tests/fixtures/fixtures.ts b/apps/examples/e2e/tests/fixtures/fixtures.ts
index 9df95f90d..35c226338 100644
--- a/apps/examples/e2e/tests/fixtures/fixtures.ts
+++ b/apps/examples/e2e/tests/fixtures/fixtures.ts
@@ -1,4 +1,5 @@
-import { test as base } from '@playwright/test'
+import { Page, test as base } from '@playwright/test'
+import { EndToEndApi } from '../../../src/misc/EndToEndApi'
import { ActionsMenu } from './menus/ActionsMenu'
import { HelpMenu } from './menus/HelpMenu'
import { MainMenu } from './menus/MainMenu'
@@ -15,6 +16,30 @@ type Fixtures = {
mainMenu: MainMenu
pageMenu: PageMenu
navigationPanel: NavigationPanel
+ api: ReturnType
+}
+
+export type ApiFixture = {
+ [K in keyof EndToEndApi]: (
+ ...args: Parameters
+ ) => Promise>
+}
+
+function makeApiFixture(keys: { [K in keyof EndToEndApi]: true }, page: Page): ApiFixture {
+ const result = {} as any
+
+ for (const key of Object.keys(keys)) {
+ result[key] = (...args: any[]) => {
+ return page.evaluate(
+ ([key, ...args]) => {
+ return (window as any).tldrawApi[key](...args)
+ },
+ [key, ...args]
+ )
+ }
+ }
+
+ return result
}
const test = base.extend({
@@ -46,6 +71,16 @@ const test = base.extend({
const navigationPanel = new NavigationPanel(page)
await use(navigationPanel)
},
+ api: async ({ page }, use) => {
+ const api = makeApiFixture(
+ {
+ exportAsSvg: true,
+ exportAsFormat: true,
+ },
+ page
+ )
+ await use(api)
+ },
})
export default test
diff --git a/apps/examples/e2e/tests/test-api.spec.ts b/apps/examples/e2e/tests/test-api.spec.ts
new file mode 100644
index 000000000..8a6a0b6a7
--- /dev/null
+++ b/apps/examples/e2e/tests/test-api.spec.ts
@@ -0,0 +1,14 @@
+import { setupWithShapes } from '../shared-e2e'
+import test from './fixtures/fixtures'
+
+test.beforeEach(setupWithShapes)
+
+test.describe('api', () => {
+ for (const format of ['svg', 'png', 'jpeg', 'webp', 'json'] as const) {
+ test(`export as ${format}`, async ({ page, api }) => {
+ const downloadEvent = page.waitForEvent('download')
+ await api.exportAsFormat(format)
+ await downloadEvent
+ })
+ }
+})
diff --git a/apps/examples/src/misc/EndToEndApi.tsx b/apps/examples/src/misc/EndToEndApi.tsx
new file mode 100644
index 000000000..42f2eabab
--- /dev/null
+++ b/apps/examples/src/misc/EndToEndApi.tsx
@@ -0,0 +1,6 @@
+import { TLExportType } from 'tldraw/src/lib/utils/export/exportAs'
+
+export interface EndToEndApi {
+ exportAsSvg: () => void
+ exportAsFormat: (format: TLExportType) => void
+}
diff --git a/apps/examples/src/misc/end-to-end.tsx b/apps/examples/src/misc/end-to-end.tsx
index e92fa4bfe..06ad6c556 100644
--- a/apps/examples/src/misc/end-to-end.tsx
+++ b/apps/examples/src/misc/end-to-end.tsx
@@ -1,6 +1,7 @@
import { useEffect } from 'react'
-import { Tldraw, useActions } from 'tldraw'
+import { Tldraw, exportAs, useActions, useEditor } from 'tldraw'
import 'tldraw/tldraw.css'
+import { EndToEndApi } from './EndToEndApi'
;(window as any).__tldraw_ui_event = { id: 'NOTHING_YET' }
;(window as any).__tldraw_editor_events = []
@@ -27,11 +28,17 @@ export default function EndToEnd() {
}
function SneakyExportButton() {
+ const editor = useEditor()
const actions = useActions()
useEffect(() => {
- ;(window as any)['tldraw-export'] = () => actions['export-as-svg'].onSelect('unknown')
- }, [actions])
+ const api: EndToEndApi = {
+ exportAsSvg: () => actions['export-as-svg'].onSelect('unknown'),
+ exportAsFormat: (format) =>
+ exportAs(editor, editor.selectAll().getSelectedShapeIds(), format, 'test'),
+ }
+ ;(window as any).tldrawApi = api
+ }, [actions, editor])
return null
}
diff --git a/packages/tldraw/src/lib/Tldraw.test.tsx b/packages/tldraw/src/lib/Tldraw.test.tsx
index 367b37de2..2fe99f7dc 100644
--- a/packages/tldraw/src/lib/Tldraw.test.tsx
+++ b/packages/tldraw/src/lib/Tldraw.test.tsx
@@ -10,7 +10,7 @@ describe('', () => {
,
- { waitForPatterns: false }
+ { waitForPatterns: true }
)
await screen.findByTestId('canvas-1')
@@ -27,7 +27,7 @@ describe('', () => {
)
}
- await renderTldrawComponent(, { waitForPatterns: false })
+ await renderTldrawComponent(, { waitForPatterns: true })
await screen.findByTestId('canvas-1')
})
diff --git a/packages/tldraw/src/lib/utils/export/export.ts b/packages/tldraw/src/lib/utils/export/export.ts
index 263f478d0..26cf8cf14 100644
--- a/packages/tldraw/src/lib/utils/export/export.ts
+++ b/packages/tldraw/src/lib/utils/export/export.ts
@@ -86,10 +86,14 @@ export async function getSvgAsImage(
if (!blob) return null
- const view = new DataView(await blob.arrayBuffer())
- return PngHelpers.setPhysChunk(view, effectiveScale, {
- type: 'image/' + type,
- })
+ if (type === 'png') {
+ const view = new DataView(await blob.arrayBuffer())
+ return PngHelpers.setPhysChunk(view, effectiveScale, {
+ type: 'image/' + type,
+ })
+ } else {
+ return blob
+ }
}
/** @public */