From 924724c5e4fec97913fe39c73cdca4bf53b7f9df Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Fri, 30 Oct 2026 14:16:14 +0800 Subject: [PATCH] Align server visual acceptance with canonical editor routes and canvas onboarding --- apps/studio/scripts/graphic-smoke.cjs | 2 +- apps/studio/scripts/infinite-canvas-smoke.cjs | 5 +++-- apps/waterfall-wiki/src/proxy.ts | 2 +- scripts/verify-studio-visual.cjs | 11 ++++++----- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/studio/scripts/graphic-smoke.cjs b/apps/studio/scripts/graphic-smoke.cjs index 975c480..6808b23 100644 --- a/apps/studio/scripts/graphic-smoke.cjs +++ b/apps/studio/scripts/graphic-smoke.cjs @@ -2,7 +2,7 @@ const {chromium}=require('playwright-core'); const assert=require('node:assert/strict'); (async()=>{const browser=await chromium.launch({channel:'chrome',headless:true});try{const page=await browser.newPage({viewport:{width:1440,height:1000}});const errors=[];page.on('pageerror',e=>errors.push(e.message)); await page.route('**/api/account/session',r=>r.fulfill({json:{user:null}})); - await page.goto((process.env.STUDIO_TEST_ORIGIN||'http://127.0.0.1:3011')+'/studio/graphic'); + await page.goto((process.env.STUDIO_TEST_ORIGIN||'http://8.211.154.134:18131')+'/graphic'); await page.getByRole('button',{name:'添加文字',exact:true}).click(); await page.getByRole('textbox',{name:'文字内容',exact:true}).fill('设计从这里开始'); await page.getByRole('button',{name:'添加矩形',exact:true}).click(); diff --git a/apps/studio/scripts/infinite-canvas-smoke.cjs b/apps/studio/scripts/infinite-canvas-smoke.cjs index 84a0d93..9f21d13 100644 --- a/apps/studio/scripts/infinite-canvas-smoke.cjs +++ b/apps/studio/scripts/infinite-canvas-smoke.cjs @@ -9,9 +9,10 @@ const fs=require('node:fs/promises'); try{ const context=await browser.newContext({viewport:{width:1600,height:1100},storageState:process.env.STORAGE_STATE||undefined}); const page=await context.newPage(),errors=[];page.on('pageerror',e=>errors.push(e.message)); - await page.goto(base+'/studio/infinite_canvas'); - assert.equal(new URL(page.url()).pathname,'/studio/infinite_canvas','Login required; authenticate without weakening protection'); + await page.goto(base+'/infinite_canvas'); + assert.equal(new URL(page.url()).pathname,'/infinite_canvas','Login required; authenticate without weakening protection'); await page.getByRole('heading',{name:'无限画布 / Infinite canvas'}).waitFor(); + await page.getByRole('button',{name:'从示例开始 ↗',exact:true}).click(); // A fresh context is used so this test cannot overwrite a human browser draft. const snapshot=()=>page.evaluate(()=>JSON.parse(localStorage.getItem('studio.infinite-canvas.v1'))); const node=id=>page.locator(`[data-node-id="${id}"]`); diff --git a/apps/waterfall-wiki/src/proxy.ts b/apps/waterfall-wiki/src/proxy.ts index bbc543e..1dea998 100644 --- a/apps/waterfall-wiki/src/proxy.ts +++ b/apps/waterfall-wiki/src/proxy.ts @@ -4,7 +4,7 @@ export function proxy(request: NextRequest) { const path = request.nextUrl.pathname; const responseHeaders = {'Cache-Control':'private, no-store', 'Referrer-Policy':'same-origin'}; // Public knowledge pages are read-only. Account handlers enforce their own origin and session checks. - const publicRead = ['GET','HEAD'].includes(request.method) && (path === '/' || ['/workspace','/graphic','/infinite_canvas','/studio','/studio/graphic','/studio/infinite_canvas'].includes(path) || path.startsWith('/studio/_next/') || path === '/protocol' || ['/llms.txt','/index.md','/agent','/agent/index.md','/api/agent-index','/api/guides'].includes(path) || path.startsWith('/guide/') || path.startsWith('/api/guides/')); + const publicRead = ['GET','HEAD'].includes(request.method) && (path === '/' || ['/workspace','/graphic','/infinite_canvas','/studio','/studio/graphic','/studio/infinite_canvas','/studio/api'].includes(path) || path.startsWith('/studio/_next/') || path === '/protocol' || ['/llms.txt','/index.md','/agent','/agent/index.md','/api/agent-index','/api/guides'].includes(path) || path.startsWith('/guide/') || path.startsWith('/api/guides/')); if (path === '/write' || path === '/documents' || path.startsWith('/documents/') || path === '/api/documents' || path.startsWith('/api/documents/') || publicRead || path === '/account' || path.startsWith('/api/account/')) return NextResponse.next({headers:{...responseHeaders,'Referrer-Policy':'no-referrer'}}); if (path === '/brand-mark.svg' || path === '/login' || path === '/api/auth/login' || path === '/api/auth/logout' || path === '/api/health' || path === '/api/ready' || path.startsWith('/_next/static/')) return NextResponse.next({headers:responseHeaders}); let config; diff --git a/scripts/verify-studio-visual.cjs b/scripts/verify-studio-visual.cjs index 0663bdb..d4b376b 100644 --- a/scripts/verify-studio-visual.cjs +++ b/scripts/verify-studio-visual.cjs @@ -23,8 +23,9 @@ const assert=require('node:assert/strict'); });metrics.push(m);await writeFile(dir+'/metrics.json',JSON.stringify({metrics,images,errors},null,2)); } if(!process.argv.includes('--after-layouts')&&!process.argv.includes('--diagnose'))assert.deepEqual(metrics.filter(m=>m.overflow.length),[],'Default copy must fit every native slot'); - await page.goto(base+'/studio',{waitUntil:'networkidle'}); - assert.equal(new URL(page.url()).pathname,'/studio/graphic'); + await page.goto(base+'/',{waitUntil:'networkidle'});await page.getByRole('heading',{name:/想法不该停在对话里/}).waitFor();await page.screenshot({path:dir+'/landing-desktop.png',fullPage:true}); + await page.goto(base+'/graphic',{waitUntil:'networkidle'}); + assert.equal(new URL(page.url()).pathname,'/graphic'); await page.getByRole('button',{name:'添加文字',exact:true}).waitFor({state:'visible'}); assert.equal(await page.locator('.library-item').count(),0,'Old catalog is retired from the entry page'); await page.getByRole('button',{name:'添加文字',exact:true}).click(); @@ -32,8 +33,8 @@ const assert=require('node:assert/strict'); await page.reload({waitUntil:'networkidle'}); assert.ok(await page.evaluate(()=>JSON.parse(localStorage.getItem('studio.graphic.v1')).items.some(i=>i.text==='Studio 线上验收'))); await page.screenshot({path:dir+'/graphic-desktop.png',fullPage:true}); - await page.goto(base+'/studio/infinite_canvas',{waitUntil:'networkidle'}); - assert.equal(new URL(page.url()).pathname,'/studio/infinite_canvas'); + await page.goto(base+'/infinite_canvas',{waitUntil:'networkidle'}); + assert.equal(new URL(page.url()).pathname,'/infinite_canvas'); await page.getByRole('button',{name:'添加笔记',exact:true}).waitFor({state:'visible'}); await page.screenshot({path:dir+'/infinite-canvas-desktop.png',fullPage:true}); const verify=JSON.parse(await readFile('/tmp/studio-library/verification.json','utf8')); @@ -47,7 +48,7 @@ const assert=require('node:assert/strict'); const direct=await plain.newPage();await direct.goto(base+d.url,{waitUntil:'networkidle'});assert.equal(await direct.locator('article[data-design-id="'+d.id+'"]').count(),1);assert.ok((await direct.locator('article').innerText()).includes('API 验收'));await plain.close(); } for(const slug of ['learning-skills-template','layout-selection']){await page.goto(base+'/studio/ideas/'+slug,{waitUntil:'networkidle'});await page.screenshot({path:dir+'/tool-'+slug+'.png',fullPage:true})} - await page.setViewportSize({width:390,height:844});await page.goto(base+'/studio',{waitUntil:'networkidle'});assert.ok(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth));await page.screenshot({path:dir+'/graphic-mobile.png',fullPage:true}); + await page.setViewportSize({width:390,height:844});await page.goto(base+'/graphic',{waitUntil:'networkidle'});assert.ok(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth));await page.screenshot({path:dir+'/graphic-mobile.png',fullPage:true}); await page.goto(base+verify.results[0].url,{waitUntil:'networkidle'});await page.screenshot({path:dir+'/standard-mobile.png',fullPage:true}); await page.goto(base+'/categories?category='+encodeURIComponent('文档入口'),{waitUntil:'domcontentloaded',timeout:60000});await page.getByRole('navigation',{name:'系统标签分类',exact:true}).waitFor({state:'visible'});assert.equal(await page.locator('.discovery-card').count(),3);await page.waitForFunction(()=>Array.from(document.querySelectorAll('.discovery-card img')).every(img=>img.complete&&img.naturalWidth>0),null,{timeout:60000});await page.screenshot({path:dir+'/document-entries.png',fullPage:true}); await writeFile(dir+'/metrics.json',JSON.stringify({metrics,images,errors},null,2));