/* Drive the table view's formatting with JavaScript SWITCHED OFF. * * The only drive script that runs a page with javaScriptEnabled:false, * and the point of it: PRODUCT.md's second principle says the scriptless * path is the product, not the fallback, so a test that drove this with * scripting on would prove the wrong thing entirely. * * It picks bold, centre and a fill from three selects, submits, follows * the 303, and reads the COMPUTED style off the cell — then reopens the * grid and asserts it agrees. Both halves matter: a screen that can set * bold and not show it is the worse half of the feature. * * SHEETS_SOCK=$D/s.sock SHEETS_LOG=$D/s.log OUT=$D \ * PLAYWRIGHT=/path/to/playwright/index.js node tools/drive/tableformat.mjs */ import net from 'node:net'; import fs from 'node:fs'; const pw=await import(process.env.PLAYWRIGHT); const chromium=pw.chromium||(pw.default&&pw.default.chromium); const proxy=net.createServer(c=>{const u=net.connect(process.env.SHEETS_SOCK);c.pipe(u);u.pipe(c);c.on('error',()=>u.destroy());u.on('error',()=>c.destroy());}); await new Promise(r=>proxy.listen(8799,'127.0.0.1',r)); const base='http://127.0.0.1:8799', OUT=process.env.OUT; const browser=await chromium.launch(); const page=await (await browser.newContext({viewport:{width:1280,height:900},deviceScaleFactor:2})).newPage(); const errs=[]; page.on('pageerror',e=>errs.push(String(e))); await page.goto(`${base}/signin`); await page.fill('input[type=email]','paul@example.com'); await Promise.all([page.waitForURL(/signin\?sent=1/), page.click('form[action="/signin"] button[type=submit]')]); const mm=[...fs.readFileSync(process.env.SHEETS_LOG,'utf8').matchAll(/http:\/\/127\.0\.0\.1:8799\/auth\/verify\?[^\s\\"]+/g)].pop(); await page.goto(mm[0]); await page.waitForURL(/\/sheets/); // Create from the top bar, then name it by renaming: the list's #title // field is gone, so a sheet is born "Untitled sheet" and named after. await Promise.all([page.waitForURL(/\/sheets\/\d+$/),page.click('[estilo-bar-actions] form[action="/sheets"] button[type=submit]')]); await page.fill('[estilo-bar-title-input]','Table format'); await Promise.all([page.waitForURL(/\/sheets\/\d+$/),page.press('[estilo-bar-title-input]','Enter')]); const url=page.url(); await page.waitForFunction(()=>window.SheetsGrid&&window.SheetsGrid.worksheet()); for(const [r,c,v] of [[0,0,'Region'],[0,1,'Revenue'],[1,0,'North'],[1,1,'1200'],[2,0,'South'],[2,1,'900']]) await page.evaluate(([r,c,v])=>window.SheetsGrid.write(r,c,v),[r,c,v]); await page.waitForTimeout(600); // JavaScript OFF, to prove the scriptless claim. const ctx2=await browser.newContext({viewport:{width:1280,height:900},deviceScaleFactor:2,javaScriptEnabled:false, storageState: await page.context().storageState()}); const p2=await ctx2.newPage(); await p2.goto(`${base}${new URL(url).pathname}/table?page=1&edit=0,0`); console.log('scriptless: the format form is present:', await p2.locator('[data-cell-format]').count()>0); await p2.selectOption('select[name=bold]','set'); await p2.selectOption('select[name=align]','center'); await p2.selectOption('select[name=fill]','green'); await Promise.all([p2.waitForNavigation(), p2.click('[data-cell-format] button[type=submit]')]); console.log('scriptless: landed on', new URL(p2.url()).pathname + new URL(p2.url()).search); const painted = await p2.evaluate(()=>{ const td=[...document.querySelectorAll('[data-cell-table] td')].find(t=>t.textContent.includes('Region')); if(!td) return 'cell not found'; const cs=getComputedStyle(td); return {attrs:[...td.attributes].map(a=>a.name).join(' '), weight:cs.fontWeight, align:cs.textAlign, bg:cs.backgroundColor};}); console.log('scriptless: the cell now paints', JSON.stringify(painted)); await p2.screenshot({path:`${OUT}/table-format.png`, clip:{x:0,y:0,width:1000,height:620}}); // and the grid agrees await page.reload(); await page.waitForFunction(()=>window.SheetsGrid&&window.SheetsGrid.worksheet()); await page.waitForTimeout(600); console.log('grid agrees:', JSON.stringify(await page.evaluate(()=>window.SheetsGrid.styleAt(0,0)))); console.log('ERRORS:',JSON.stringify(errs)); await browser.close(); proxy.close(); process.exit(0);