'use strict'; const assert = require('node:assert/strict'); const path = require('node:path'); const { spawnSync } = require('node:child_process'); const test = require('node:test'); let fixture; function rendered() { if (!fixture) { const run = spawnSync(process.env.PHP_BINARY || 'php', [path.join(__dirname, 'ticket-native-render-harness.php')], { encoding: 'utf8' }); assert.equal(run.status, 0, run.stderr || run.stdout); fixture = JSON.parse(run.stdout); } return fixture; } test('page renders header creation action and one of each dialog, without eagerly reading conversations', () => { const { html, initial } = rendered(); assert.equal((html.match(/工单号<\/dt>
TK-00021<\/dd>/); }); test('read handler enforces capability, nonce and record existence', () => { const { missing, denied, nonce } = rendered(); assert.equal(missing.status, 404); assert.equal(denied.status, 403); assert.equal(nonce.status, 403); for (const result of [missing, denied, nonce]) { assert.equal(result.success, false); assert.equal(result.data.panel, undefined); assert.equal(result.data.list, undefined); } }); test('real rendering escapes user content, quotes and metadata', () => { const { html, open } = rendered(); const all = html + open.data.panel; assert.match(all, /Question <svg onload=alert\(1\)>/); assert.match(all, /Description <script>alert\(1\)<\/script>/); assert.match(all, /Secret <script>alert\(1\)<\/script>/); assert.match(all, /原回复已删除/); assert.match(all, /target="_blank" rel="noopener noreferrer"/); assert.doesNotMatch(all, /