// Optional external-exhibit regression check; not NGN product configuration. // Usage: node test-fixtures/check-scifi-arguments.cjs const fs = require('node:fs'); const vm = require('node:vm'); const assert = require('node:assert/strict'); async function main() { const context = { window: {}, console }; vm.createContext(context); vm.runInContext(fs.readFileSync(process.argv[2], 'utf8'), context); const calls = []; const adapter = new context.window.XZBTContractAdapter({ bindings: { invokers: { 'speech.say': args => calls.push(args), 'display.ticker': args => calls.push(args), 'speech.generate-announcement': args => calls.push(args) } } }); for (const [id, maxLength] of [['speech.say', 2000], ['display.ticker', 512]]) { const descriptor = adapter.targets.get(id); assert.equal(Object.hasOwn(descriptor, 'args'), false); assert.deepEqual(JSON.parse(JSON.stringify(descriptor.arguments)), [ { name: 'text', type: 'string', required: true, maxLength } ]); for (const args of [{}, { text: null }, { text: 42 }, { text: 'x', extra: true }, { text: 'x'.repeat(maxLength + 1) }]) { const before = calls.length; const result = await adapter.invokeAction(id, args); assert.equal(result.code, 'INVALID_VALUE'); assert.equal(calls.length, before, 'invalid arguments must not execute'); } const text = 'x'.repeat(maxLength); assert.equal((await adapter.invokeAction(id, { text })).ok, true); assert.equal(calls.at(-1).text, text); console.log(`PASS ${id}: arguments metadata, required/type/unknown/length rejection, exact length accepted`); } assert.equal((await adapter.invokeAction('speech.generate-announcement', {})).ok, true); assert.equal((await adapter.invokeAction('speech.generate-announcement', { text: 'x' })).code, 'INVALID_VALUE'); console.log('PASS argumentless impulse: empty args accepted, unknown key rejected'); } main().catch(error => { console.error(error); process.exitCode = 1; });