diff --git a/tests/e2e/autosave.spec.ts b/tests/e2e/autosave.spec.ts index 493b097f4..ad5412a0c 100644 --- a/tests/e2e/autosave.spec.ts +++ b/tests/e2e/autosave.spec.ts @@ -63,9 +63,11 @@ test('autosave triggers after scene changes with a file handle', async () => { await canvas.drawRect(400, 400, 60, 60) // Check that the scene version changed - const versionAfterDraw = await page.evaluate( - () => window.__OPEN_PENCIL_STORE__!.state.sceneVersion - ) + const versionAfterDraw = await page.evaluate(() => { + const store = window.__OPEN_PENCIL_STORE__ + if (!store) throw new Error('OpenPencil store not initialized') + return store.state.sceneVersion + }) expect(versionAfterDraw).toBeGreaterThan(0) // Wait for autosave debounce (3s) + buffer diff --git a/tests/e2e/clipboard/copy-paste.spec.ts b/tests/e2e/clipboard/copy-paste.spec.ts index 591cc3f9f..f4f1b5ca3 100644 --- a/tests/e2e/clipboard/copy-paste.spec.ts +++ b/tests/e2e/clipboard/copy-paste.spec.ts @@ -27,7 +27,11 @@ function getPageChildCount() { } function getSelectedCount() { - return page.evaluate(() => window.__OPEN_PENCIL_STORE__!.state.selectedIds.size) + return page.evaluate(() => { + const store = window.__OPEN_PENCIL_STORE__ + if (!store) throw new Error('OpenPencil store not initialized') + return store.state.selectedIds.size + }) } function getSelectedNodes() { @@ -35,7 +39,8 @@ function getSelectedNodes() { const store = window.__OPEN_PENCIL_STORE__ if (!store) throw new Error('OpenPencil store not initialized') return [...store.state.selectedIds].map((id) => { - const n = store.graph.getNode(id)! + const n = store.graph.getNode(id) + if (!n) throw new Error(`Selected node ${id} not found`) return { id: n.id, name: n.name, diff --git a/tests/e2e/layers/panel.spec.ts b/tests/e2e/layers/panel.spec.ts index 0edf93aea..157f2b401 100644 --- a/tests/e2e/layers/panel.spec.ts +++ b/tests/e2e/layers/panel.spec.ts @@ -61,7 +61,9 @@ async function getSceneTree(): Promise { async function getSelectedCount(): Promise { return page.evaluate(() => { - return window.__OPEN_PENCIL_STORE__!.state.selectedIds.size + const store = window.__OPEN_PENCIL_STORE__ + if (!store) throw new Error('OpenPencil store not initialized') + return store.state.selectedIds.size }) } diff --git a/tests/e2e/pages/multi-page.spec.ts b/tests/e2e/pages/multi-page.spec.ts index 6a74606a2..ef2d9a4da 100644 --- a/tests/e2e/pages/multi-page.spec.ts +++ b/tests/e2e/pages/multi-page.spec.ts @@ -27,7 +27,11 @@ function getPages() { } function getCurrentPageId() { - return page.evaluate(() => window.__OPEN_PENCIL_STORE__!.state.currentPageId) + return page.evaluate(() => { + const store = window.__OPEN_PENCIL_STORE__ + if (!store) throw new Error('OpenPencil store not initialized') + return store.state.currentPageId + }) } function getPageChildCount() { @@ -141,7 +145,9 @@ test('rename page via store', async () => { await page.evaluate( ([id, name]) => { - window.__OPEN_PENCIL_STORE__!.renamePage(id, name) + const store = window.__OPEN_PENCIL_STORE__ + if (!store) throw new Error('OpenPencil store not initialized') + store.renamePage(id, name) }, [currentId, 'Renamed Page'] as [string, string] ) @@ -149,7 +155,7 @@ test('rename page via store', async () => { const updated = await getPages() const renamed = updated.find((p) => p.id === currentId) - expect(renamed!.name).toBe('Renamed Page') + expect(renamed?.name).toBe('Renamed Page') canvas.assertNoErrors() }) diff --git a/tests/e2e/properties/corner-stroke-toggles.spec.ts b/tests/e2e/properties/corner-stroke-toggles.spec.ts index 2962f9d53..e6cb1b1b7 100644 --- a/tests/e2e/properties/corner-stroke-toggles.spec.ts +++ b/tests/e2e/properties/corner-stroke-toggles.spec.ts @@ -45,8 +45,8 @@ test('independent corners toggle shows per-corner inputs', async () => { await canvas.waitForRender() const flags = await getSelectedNodeFlags() - expect(flags!.type).toBe('FRAME') - expect(flags!.independentCorners).toBe(false) + expect(flags?.type).toBe('FRAME') + expect(flags?.independentCorners).toBe(false) const toggle = page.locator('[data-test-id="independent-corners-toggle"]') await expect(toggle).toBeVisible() @@ -54,7 +54,7 @@ test('independent corners toggle shows per-corner inputs', async () => { await toggle.click() await canvas.waitForRender() - expect((await getSelectedNodeFlags())!.independentCorners).toBe(true) + expect((await getSelectedNodeFlags())?.independentCorners).toBe(true) const grid = page.locator('[data-test-id="independent-corners-grid"]') await expect(grid).toBeVisible() const cornerInputs = grid.locator('[data-test-id="scrub-input"]') diff --git a/tests/engine/tools/ai-adapter.test.ts b/tests/engine/tools/ai-adapter.test.ts index d81fe7a5e..9020f68ab 100644 --- a/tests/engine/tools/ai-adapter.test.ts +++ b/tests/engine/tools/ai-adapter.test.ts @@ -6,6 +6,8 @@ import * as v from 'valibot' import { ALL_TOOLS, FigmaAPI, SceneGraph, toolsToAI } from '@open-pencil/core' +import { expectDefined } from '#tests/helpers/assert' + type AdapterTool = { execute(args: Record): Promise; description: string } function adapterTool(tools: Record, name: string): AdapterTool { @@ -62,7 +64,7 @@ describe('AI adapter', () => { expect(result.type).toBe('RECTANGLE') expect(result.name).toBe('Test Rect') - const node = figma.getNodeById(result.id)! + const node = expectDefined(figma.getNodeById(result.id), 'created node') expect(node.x).toBe(10) expect(node.y).toBe(20) expect(node.width).toBe(100) @@ -76,7 +78,7 @@ describe('AI adapter', () => { const setFill = adapterTool(tools, 'set_fill') await setFill.execute({ id: rect.id, color: '#00ff00' }) - const fills = figma.getNodeById(rect.id)!.fills + const fills = expectDefined(figma.getNodeById(rect.id), 'filled rectangle').fills expect(fills.length).toBe(1) expect(fills[0].color.g).toBeCloseTo(1) }) @@ -167,7 +169,7 @@ describe('AI adapter', () => { padding: 16 }) - const node = figma.getNodeById(frame.id)! + const node = expectDefined(figma.getNodeById(frame.id), 'layout frame') expect(node.layoutMode).toBe('HORIZONTAL') expect(node.itemSpacing).toBe(8) expect(node.paddingLeft).toBe(16) diff --git a/tests/engine/tools/structure.test.ts b/tests/engine/tools/structure.test.ts index 3eada397f..edcf589a8 100644 --- a/tests/engine/tools/structure.test.ts +++ b/tests/engine/tools/structure.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from 'bun:test' +import { expectDefined } from '#tests/helpers/assert' import { getTool, setupToolTest, type ToolResult } from '#tests/helpers/tools' describe('delete_node', () => { @@ -37,7 +38,7 @@ describe('rename_node', () => { const tool = getTool('rename_node') tool.execute(figma, { id: rect.id, name: 'My Rectangle' }) - expect(figma.getNodeById(rect.id)!.name).toBe('My Rectangle') + expect(expectDefined(figma.getNodeById(rect.id), 'renamed rectangle').name).toBe('My Rectangle') }) }) @@ -52,7 +53,11 @@ describe('reparent_node', () => { const tool = getTool('reparent_node') tool.execute(figma, { id: rect.id, parent_id: frame.id }) - expect(figma.getNodeById(frame.id)!.children.some((c) => c.id === rect.id)).toBe(true) + expect( + expectDefined(figma.getNodeById(frame.id), 'target frame').children.some( + (c) => c.id === rect.id + ) + ).toBe(true) }) }) @@ -68,7 +73,10 @@ describe('group_nodes', () => { const result = tool.execute(figma, { ids: [r1.id, r2.id] }) as ToolResult expect(result.type).toBe('GROUP') - const group = figma.getNodeById(result.id)! + const group = expectDefined( + figma.getNodeById(expectDefined(result.id, 'group id')), + 'created group' + ) expect(group.children.length).toBe(2) }) }) diff --git a/tests/engine/xpath.test.ts b/tests/engine/xpath.test.ts index 663a2ef52..84df5461b 100644 --- a/tests/engine/xpath.test.ts +++ b/tests/engine/xpath.test.ts @@ -2,6 +2,8 @@ import { describe, expect, test } from 'bun:test' import { FigmaAPI, SceneGraph, matchByXPath, nodeToXPath, queryByXPath } from '@open-pencil/core' +import { expectDefined } from '#tests/helpers/assert' + function setup() { const graph = new SceneGraph() const figma = new FigmaAPI(graph) @@ -164,7 +166,7 @@ describe('nodeToXPath', () => { btn.name = 'Button' frame.appendChild(btn) - const xpath = nodeToXPath(graph, btn.id)! + const xpath = expectDefined(nodeToXPath(graph, btn.id), 'button XPath') const results = await queryByXPath(graph, xpath) expect(results.length).toBe(1) expect(results[0].id).toBe(btn.id) @@ -187,7 +189,7 @@ describe('matchByXPath', () => { rect.resize(100, 100) rect.name = 'TestRect' - const sceneNode = graph.getNode(rect.id)! + const sceneNode = expectDefined(graph.getNode(rect.id), 'matching rectangle') const result = await matchByXPath(graph, '@name = "TestRect"', sceneNode) expect(result).toBe(true) }) @@ -198,7 +200,7 @@ describe('matchByXPath', () => { rect.resize(100, 100) rect.name = 'Other' - const sceneNode = graph.getNode(rect.id)! + const sceneNode = expectDefined(graph.getNode(rect.id), 'non-matching rectangle') const result = await matchByXPath(graph, '@name = "TestRect"', sceneNode) expect(result).toBe(false) })