feat: account sessions and usable template editors

This commit is contained in:
Pigway
2026-10-02 08:43:07 +08:00
parent 186b56c495
commit 141849d682
12 changed files with 515 additions and 33 deletions
+4 -5
View File
@@ -5,7 +5,7 @@ const fs=require('fs');const path=require('path');const assert=require('assert')
const base=process.env.FRAME_FLOW_URL||'http://127.0.0.1:18787';const response=await fetch(base+'/api/v1/settings',{headers:{Authorization:'Bearer '+token}});const settings=await response.json();assert(settings.mock===true,'UI smoke requires Mock mode');
const browser=await chromium.launch({headless:true,executablePath:'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'});
const context=await browser.newContext({viewport:{width:1440,height:1000}});const page=await context.newPage();const errors=[];page.on('pageerror',e=>errors.push(e.message.replaceAll(token,'[REDACTED]')));let checks=0;
await page.addInitScript(()=>Object.defineProperty(window.crypto,'randomUUID',{value:undefined,configurable:true}));await page.goto(base);await page.locator('#api-token').fill(token);await page.locator('#login-form button').click();await page.locator('.hero').waitFor();assert(await page.locator('h2').first().innerText()==='客厅相框');checks++;
await page.addInitScript(()=>Object.defineProperty(window.crypto,'randomUUID',{value:undefined,configurable:true}));await page.goto(base);await page.locator('#username').fill(process.env.FRAME_FLOW_TEST_USERNAME);await page.locator('#password').fill(process.env.FRAME_FLOW_TEST_PASSWORD);await page.locator('#login-form button').click();await page.locator('.hero').waitFor();assert(await page.locator('h2').first().innerText()==='客厅相框');checks++;
const shots=process.env.FRAME_FLOW_SCREENSHOT_DIR||path.join(root,'docs/screenshots');fs.mkdirSync(shots,{recursive:true});await page.screenshot({path:path.join(shots,'dashboard-light-zh.png'),fullPage:true});
await page.locator('#lang').click();await page.getByRole('heading',{name:'Dashboard',exact:true}).waitFor();checks++;
await page.locator('#theme').click();assert(await page.locator('html').getAttribute('data-theme')==='dark');checks++;
@@ -18,7 +18,7 @@ const fs=require('fs');const path=require('path');const assert=require('assert')
await uploaded.locator('[data-delete]').click();await page.locator('#modal-confirm').click();await uploaded.waitFor({state:'hidden'});checks++;
await page.locator('[data-page="templates"]').click();await page.locator('.template-card').first().waitFor();assert(await page.locator('.template-card').count()===6);checks++;
await page.locator('#render-template').click();await page.locator('#template-image').waitFor({timeout:30000});assert(await page.locator('#display-template').isEnabled());checks++;
await page.locator('#display-template').click();await page.locator('[data-page="history"]').click();await page.locator('tbody tr').first().waitFor();checks++;
await page.locator('#field-title').fill('Edited title');assert(await page.locator('#display-template').isDisabled());checks++;await page.locator('#save-template').click();await page.reload();await page.locator('#field-title').waitFor();assert(await page.locator('#field-title').inputValue()==='Edited title');checks++;await page.locator('#reset-template').click();await page.locator('#modal-confirm').click();await page.waitForFunction(()=>document.querySelector('#field-title')?.value!=='Edited title'&&document.querySelector('#field-title'));assert(await page.locator('#field-title').inputValue()!=='Edited title');checks++;await page.locator('#render-template').click();await page.locator('#template-image').waitFor();await page.locator('#display-template').click();await page.locator('[data-page="history"]').click();await page.locator('tbody tr').first().waitFor();checks++;
await page.locator('[data-page="automation"]').click();await page.locator('#new-job').click();await page.locator('#job-name').fill('UI acceptance');await page.locator('#job-form button[type=submit]').click();await page.locator('td strong').filter({hasText:'UI acceptance'}).waitFor();checks++;
await page.locator('[data-job-toggle]').first().click();await page.getByText('Paused',{exact:true}).first().waitFor();checks++;
await page.locator('[data-job-delete]').first().click();await page.locator('#modal-confirm').click();await page.locator('td strong').filter({hasText:'UI acceptance'}).waitFor({state:'hidden'});checks++;
@@ -31,9 +31,8 @@ const fs=require('fs');const path=require('path');const assert=require('assert')
await page.reload();await page.locator('.hero').waitFor();checks++;
const reopened=await page.context().newPage();await reopened.goto(base);await reopened.locator('.hero').waitFor();await reopened.close();checks++;
await page.locator('[data-page="settings"]').click();await page.locator('#logout').click();await page.locator('#login-form').waitFor();assert(await page.evaluate(()=>localStorage.getItem('ff-login')===null));checks++;
await page.locator('#remember-login').uncheck();await page.locator('#api-token').fill(token);await page.locator('#login-form button').click();await page.locator('#logout').waitFor();await page.reload();await page.locator('#login-form').waitFor();checks++;
await page.evaluate(token=>localStorage.setItem('ff-login',JSON.stringify({token,expires_at:Date.now()-1})),token);await page.reload();await page.locator('#login-form').waitFor();assert(await page.evaluate(()=>localStorage.getItem('ff-login')===null));checks++;
await page.evaluate(()=>localStorage.setItem('ff-login',JSON.stringify({token:'test-invalid-frame-flow-token',expires_at:Date.now()+60000})));await page.reload();await page.locator('#login-form').waitFor();assert(await page.evaluate(()=>localStorage.getItem('ff-login')===null));checks++;
await page.locator('#remember-login').uncheck();await page.locator('#username').fill(process.env.FRAME_FLOW_TEST_USERNAME);await page.locator('#password').fill(process.env.FRAME_FLOW_TEST_PASSWORD);await page.locator('#login-form button').click();await page.locator('#logout').waitFor();await page.reload();await page.locator('#logout').waitFor();assert((await context.cookies()).find(c=>c.name==='frameflow_session').expires===-1);checks++;
assert(await page.evaluate(()=>!document.cookie.includes('frameflow_session')));checks++;
assert(errors.length===0,JSON.stringify(errors));checks++;
await browser.close();console.log('Browser smoke:',checks,'passed; page errors:',errors.length);
})().catch(error=>{console.error(error.message);process.exit(1)});