74 lines
5.5 KiB
JavaScript
74 lines
5.5 KiB
JavaScript
// Run against a built frontend with PLAYWRIGHT_MODULE pointing to an installed Playwright package.
|
|
// All API calls are isolated fixtures; no real account or application data is used.
|
|
import assert from 'node:assert/strict'
|
|
const { chromium } = await import(process.env.PLAYWRIGHT_MODULE || 'playwright')
|
|
const base = process.env.TIME_V2_FRONTEND_URL || 'http://127.0.0.1:3148'
|
|
const browser = await chromium.launch({headless:true})
|
|
const page = await browser.newPage({viewport:{width:1440,height:1100}})
|
|
const errors = []
|
|
page.on('pageerror',e => errors.push(e.message))
|
|
const user = '11111111-1111-4111-8111-111111111111'
|
|
const month = new Date().toISOString().slice(0,7)
|
|
const start = `${month}-01T06:00:00.000Z`
|
|
let item = {id:'22222222-2222-4222-8222-222222222222',user_id:user,type:'work',description:'Test Anwesenheit',started_at:start,
|
|
ended_at:`${month}-01T14:30:00.000Z`,date_from:null,date_to:null,timezone:'Europe/Berlin',status:'factual',version:1,
|
|
breaks:[{started_at:`${month}-01T10:00:00.000Z`,ended_at:`${month}-01T10:30:00.000Z`}],projects:[]}
|
|
const profile={id:user,user_id:user,full_name:'Anna Beispiel',first_name:'Anna',last_name:'Beispiel',pinned_on_navigation:[],temp_config:{},role:{rights:[]}}
|
|
const tenant={id:1,name:'Testbetrieb',extraModules:[],features:{},locked:'none'}
|
|
const commands=[]
|
|
await page.addInitScript(() => localStorage.setItem('token','fixture-only'))
|
|
await page.route('**/*',async route => {
|
|
const url=new URL(route.request().url())
|
|
if(url.origin!==new URL(base).origin) return route.abort()
|
|
if(!url.pathname.startsWith('/api/') && !url.pathname.startsWith('/auth/')) return route.continue()
|
|
let body=[]
|
|
if(url.pathname==='/api/me') body={user:{id:user,email:'anna@example.test',is_admin:true},profile,permissions:[],tenants:[tenant],activeTenant:1}
|
|
else if(url.pathname==='/api/tenant') body=tenant
|
|
else if(url.pathname==='/api/tenant/profiles') body={data:[profile]}
|
|
else if(url.pathname==='/api/v2/time/context') body={profiles:[{...profile,activated_at:start}],projects:[{id:1,name:'Projekt Nord'}],permissions:{readAll:true,writeAll:true,approve:true,activate:true}}
|
|
else if(url.pathname==='/api/v2/time/spans') body={items:[item],active:item.ended_at ? null : item,account:{activated_at:start}}
|
|
else if(url.pathname==='/api/v2/time/evaluation') body={summary:{timeSpanWorkingMinutes:480,presenceMinutes:510,breakMinutes:30,sumWorkingMinutesApproved:480,sumWorkingMinutesSubmitted:480,saldoApproved:0,saldoSubmitted:0,sumVacationDays:0,sumSickDays:0,sumRecreationDays:0}}
|
|
else if(url.pathname==='/api/v2/time/commands') {
|
|
const data=route.request().postDataJSON();commands.push(data)
|
|
const c=data.command
|
|
if(c.action==='update') item={...item,...c.data,status:'factual',version:item.version+1}
|
|
else if(c.action==='submit') item={...item,status:'submitted',version:item.version+1}
|
|
else if(c.action==='approve') item={...item,status:'approved',version:item.version+1}
|
|
body=item
|
|
}
|
|
else if(url.pathname.endsWith('/history')) body=[{id:'history-1',span_id:item.id,actor_id:user,action:'create',reason:'',before_data:null,after_data:item,created_at:start}]
|
|
return route.fulfill({contentType:'application/json',body:JSON.stringify(body)})
|
|
})
|
|
try {
|
|
await page.goto(`${base}/v2/time`,{waitUntil:'networkidle'})
|
|
await page.getByRole('button',{name:'Manuell erfassen',exact:true}).waitFor()
|
|
await page.getByRole('button',{name:'Zeitstrahl',exact:true}).click()
|
|
await page.getByRole('img',{name:'Anwesenheit mit 1 Pausen'}).waitFor()
|
|
await page.getByRole('button',{name:'Bearbeiten',exact:true}).click()
|
|
await page.getByLabel('Beschreibung',{exact:true}).fill('Korrigierte Anwesenheit')
|
|
await page.getByLabel('Korrekturgrund',{exact:true}).fill('Notiz korrigiert')
|
|
await page.getByRole('button',{name:'Speichern',exact:true}).click()
|
|
await page.getByText('Zeit gespeichert.',{exact:true}).waitFor()
|
|
assert.equal(commands.at(-1).command.data.breaks.length,1)
|
|
assert.equal(commands.at(-1).command.version,1)
|
|
assert.equal(commands.at(-1).command.reason,'Notiz korrigiert')
|
|
await page.getByRole('button',{name:'Einreichen',exact:true}).click()
|
|
await page.getByRole('button',{name:'Genehmigen',exact:true}).click()
|
|
await page.getByRole('button',{name:'Verlauf',exact:true}).click()
|
|
await page.getByText('Verlauf ·',{exact:false}).waitFor()
|
|
await page.getByRole('button',{name:'Schließen',exact:true}).click()
|
|
await page.getByRole('button',{name:'Auswertung',exact:true}).click()
|
|
await page.getByText('Saldo genehmigt',{exact:true}).waitFor()
|
|
await page.screenshot({path:process.env.TIME_V2_SCREENSHOT_DESKTOP || '/tmp/fedeo-time-v2-desktop.png',fullPage:true})
|
|
await page.setViewportSize({width:390,height:844})
|
|
await page.getByRole('button',{name:'Meine Zeiten',exact:true}).click()
|
|
await page.getByRole('button',{name:'Manuell erfassen',exact:true}).click()
|
|
await page.getByLabel(/^Art/).selectOption('vacation')
|
|
await page.getByLabel('Ganztägig',{exact:true}).check()
|
|
await page.getByLabel('Erster Tag',{exact:true}).waitFor()
|
|
await page.screenshot({path:process.env.TIME_V2_SCREENSHOT_MOBILE || '/tmp/fedeo-time-v2-mobile.png',fullPage:true})
|
|
assert.equal(await page.evaluate(() => document.documentElement.scrollWidth>window.innerWidth),false,'Mobile layout overflows')
|
|
assert.deepEqual(errors,[],'Browser runtime errors')
|
|
console.log('Time 2.0 browser checks passed: editing with pauses, submission, approval, history, evaluation, mobile absence form.')
|
|
} catch (error) { await page.screenshot({path:'/tmp/fedeo-time-v2-error.png',fullPage:true}); throw error } finally {await browser.close()}
|