const assert=require('node:assert/strict'); const fs=require('node:fs'); const {launchBrowser,isolatedUser,signIn}=require('./support/browser.cjs'); const base=process.env.MEGURI_BROWSER_URL||'http://127.0.0.1:3000'; assert(['localhost','127.0.0.1'].includes(new URL(base).hostname)); (async()=>{ const browser=await launchBrowser(); try { const page=await browser.newPage({locale:'en-US',viewport:{width:1280,height:900}}); const errors=[];page.on('pageerror',e=>errors.push(e.message)); // Sandbox 12 belongs to this suite; workspaces cannot be created, so it starts empty. const tester=await isolatedUser({sandbox:12,prefix:'binding-path',display:'Path tester'}); await signIn(page,tester.username,tester.password); await page.getByLabel('Workspace',{exact:true}).waitFor(); const dialog=page.getByRole('dialog'); await page.evaluate(()=>{ const a=Alpine.$data(document.body),root=a.newNode('dictionary'),owners=a.newNode('list',null,'owners'); owners.entries=[a.newNode('text','First owner'),a.newNode('text','Second owner')];root.entries=[owners]; const variable={id:crypto.randomUUID(),name:'Project',node:root};a.generationDraft.variables.push(variable); a.editGenerationRule();const block=a.newBlock('rotation');block.fields.name={kind:'variable',variable:variable.id,path:[]};a.form.blocks=[block]; }); const open=()=>page.evaluate(()=>{const a=Alpine.$data(document.body);a.editBinding(a.form.blocks[0].fields.name,'text','Name');}); await open(); const popup=page.locator('.binding-popover'),path=popup.getByLabel('Nested field or position',{exact:true}); await path.pressSequentially('owners / ',{delay:30}); assert.equal(await path.inputValue(),'owners / '); await path.pressSequentially('1',{delay:30}); await page.waitForFunction(()=>Alpine.$data(document.body).bindingValuePreview().text.includes('First owner')); assert.deepEqual(await page.evaluate(()=>Alpine.$data(document.body).form.blocks[0].fields.name.path),['owners','1']); await path.press('Backspace');await path.pressSequentially('2'); await page.waitForFunction(()=>Alpine.$data(document.body).bindingValuePreview().text.includes('Second owner')); await popup.getByRole('button',{name:'Done',exact:true}).click();await open(); assert.equal(await path.inputValue(),'owners / 2'); await page.setViewportSize({width:390,height:844}); fs.mkdirSync('test-results',{recursive:true});await page.screenshot({path:'test-results/binding-path-mobile.png'}); assert(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)); await popup.getByLabel('Value source',{exact:true}).selectOption('literal'); await popup.getByLabel('Value source',{exact:true}).selectOption('variable'); assert.equal(await path.inputValue(),''); assert.deepEqual(errors,[]); console.log('PASS: typed nested path, live resolved values, edits, reopening, mobile and source reset'); }finally{await browser.close();} })().catch(e=>{console.error(e);process.exitCode=1;});