import { expect, test } from '@playwright/test'; import fs from 'node:fs'; import path from 'node:path'; import { createHash } from 'node:crypto'; import { observeNative, exposeWebTools, performNativeAction, captureNativeWorkflowState } from '../fixtures/native-ui-workflow'; import { pythonReply, switchNativeWorkspace } from '../fixtures/wasm-console-workflow'; import { stageOriginalAutosaveCase } from '../fixtures/upstream-autosave-case'; test.setTimeout(300000); test.afterEach(async ({ page }, info) => { fs.writeFileSync(info.outputPath('native-trust-last-state.json'), JSON.stringify(await captureNativeWorkflowState(page).catch(error => ({ error: String(error) })), null, 2)); }); test('source-derived native autosave script permission matches desktop assertions', async ({ page }, info) => { await observeNative(page); await page.goto('/?ui=native'); await expect(page.locator('canvas[aria-label="Blender desktop"]')).toHaveAttribute('data-native-input-ready', 'true', { timeout: 60000 }); await exposeWebTools(page); await switchNativeWorkspace(page, 'Scripting'); const prepared = await stageOriginalAutosaveCase(page, info); const inputFile = `${prepared.caseDir}/assets/io_tests/blend_autosave/autosave_image_test.blend`, workDirectory = `${prepared.caseDir}/native-script-trust`; const fixtureSource = fs.readFileSync(path.resolve(import.meta.dirname, '../fixtures/native-autosave-script-trust.py'), 'utf8'), fixtureSha256 = createHash('sha256').update(fixtureSource).digest('hex'); const program = [ 'import hashlib,json', `fixture_source=${JSON.stringify(fixtureSource)}; fixture_scope={'__name__':'__wbv2_native_trust__'}; exec(compile(fixture_source,'NativeAutosaveScriptTrust.py','exec'),fixture_scope)`, `result=fixture_scope['run'](${JSON.stringify(inputFile)},${JSON.stringify(workDirectory)})`, "print('WBV2_NATIVE_AUTOSAVE_SCRIPT_TRUST',json.dumps({'fixtureSha256':hashlib.sha256(fixture_source.encode('utf8')).hexdigest(),'result':result}))", ].join('\n'); const input = page.getByLabel('Python 输入', { exact: true }); await input.fill(`exec(${JSON.stringify(program)})`); await performNativeAction(page, { type: 'jsonCommand', jsonCommand: 'pythonExec' }, () => input.press('Enter')); const reply = await pythonReply(page); fs.writeFileSync(info.outputPath('native-script-trust-result.json'), JSON.stringify({ kind: 'source-derived-native-operator-case', prepared, fixtureSha256, reply, desktopBaseline: 'NOT_CAPTURED', fullAcceptance: 'NOT_CLAIMED' }, null, 2)); expect(reply?.state, reply?.output).toBe('DONE'); expect(reply?.truncated).toBe(false); const marker = reply!.output.split('\n').findLast(line => line.startsWith('WBV2_NATIVE_AUTOSAVE_SCRIPT_TRUST ')); expect(marker, reply!.output).toBeTruthy(); const payload = JSON.parse(marker!.slice('WBV2_NATIVE_AUTOSAVE_SCRIPT_TRUST '.length)); expect(payload.fixtureSha256).toBe(fixtureSha256); expect(payload.result.platform).toBe('emscripten'); expect(payload.result.version).toEqual([5, 2, 0]); expect(payload.result.inputSha256).toBe(prepared.assetHashes['io_tests/blend_autosave/autosave_image_test.blend']); expect(payload.result.kind).toBe('source-derived-native-operator-case'); expect(payload.result.results.map((item: { useScripts: boolean; executed: boolean; sceneMarker: boolean }) => [item.useScripts, item.executed, item.sceneMarker])).toEqual([[false, false, false], [true, true, true], [false, false, false]]); expect(payload.result.autosavePath).toContain(`${workDirectory}/autosave/`); expect(payload.result.autosaveSha256).toMatch(/^[a-f0-9]{64}$/); fs.writeFileSync(info.outputPath('native-script-trust-result.json'), JSON.stringify({ kind: 'source-derived-native-operator-case', prepared, fixtureSha256, payload, reply, desktopBaseline: 'NOT_CAPTURED', nativeCheckboxPointerCase: 'MANUAL_CASE_NOT_RUN', fullAcceptance: 'NOT_CLAIMED' }, null, 2)); await page.screenshot({ path: info.outputPath('native-script-trust.png') }); });