diff options
Diffstat (limited to 'prototypes/workbench/value-input.test.mjs')
| -rw-r--r-- | prototypes/workbench/value-input.test.mjs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/prototypes/workbench/value-input.test.mjs b/prototypes/workbench/value-input.test.mjs new file mode 100644 index 0000000..3044048 --- /dev/null +++ b/prototypes/workbench/value-input.test.mjs @@ -0,0 +1,50 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import {readFile} from 'node:fs/promises'; +import {spawnSync} from 'node:child_process'; +import {compile} from './web/compiler.mjs'; +import {createRuntime} from './web/runtime.mjs'; +const wasm=await readFile(new URL('./web/core.wasm',import.meta.url)); +const source=await readFile(new URL('./examples/document.pure',import.meta.url),'utf8'); + +test('numeric controls use explicit change context and cannot read pointer or frame payloads',()=>{ + const p=compile(source);assert.equal(p.states.length,1);assert.equal(p.views.length,0);assert.equal(p.handlers[0].event,33); + for(const s of [ + 'state x=0\ninput n=value\non n.down {x=1}', + 'state x=0\ninput k=Space\non k.change {x=1}', + 'state x=0\ninput n=value\non n.change {x=event_x}', + 'state x=0\non frame {x=event_value}', + 'input n=value\ntext v(0,0,event_value)', + 'record R {x=0}\nitem a=R()\ninput k=Space\nrule r(t:R){t.x=event_value}\non k.down use r(a)', + 'state event_value=0', + ])assert.throws(()=>compile(s),s); +}); + +test('numeric input handles scalar rules, rollback, cache invalidation and signed zero',async()=>{ + const r=await createRuntime(wasm,{cacheEntries:32}); + const code='record R {x=10}\nitem a=R()\ninput n=value\nrule r(t:R){t.x=event_value}\non n.change use r(a)\ntext v(0,0,a.x)'; + r.apply(code);r.snapshot();r.snapshot();r.change('n',25);assert.equal(r.snapshot().views[0].value,25); + r.change('n',-0);assert(Object.is(r.snapshot().states['a.x'],-0));assert.deepEqual(r.snapshot().held,[]); + const before=r.snapshot();assert.throws(()=>r.change('n',Infinity));assert.throws(()=>r.down('n'));assert.throws(()=>r.point('n','down',1,2)); + assert.equal(r.snapshot().successfulEvents,before.successfulEvents); + r.apply(code+'\non n.change {a.x=1/0}');assert.equal(r.change('n',80),4);assert(Object.is(r.snapshot().states['a.x'],-0)); + assert.equal(r.snapshot().lastFailure.value,80);assert.throws(()=>r.exportDocument(),/오류/); + r.apply(code);const saved=r.exportDocument();const next=await createRuntime(wasm);next.restoreDocument(saved);next.change('n',32);assert.equal(next.snapshot().states['a.x'],32); +}); + +test('the document policy receives range, keyboard and pointer requests without layouts or text in VM state',async()=>{ + const r=await createRuntime(wasm);r.apply(source); + for(const [value,expected] of [[60,60],[1000,80],[-1000,20],[45.5,45.5]]){assert.equal(r.change('split',value,'control'),0);assert.deepEqual(r.snapshot().states,{ratio:expected});} + r.down('reset');r.up('reset');assert.deepEqual(r.snapshot().states,{ratio:50}); + assert.equal(r.snapshot().views.length,0);assert.equal(r.snapshot().memory.activeStateBytes,8); + const published=[];const target={begin(){},view(){assert.fail('no declared views');},value(){assert.fail('no view values');},state(i,v){published.push(v);},end(n){assert.equal(n,0);}}; + r.present(target);assert.deepEqual(published,[50]); + r.apply(source.replace('20, 80','30, 70'));r.change('split',10);assert.equal(r.snapshot().states.ratio,30); + const current=r.currentProgram;assert.throws(()=>r.apply(source+'\non split.down {ratio=0}'));assert.equal(r.currentProgram,current); +}); + +test('CLI supplies the same numeric control value and rejects nonfinite input',()=>{ + const run=input=>spawnSync(process.execPath,[new URL('./cli.mjs',import.meta.url).pathname,new URL('./examples/document.pure',import.meta.url).pathname],{input,encoding:'utf8'}); + const ok=run('change split 95\nquit\n');assert.equal(ok.status,0,ok.stderr);assert.equal(JSON.parse(ok.stdout.trim()).states.ratio,80); + const bad=run('change split NaN\nquit\n');assert.equal(bad.status,1);assert.match(bad.stderr,/유한/); +}); |
