diff --git a/.gitea/workflows/creative-workspace.yml b/.gitea/workflows/creative-workspace.yml index e784ddd..c3c3a70 100644 --- a/.gitea/workflows/creative-workspace.yml +++ b/.gitea/workflows/creative-workspace.yml @@ -15,6 +15,23 @@ concurrency: group: creative-workspace-${{ gitea.event.pull_request.number }} cancel-in-progress: true jobs: + verify-deployed-canvas: + runs-on: ces-control + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Verify canvas acceptance script against the designated deployed server + run: | + node --check apps/studio/scripts/infinite-canvas-smoke.cjs + wiki_image=$(docker inspect --format '{{.Config.Image}}' prompt-waterfall-wiki-1) + [[ "$wiki_image" =~ ^waterfall-wiki:[0-9a-f]{40}$ ]] + test_image="waterfall-wiki-tests:${wiki_image#waterfall-wiki:}" + docker image inspect "$test_image" >/dev/null + docker run --rm \ + --mount "type=bind,src=$PWD,dst=/delivery,readonly" \ + -e NODE_PATH=/repo/apps/waterfall-wiki/node_modules \ + -e CHROMIUM_PATH=/usr/bin/chromium \ + --entrypoint node "$test_image" /delivery/apps/studio/scripts/infinite-canvas-smoke.cjs verify: runs-on: ces-control timeout-minutes: 60 diff --git a/apps/studio/scripts/infinite-canvas-smoke.cjs b/apps/studio/scripts/infinite-canvas-smoke.cjs index 730095e..344aa7c 100644 --- a/apps/studio/scripts/infinite-canvas-smoke.cjs +++ b/apps/studio/scripts/infinite-canvas-smoke.cjs @@ -100,11 +100,27 @@ const fs=require('node:fs/promises'); await page.waitForFunction(z=>new DOMMatrix(getComputedStyle(document.querySelector('[class*=world]')).transform).a!==z,anchorBefore.z); const anchorAfter=await worldAt();close(anchorBefore.x,anchorAfter.x);close(anchorBefore.y,anchorAfter.y); const saved=await snapshot();await page.reload();await page.waitForFunction(()=>!!localStorage.getItem('studio.infinite-canvas.v1'));assert.deepEqual(await snapshot(),saved); - await page.getByRole('button',{name:'切换明暗主题',exact:true}).click();await page.reload();await page.waitForFunction(()=>document.querySelector('main').dataset.theme==='light'); + const themeToggle=page.getByRole('button',{name:'切换明暗主题',exact:true}); + await page.waitForFunction(()=>document.querySelector('[data-theme-ready]')?.dataset.themeReady==='true'); + const initialMode=await page.evaluate(()=>document.documentElement.dataset.mode); + assert.ok(['light','dark'].includes(initialMode)); + for(const mode of [initialMode==='light'?'dark':'light',initialMode]){ + await themeToggle.click(); + const matchesTheme=mode=>{ + const root=document.documentElement,canvas=document.querySelector('main'); + return root.dataset.mode===mode&&root.dataset.theme===`canvas-${mode}`&&localStorage.getItem('endoleap.theme')===mode&&getComputedStyle(canvas).backgroundColor===(mode==='dark'?'rgb(20, 20, 20)':'rgb(250, 250, 250)'); + }; + await page.waitForFunction(matchesTheme,mode); + await page.reload({waitUntil:'commit'}); + await page.waitForFunction(()=>document.querySelector('[data-theme-ready]')?.dataset.themeReady==='true'); + await page.waitForFunction(matchesTheme,mode); + assert.deepEqual(await snapshot(),saved,'Theme changes must preserve canvas content'); + await capture('canvas-theme-'+mode); + } if(process.env.SCREENSHOT_DIR){await fs.mkdir(process.env.SCREENSHOT_DIR,{recursive:true});await page.screenshot({path:process.env.SCREENSHOT_DIR+'/canvas-nodes-desktop.png'});} await page.setViewportSize({width:390,height:844});assert.ok(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)); const viewport=await page.locator('[class*=viewport]').boundingBox();assert.equal(viewport.width,390);assert.equal(viewport.height,844); if(process.env.SCREENSHOT_DIR)await page.screenshot({path:process.env.SCREENSHOT_DIR+'/canvas-nodes-mobile.png'}); - assert.deepEqual(errors,[]);console.log('Passed: selected-node re-click editing, drag, formatting, fixed composer, upload, references, task export, deletion/undo, reload and mobile bounds'); + assert.deepEqual(errors,[]);console.log('Passed: selected-node re-click editing, drag, formatting, fixed composer, upload, references, task export, deletion/undo, reload, both persistent root themes and mobile bounds'); }catch(error){if(process.env.SCREENSHOT_DIR&&page){await fs.mkdir(process.env.SCREENSHOT_DIR,{recursive:true});await page.screenshot({path:process.env.SCREENSHOT_DIR+'/canvas-failure.png'}).catch(()=>{})}throw error}finally{await browser.close()} })().catch(e=>{console.error(e);process.exitCode=1});