import { expect, test } from '@playwright/test'; import path from 'node:path'; import fs from 'node:fs'; import { observeNative, captureNativeWorkflowState, performNativeAction, exposeWebTools } from '../fixtures/native-ui-workflow'; import { queryNativeJSON, readNativeHistory } from '../fixtures/native-modeling-workflow'; const sceneSource = 'import bpy,json\nprint(json.dumps([{\"name\":s.name,\"viewLayers\":[v.name for v in s.view_layers]} for s in bpy.data.scenes]))'; const cases = [ ['sequence_editing/sequence.blend', 'sequence', '1', '1 RenderLayer'], ['io_tests/blend_geometry/all_quads.blend', 'all_quads', 'Scene', 'RenderLayer'], ['sequence_editing/effects/blends.blend', 'blends', 'Scene', 'ViewLayer'], ['sequence_editing/vse_load_meta_stack.blend', 'vse_load_meta_stack', 'Scene', 'ViewLayer'], ] as const; test.afterEach(async ({ page }, info) => { await info.attach('native-state', { body: JSON.stringify(await captureNativeWorkflowState(page)), contentType: 'application/json' }); }); for (const [file, project, scene, viewLayer] of cases) test(`original ${project} opens through the product file input`, async ({ page }) => { const fixture = path.resolve(import.meta.dirname, '../../../blender-5.2.0/tests/files', file); test.setTimeout(180000); await observeNative(page); await page.goto('/'); await expect(page.getByTestId('engine-status')).toHaveText('Engine: new General project', { timeout: 60000 }); await performNativeAction(page, { type: 'openBlend' }, () => page.getByTestId('blend-file-input').setInputFiles(fixture)); await expect(page.locator('main.blender-app')).toHaveAttribute('data-project-id', project, { timeout: 30000 }); await expect(page.getByTestId('engine-status')).toContainText('SceneIR'); const { value } = await queryNativeJSON(page, sceneSource); expect(value).toEqual([{ name: scene, viewLayers: [viewLayer] }]); await exposeWebTools(page); const download = page.waitForEvent('download'); await page.getByRole('button', { name: '保存项目', exact: true }).click(); const saved = await download; const bytes = fs.readFileSync((await saved.path())!); await performNativeAction(page, { type: 'openBlend' }, () => page.getByTestId('blend-file-input').setInputFiles({ name: `${project}-saved.blend`, mimeType: 'application/octet-stream', buffer: bytes })); await expect(page.locator('main.blender-app')).toHaveAttribute('data-project-id', `${project}-saved`); expect((await queryNativeJSON(page, sceneSource)).value).toEqual(value); const history = await readNativeHistory(page); await performNativeAction(page, { type: 'openBlend' }, () => page.getByTestId('blend-file-input').setInputFiles({ name: 'truncated.blend', mimeType: 'application/octet-stream', buffer: fs.readFileSync(fixture).subarray(0, 8) }), false); expect((await queryNativeJSON(page, sceneSource)).value).toEqual(value); expect(await readNativeHistory(page)).toEqual(history); });