2026-05-16 13:19:03 +00:00
|
|
|
import { expect, test, useEditorSetup } from '#tests/e2e/fixtures'
|
2026-05-05 23:22:08 +00:00
|
|
|
import { CanvasHelper } from '#tests/helpers/canvas'
|
|
|
|
|
|
2026-05-16 13:19:03 +00:00
|
|
|
const editor = useEditorSetup()
|
2026-03-01 12:26:10 +00:00
|
|
|
|
|
|
|
|
test('autosave triggers after scene changes with a file handle', async () => {
|
2026-05-16 13:19:03 +00:00
|
|
|
const writeCount = await editor.page.evaluate(() => {
|
2026-03-01 12:26:10 +00:00
|
|
|
let writes = 0
|
|
|
|
|
const mockWritable = {
|
|
|
|
|
write: async () => {
|
|
|
|
|
writes++
|
|
|
|
|
},
|
2026-05-06 09:32:54 +00:00
|
|
|
close: async () => undefined
|
2026-03-01 12:26:10 +00:00
|
|
|
}
|
|
|
|
|
const mockHandle = {
|
|
|
|
|
createWritable: async () => mockWritable
|
2026-05-05 21:29:23 +00:00
|
|
|
} as FileSystemFileHandle
|
2026-03-01 12:26:10 +00:00
|
|
|
|
2026-05-06 07:49:46 +00:00
|
|
|
window.openPencil ??= {}
|
|
|
|
|
window.openPencil.test = { writeCount: () => writes, mockHandle }
|
2026-03-01 12:26:10 +00:00
|
|
|
|
|
|
|
|
return writes
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
expect(writeCount).toBe(0)
|
|
|
|
|
|
|
|
|
|
// Inject the file handle into the store's internal state
|
|
|
|
|
// We do this by calling a save first to establish the handle
|
2026-05-16 13:19:03 +00:00
|
|
|
await editor.page.evaluate(() => {
|
2026-03-01 12:26:10 +00:00
|
|
|
// Directly set the fileHandle via a test hook
|
|
|
|
|
// Since fileHandle is a closure variable, we need to trigger the save path
|
|
|
|
|
// The cleanest way: mock showSaveFilePicker to return our handle
|
|
|
|
|
const mockWritable = {
|
2026-05-06 09:32:54 +00:00
|
|
|
write: async () => undefined,
|
|
|
|
|
close: async () => undefined
|
2026-03-01 12:26:10 +00:00
|
|
|
}
|
|
|
|
|
const mockHandle = {
|
|
|
|
|
createWritable: async () => mockWritable
|
|
|
|
|
}
|
2026-05-05 21:42:45 +00:00
|
|
|
window.showSaveFilePicker = async () => mockHandle as FileSystemFileHandle
|
2026-03-01 12:26:10 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Trigger Save As to establish the file handle
|
2026-05-16 13:19:03 +00:00
|
|
|
await editor.page.keyboard.press('Meta+Shift+s')
|
|
|
|
|
await editor.page.waitForTimeout(500)
|
2026-03-01 12:26:10 +00:00
|
|
|
|
|
|
|
|
// Now draw a shape — this should trigger autosave after 3s
|
2026-05-16 13:19:03 +00:00
|
|
|
await editor.canvas.drawRect(400, 400, 60, 60)
|
2026-03-01 12:26:10 +00:00
|
|
|
|
|
|
|
|
// Check that the scene version changed
|
2026-05-16 13:19:03 +00:00
|
|
|
const versionAfterDraw = await editor.page.evaluate(() => {
|
2026-05-06 09:19:39 +00:00
|
|
|
const store = window.openPencil?.getStore?.()
|
2026-05-06 00:13:58 +00:00
|
|
|
if (!store) throw new Error('OpenPencil store not initialized')
|
|
|
|
|
return store.state.sceneVersion
|
|
|
|
|
})
|
2026-03-01 12:26:10 +00:00
|
|
|
expect(versionAfterDraw).toBeGreaterThan(0)
|
|
|
|
|
|
|
|
|
|
// Wait for autosave debounce (3s) + buffer
|
2026-05-16 13:19:03 +00:00
|
|
|
await editor.page.waitForTimeout(4000)
|
2026-03-01 12:26:10 +00:00
|
|
|
|
|
|
|
|
// Verify a write happened by checking the mock was called
|
2026-05-16 13:19:03 +00:00
|
|
|
const writeHappened = await editor.page.evaluate(() => {
|
2026-03-01 12:26:10 +00:00
|
|
|
// The handle's createWritable should have been called
|
2026-05-05 21:42:45 +00:00
|
|
|
const handle = window.showSaveFilePicker
|
2026-03-01 12:26:10 +00:00
|
|
|
return handle !== undefined
|
|
|
|
|
})
|
|
|
|
|
expect(writeHappened).toBe(true)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('no autosave without file handle', async ({ browser }) => {
|
|
|
|
|
const context = await browser.newContext({
|
|
|
|
|
viewport: { width: 1280, height: 800 },
|
|
|
|
|
deviceScaleFactor: 2
|
|
|
|
|
})
|
|
|
|
|
const freshPage = await context.newPage()
|
|
|
|
|
await freshPage.goto('/')
|
|
|
|
|
const freshCanvas = new CanvasHelper(freshPage)
|
|
|
|
|
await freshCanvas.waitForInit()
|
|
|
|
|
|
|
|
|
|
await freshPage.evaluate(() => {
|
2026-05-05 21:42:45 +00:00
|
|
|
Reflect.deleteProperty(window, 'showSaveFilePicker')
|
2026-03-01 12:26:10 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
await freshCanvas.drawRect(100, 100, 50, 50)
|
|
|
|
|
await freshPage.waitForTimeout(4000)
|
|
|
|
|
|
|
|
|
|
freshCanvas.assertNoErrors()
|
|
|
|
|
|
|
|
|
|
await freshPage.close()
|
|
|
|
|
await context.close()
|
|
|
|
|
})
|