oficina / sheets Public

Clone
git clone https://amadan.net/oficina/sheets

Plain git — no account needed to clone.

Download

Download this file

1/* Drive the table view's formatting with JavaScript SWITCHED OFF.
2 *
3 * The only drive script that runs a page with javaScriptEnabled:false,
4 * and the point of it: PRODUCT.md's second principle says the scriptless
5 * path is the product, not the fallback, so a test that drove this with
6 * scripting on would prove the wrong thing entirely.
7 *
8 * It picks bold, centre and a fill from three selects, submits, follows
9 * the 303, and reads the COMPUTED style off the cell — then reopens the
10 * grid and asserts it agrees. Both halves matter: a screen that can set
11 * bold and not show it is the worse half of the feature.
12 *
13 * SHEETS_SOCK=$D/s.sock SHEETS_LOG=$D/s.log OUT=$D \
14 * PLAYWRIGHT=/path/to/playwright/index.js node tools/drive/tableformat.mjs
15 */
16import net from 'node:net';
17import fs from 'node:fs';
18const pw=await import(process.env.PLAYWRIGHT); const chromium=pw.chromium||(pw.default&&pw.default.chromium);
19const 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());});
20await new Promise(r=>proxy.listen(8799,'127.0.0.1',r));
21const base='http://127.0.0.1:8799', OUT=process.env.OUT;
22const browser=await chromium.launch();
23const page=await (await browser.newContext({viewport:{width:1280,height:900},deviceScaleFactor:2})).newPage();
24const errs=[]; page.on('pageerror',e=>errs.push(String(e)));
25await page.goto(`${base}/signin`); await page.fill('input[type=email]','paul@example.com');
26await Promise.all([page.waitForURL(/signin\?sent=1/), page.click('form[action="/signin"] button[type=submit]')]);
27const mm=[...fs.readFileSync(process.env.SHEETS_LOG,'utf8').matchAll(/http:\/\/127\.0\.0\.1:8799\/auth\/verify\?[^\s\\"]+/g)].pop();
28await page.goto(mm[0]); await page.waitForURL(/\/sheets/);
29// Create from the top bar, then name it by renaming: the list's #title
30// field is gone, so a sheet is born "Untitled sheet" and named after.
31await Promise.all([page.waitForURL(/\/sheets\/\d+$/),page.click('[estilo-bar-actions] form[action="/sheets"] button[type=submit]')]);
32await page.fill('[estilo-bar-title-input]','Table format');
33await Promise.all([page.waitForURL(/\/sheets\/\d+$/),page.press('[estilo-bar-title-input]','Enter')]);
34const url=page.url();
35await page.waitForFunction(()=>window.SheetsGrid&&window.SheetsGrid.worksheet());
36for(const [r,c,v] of [[0,0,'Region'],[0,1,'Revenue'],[1,0,'North'],[1,1,'1200'],[2,0,'South'],[2,1,'900']])
37 await page.evaluate(([r,c,v])=>window.SheetsGrid.write(r,c,v),[r,c,v]);
38await page.waitForTimeout(600);
39
40// JavaScript OFF, to prove the scriptless claim.
41const ctx2=await browser.newContext({viewport:{width:1280,height:900},deviceScaleFactor:2,javaScriptEnabled:false,
42 storageState: await page.context().storageState()});
43const p2=await ctx2.newPage();
44await p2.goto(`${base}${new URL(url).pathname}/table?page=1&edit=0,0`);
45console.log('scriptless: the format form is present:', await p2.locator('[data-cell-format]').count()>0);
46await p2.selectOption('select[name=bold]','set');
47await p2.selectOption('select[name=align]','center');
48await p2.selectOption('select[name=fill]','green');
49await Promise.all([p2.waitForNavigation(), p2.click('[data-cell-format] button[type=submit]')]);
50console.log('scriptless: landed on', new URL(p2.url()).pathname + new URL(p2.url()).search);
51const painted = await p2.evaluate(()=>{
52 const td=[...document.querySelectorAll('[data-cell-table] td')].find(t=>t.textContent.includes('Region'));
53 if(!td) return 'cell not found';
54 const cs=getComputedStyle(td);
55 return {attrs:[...td.attributes].map(a=>a.name).join(' '), weight:cs.fontWeight, align:cs.textAlign, bg:cs.backgroundColor};});
56console.log('scriptless: the cell now paints', JSON.stringify(painted));
57await p2.screenshot({path:`${OUT}/table-format.png`, clip:{x:0,y:0,width:1000,height:620}});
58
59// and the grid agrees
60await page.reload(); await page.waitForFunction(()=>window.SheetsGrid&&window.SheetsGrid.worksheet());
61await page.waitForTimeout(600);
62console.log('grid agrees:', JSON.stringify(await page.evaluate(()=>window.SheetsGrid.styleAt(0,0))));
63console.log('ERRORS:',JSON.stringify(errs));
64await browser.close(); proxy.close(); process.exit(0);
65