// Uses TestBrowserMenuFixture's rendered page with synthetic cells and size API. import assert from 'node:assert/strict'; import fs from 'node:fs'; const pw=await import(process.env.PLAYWRIGHT||'playwright'); const fixture=JSON.parse(fs.readFileSync(process.env.SHEETS_MENU_FIXTURE)); for(const name of ['chromium','webkit']) { const browser=await pw[name].launch(name==='webkit'&&process.env.WEBKIT_EXECUTABLE_PATH?{executablePath:process.env.WEBKIT_EXECUTABLE_PATH}:{}); try { const page=await browser.newPage({viewport:{width:1400,height:900}}); let requests=[],sizes={cols:{}},reject=false; const errors=[];page.on('pageerror',e=>errors.push(e.message)); const cells=[{r:0,c:0,raw:'=SUM(B1:B80)',display:'5'}, {r:80,c:0,raw:'The widest value is below the viewport',display:'The widest value is below the viewport',f:'bold'}, {r:1,c:1,raw:'Medium length',display:'Medium length'}, {r:0,c:2,raw:'=A_VERY_LONG_FORMULA_WITH_A_SHORT_RESULT()',display:'1'}, {r:0,c:3,raw:'W'.repeat(1000),display:'W'.repeat(1000)}]; await page.route('https://sheets.test/**',async route=>{ const req=route.request(),path=new URL(req.url()).pathname; if(fixture.assets[path])return route.fulfill({body:fixture.assets[path],contentType:path.endsWith('.js')?'application/javascript':path.endsWith('.css')?'text/css':'image/svg+xml'}); if(path.endsWith('/stream'))return route.fulfill({body:'',contentType:'text/event-stream'}); if(path.endsWith('/size')&&req.method()==='POST') { const value=req.postDataJSON();requests.push(value); if(reject)return route.fulfill({status:400,body:'refused'}); sizes.cols[value.col]=value.size; } if(path.startsWith('/api/'))return route.fulfill({json:{version:1,cells,formats:{bold:{b:true,i:true}},sizes}}); return route.fulfill({body:fixture.html,contentType:'text/html'}); }); async function load() { requests=[];sizes={cols:{}};reject=false; await page.goto('https://sheets.test/sheets/1');await page.waitForFunction(()=>SheetsGrid?.worksheet()); await page.evaluate(()=>new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve)))); } const header=c=>page.locator(`.jss_worksheet > thead > tr:first-child > td[data-x="${c}"]`); async function divider(c) { const rect=await header(c).boundingBox(); await page.mouse.dblclick(rect.x+rect.width-2,rect.y+rect.height/2); } async function resized(c) { await page.waitForFunction(c=>Number(SheetsGrid.worksheet().getWidth(c))!==100,c); } await load();await divider(0);await resized(0); assert.equal(requests.length,1);assert.equal(requests[0].col,0); assert.ok(requests[0].size>200,'must measure content below viewport'); const first=requests[0].size; await page.reload();await page.waitForFunction(()=>SheetsGrid?.worksheet()); assert.equal(Number(await page.evaluate(()=>SheetsGrid.worksheet().getWidth(0))),first,'width survives reload'); console.log(name+': single-column divider fits offscreen formatted content and persists'); await load();await header(0).click();await header(1).click({modifiers:['Shift']}); const selected=await page.evaluate(()=>SheetsGrid.selection()); assert.equal(Math.min(selected.c,selected.c2),0);assert.equal(Math.max(selected.c,selected.c2),1); await divider(0);await page.waitForFunction(()=>Number(SheetsGrid.worksheet().getWidth(1))!==100); assert.deepEqual(requests.map(r=>r.col),[0,1]);assert.ok(sizes.cols[0]>sizes.cols[1]); assert.equal(sizes.cols[0],first); console.log(name+': selected columns fit individually without first equalizing widths'); // The existing manual group resize must persist both columns too. requests=[];const rect=await header(0).boundingBox(); await page.mouse.move(rect.x+rect.width-2,rect.y+rect.height/2);await page.mouse.down(); await page.mouse.move(rect.x+rect.width+30,rect.y+rect.height/2);await page.mouse.up(); await page.evaluate(()=>SheetsSizes.settled()); assert.deepEqual(requests.map(r=>r.col),[0,1]);assert.equal(sizes.cols[0],sizes.cols[1]); console.log(name+': manual group resize persists all columns'); await load();await header(2).click();await page.evaluate(()=>SheetsAutoFit()); assert.ok(sizes.cols[2]<100,'measure formula result, not raw expression'); await header(3).click();await page.evaluate(()=>SheetsAutoFit());assert.equal(sizes.cols[3],2000); await header(4).click();await page.evaluate(()=>SheetsAutoFit());assert.ok(sizes.cols[4]>=16&&sizes.cols[4]<100); console.log(name+': formula display, empty columns, and maximum width'); await load();await header(0).click();await header(1).click({modifiers:['Shift']});reject=true; await page.evaluate(()=>SheetsAutoFit());assert.equal(requests.length,1);assert.deepEqual(sizes.cols,{}); reject=false;await page.evaluate(()=>SheetsAutoFit());assert.equal(requests.length,3); assert.deepEqual(errors,[]);console.log(name+': failed resize stops and can retry'); } finally {await browser.close();} }