import { expect, type APIRequestContext } from '@playwright/test'; import type { NativeMainReceipt } from '../../protocol/native-workflow'; export async function readBackendMain(api: APIRequestContext, origin: string, handle: { id: string; token: string }): Promise { const endpoint = `${origin}/api/blender-session`, headers = { 'X-Blender-Workflow': '1', 'X-Blender-Session-Token': handle.token, Origin: origin }; const read = () => api.get(`${endpoint}?id=${encodeURIComponent(handle.id)}`, { headers: { ...headers, 'X-Blender-Session-Action': 'read' } }); const post = (action: string, body: object) => api.post(endpoint, { headers: { ...headers, 'X-Blender-Session-Action': action }, data: { ...handle, ...body } }); const initial = await read(); expect(initial.ok()).toBe(true); const prior = await initial.json(); if (prior.command) { expect(prior.command.status).not.toBe('RUNNING'); expect((await post('ack', { sequence: prior.command.sequence })).ok()).toBe(true); } const submitted = await post('command', { command: { kind: 'read-main' } }); expect(submitted.ok()).toBe(true); const issued = await submitted.json(); expect(Number.isSafeInteger(issued.sequence)).toBe(true); let command: any; try { await expect.poll(async () => { const response = await read(); expect(response.ok()).toBe(true); command = (await response.json()).command; return command?.sequence === issued.sequence ? command.status : null; }, { timeout: 120000 }).toBe('SUCCEEDED'); expect(command.artifacts ?? []).toEqual([]); expect(command.resources).toBeUndefined(); const receipt = command.mainReceipt; expect(receipt?.command).toBe('read-main'); expect(receipt.sequence).toBe(issued.sequence); expect(Array.isArray(receipt.objects)).toBe(true); const observed = JSON.parse(command.output.trim().split('\n').at(-1)); expect(observed.version).toEqual([5, 2, 0]); expect(observed.objects).toBe(receipt.objects.length); expect((await post('ack', { sequence: issued.sequence })).ok()).toBe(true); return { ...receipt, workspace: observed.workspace, filepath: observed.filepath, filepathExists: observed.filepathExists, images: observed.images }; } finally { if (command?.resources) { const released = await api.post(`${origin}/api/blender-resources`, { headers: { 'X-Blender-Workflow': '1', 'X-Blender-Resource-Action': 'release', Origin: origin }, data: command.resources }); expect(released.ok()).toBe(true); } } }