// Read-only draft checks: actual values remain visible alongside server type errors. const assert=require('node:assert/strict'); (async()=>{ const browser=await require('./support/browser.cjs').launchBrowser(); try{ const page=await browser.newPage({viewport:{width:1280,height:950}}),errors=[]; page.on('pageerror',e=>errors.push(e.message)); await page.goto(process.env.MEGURI_URL||'http://127.0.0.1:3000/?view=configuration'); await page.getByLabel('Username',{exact:true}).fill('alice');await page.getByLabel('Password',{exact:true}).fill(await require('./support/browser.cjs').demoPassword());await page.getByRole('button',{name:'Sign in',exact:true}).click(); await page.getByRole('button',{name:'Edit rule Weekly Time off',exact:true}).click(); await page.evaluate(()=>{const a=Alpine.$data(document.body),b=a.form.blocks.find(b=>b.kind==='escalation');a.editBinding(b.fields.repeat_count ||= a.literal(0),'number','Repeat count');}); const preview=page.getByRole('textbox',{name:'Value preview',exact:true});await preview.waitFor();assert.equal(await preview.inputValue(),'0'); await page.getByLabel('Value source',{exact:true}).selectOption('variable'); const projects=await page.evaluate(()=>Alpine.$data(document.body).generationDraft.variables.find(v=>v.name==='projects').id); await page.getByLabel('Binding variable',{exact:true}).selectOption(projects); await page.waitForFunction(()=>document.querySelector('.binding-value-preview textarea')?.value.includes('Payments')); const projectValues=JSON.parse(await preview.inputValue()); assert.deepEqual(projectValues.map(project=>project.name),['Payments','Search','Billing','Identity','Data platform','Developer portal']); assert.deepEqual(projectValues.map(project=>project.responsible.map(person=>person.username)),[ ['alice','bob','dave'],['bob','erin'],['carol','alice','erin'], ['dave','carol'],['erin','dave','bob'],['carol','erin'], ]); const directory=await page.evaluate(()=>Alpine.$data(document.body).people); for(const project of projectValues)for(const person of project.responsible){ const known=directory.find(candidate=>candidate.id===person.id); assert(known,'Nested preview person must retain a real scoped identity'); assert.equal(person.type,'person');assert.equal(person.name,known.display_name);assert.equal(person.username,known.username); } await page.waitForFunction(()=>{const a=Alpine.$data(document.body);return !a.generationLoading && a.generationResult?.issues.some(i=>i.message.includes('repeat_count'));}); await page.screenshot({path:'test-results/binding-value-preview.png'}); await page.getByLabel('Binding variable',{exact:true}).selectOption('');await page.waitForFunction(()=>document.querySelector('.binding-value-preview textarea')?.value===''); await page.getByRole('button',{name:'Done',exact:true}).click();await page.getByRole('dialog').getByRole('button',{name:'Cancel',exact:true}).click(); await page.getByRole('button',{name:'Edit rule Project owners during working hours',exact:true}).click(); await page.evaluate(()=>{const a=Alpine.$data(document.body);a.editBinding(a.form.blocks[0].fields.participants,'list','Owners');}); await page.waitForFunction(()=>document.querySelector('.binding-value-preview textarea')?.value.includes('Dave Wilson')); const people=JSON.parse(await preview.inputValue());assert.equal(people.length,3);assert.equal(people[0].name,'Alice Morgan');assert.equal(people[0].username,'alice');assert.equal(people[1].name,'Bob Chen'); const result=await page.evaluate(()=>{const a=Alpine.$data(document.body),id=a.people.find(p=>p.username==='alice').id,unknown=crypto.randomUUID(),value={nested:[id,a.doc.schedules[0].id,unknown],number:7,flag:false};const before=JSON.stringify(value),draft=JSON.stringify(a.generationPayload());return {pretty:a.previewValue(value),unknown,unchanged:before===JSON.stringify(value)&&draft===JSON.stringify(a.generationPayload())};});assert(result.unchanged);assert.equal(result.pretty.nested[0].name,'Alice Morgan');assert.equal(result.pretty.nested[1].type,'schedule');assert.equal(result.pretty.nested[2],result.unknown);assert.equal(result.pretty.number,7);assert.equal(result.pretty.flag,false); assert((await page.locator('.binding-value-preview small').innerText()).includes('Payments')); await page.setViewportSize({width:390,height:844});await page.screenshot({path:'test-results/binding-value-preview-mobile.png'}); assert(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth));assert.deepEqual(errors,[]); console.log('PASS: live formatted values, server type errors, missing-value clearing, iteration context, mobile'); }finally{await browser.close();} })().catch(e=>{console.error(e);process.exitCode=1;});