From a6ce439f3727e27f7957806e5a52f4fb7acd8122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=8F=84=EC=96=B8?= Date: Wed, 28 Oct 2026 10:15:06 +0900 Subject: [PATCH] test: verify responsive workbench layout (#9) --- tests/responsive-ui.cjs | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/responsive-ui.cjs diff --git a/tests/responsive-ui.cjs b/tests/responsive-ui.cjs new file mode 100644 index 0000000..1583ae2 --- /dev/null +++ b/tests/responsive-ui.cjs @@ -0,0 +1,52 @@ +const {chromium}=require('playwright'); +const assert=require('node:assert/strict'); +const fs=require('node:fs/promises'); +const path=require('node:path'); +const out=path.resolve(__dirname,'../test-results'); +(async()=>{ + const browser=await chromium.launch({headless:true,...(process.env.PLAYWRIGHT_CHANNEL?{channel:process.env.PLAYWRIGHT_CHANNEL}:{})}); + const page=await browser.newPage();const errors=[];page.on('pageerror',e=>errors.push(e.message)); + const results=[];let failure; + await fs.mkdir(out,{recursive:true}); + try{ + for(const [width,height] of [[1920,1080],[1366,768],[390,844]]){ + await page.setViewportSize({width,height});await page.goto(process.env.VIEWER_URL||'http://127.0.0.1:8081/',{waitUntil:'networkidle'}); + await page.waitForFunction(()=>document.querySelector('#loading').hidden); + const bounds=await page.evaluate(()=>({width:innerWidth,scroll:document.documentElement.scrollWidth, + mainBottom:document.querySelector('.app-grid').getBoundingClientRect().bottom, + footerTop:document.querySelector('.statusbar').getBoundingClientRect().top, + canvasWidth:document.querySelector('#scene').getBoundingClientRect().width})); + assert.ok(bounds.scroll<=width+1,JSON.stringify(bounds));assert.ok(bounds.mainBottom<=bounds.footerTop+1); + assert.ok(bounds.canvasWidth>width*(width<=1000?.9:.4)); + await page.screenshot({path:path.join(out,`ui9-${width}.png`),fullPage:true}); + if(width>1000){ + const original=bounds.canvasWidth;await page.locator('#toggle-controls').click(); + assert.equal(await page.locator('#controls-panel').isVisible(),false); + assert.ok(await page.locator('#scene').evaluate(e=>e.getBoundingClientRect().width)>original); + await page.locator('#toggle-controls').click(); + await page.locator('#toggle-inspector').click();assert.equal(await page.locator('#inspector-panel').isVisible(),false); + await page.locator('#toggle-inspector').click(); + }else{ + assert.equal(await page.locator('#controls-panel').isVisible(),false); + assert.equal(await page.locator('#inspector-panel').isVisible(),false); + await page.locator('#toggle-controls').click();assert.equal(await page.locator('#controls-panel').isVisible(),true); + await page.locator('#search').fill('UHR1-02901');await page.locator('#search-results button').first().click(); + assert.equal(await page.locator('#controls-panel').isVisible(),false); + assert.equal(await page.locator('#inspector-panel').isVisible(),true); + assert.equal(await page.locator('#selected-id').textContent(),'UHR1-02901'); + await page.screenshot({path:path.join(out,'ui9-mobile-details.png'),fullPage:true}); + await page.keyboard.press('Escape');assert.equal(await page.locator('#inspector-panel').isVisible(),false); + assert.equal(await page.locator('#toggle-inspector').evaluate(e=>e===document.activeElement),true); + await page.locator('#toggle-controls').click();await page.locator('#search').fill('__no_result__'); + assert.equal(await page.locator('#search-results button').count(),0); + await page.screenshot({path:path.join(out,'ui9-mobile-controls.png'),fullPage:true}); + await page.locator('#panel-backdrop').click({position:{x:375,y:100}}); + assert.equal(await page.locator('#controls-panel').isVisible(),false); + } + const overflow=await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth+1);assert.equal(overflow,false); + results.push({width,height,status:'passed'}); + } + assert.deepEqual(errors,[]); + }catch(e){failure=e.stack;process.exitCode=1;await page.screenshot({path:path.join(out,'ui9-failure.png'),fullPage:true}).catch(()=>{});} + finally{const report={status:failure?'failed':'passed',viewports:results,...(failure?{error:failure}:{})};await fs.writeFile(path.join(out,'ui9-validation.json'),JSON.stringify(report,null,2));console.log(JSON.stringify(report,null,2));await browser.close();} +})().catch(e=>{console.error(e);process.exitCode=1;});