feat: publish CodexPi contest snapshot
Some checks are pending
Qualité / tests (push) Waiting to run

This commit is contained in:
CodexPi
2026-11-14 20:23:59 +01:00
commit 995b17a6e2
295 changed files with 36803 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
import AxeBuilder from '@axe-core/playwright'
import { expect, Page, test } from '@playwright/test'
const projects=[
{id:'project-tv',name:'TV Hub',path:'/home/tv-hub',owner_id:'owner',owner_username:'alice',kind:'local',archived:0,full_access:0,git_available:true,execution_group:'',groups:[]},
{id:'project-player',name:'Lecteur TV',path:'/home/tv-player',owner_id:'owner',owner_username:'alice',kind:'local',archived:0,full_access:0,git_available:true,execution_group:'',groups:[]},
{id:'project-remote',name:'Télécommande',path:'/home/tv-remote',owner_id:'owner',owner_username:'alice',kind:'local',archived:0,full_access:0,git_available:true,execution_group:'',groups:[]},
]
async function mockApi(page:Page){
let groups:any[]=[]
await page.route('**/api/**',async route=>{
const request=route.request(),url=new URL(request.url()),path=url.pathname,method=request.method()
let body:unknown={}
if(path==='/api/bootstrap')body={setup_required:false,csrf_token:'csrf'}
else if(path==='/api/auth/me')body={username:'alice',is_admin:true,csrf_token:'csrf'}
else if(path==='/api/projects'&&url.searchParams.get('archived')==='true')body=[]
else if(path==='/api/projects')body=projects
else if(path==='/api/projects/activity')body={running_project_ids:['project-player']}
else if(path==='/api/application/preferences')body={auto_compact_context:false,interface_type:'dashboard',theme:'dark'}
else if(path==='/api/duck/preferences')body={enabled:true,reminder_minutes:30}
else if(path==='/api/activity')body={cards:[],counts:{running:0,waiting:0,review:0},observed_at:'2026-11-12T20:00:00Z'}
else if(path==='/api/dashboard')body={connected:true,hostname:'NasPi',platform:'Linux',cpu_percent:17,cpu_count:4,ram_percent:42,ram_used:4_000_000_000,ram_total:8_000_000_000,temperature_c:48,disk_percent:55,disk_used:55_000_000_000,disk_total:100_000_000_000,uptime_seconds:86400,active_sessions:1,total_sessions:3,docker:{available:true,version:'27'},codex:{available:true,version:'1'},git:{available:true,version:'2.47'},codex_quota:{available:false}}
else if(path==='/api/project-groups'&&method==='GET')body=groups
else if(path==='/api/project-groups'&&method==='POST'){
const input=request.postDataJSON()
groups=[{id:'group-tv',key:'tv',owner_id:'owner',owner_username:'alice',name:input.name,description:input.description,member_count:input.project_ids.length,members:projects.filter(item=>input.project_ids.includes(item.id)),updates:[],created_at:'2026-11-12T20:00:00Z',updated_at:'2026-11-12T20:00:00Z'}]
body=groups[0]
}else if(path==='/api/search')body=[]
return route.fulfill({status:200,contentType:'application/json',body:JSON.stringify(body)})
})
}
test.beforeEach(async({page})=>{
await mockApi(page)
await page.goto('/?view=company')
await expect(page.getByRole('heading',{name:'Qui fait quoi ?'})).toBeVisible()
})
test('crée un groupe à partir de plusieurs projets existants',async({page})=>{
await page.getByRole('button',{name:'+ Groupe'}).first().click()
await page.getByLabel('Nom du groupe').fill('TV')
await page.getByLabel('Objectif commun').fill('Applications qui communiquent avec la télévision.')
await page.locator('label').filter({hasText:'TV Hub'}).click()
await page.locator('label').filter({hasText:'Lecteur TV'}).click()
const requestPromise=page.waitForRequest(request=>request.url().endsWith('/api/project-groups')&&request.method()==='POST')
await page.getByRole('button',{name:'Créer le groupe'}).click()
const request=await requestPromise
expect(request.postDataJSON().project_ids.sort()).toEqual(['project-player','project-tv'])
await expect(page.locator('.company-groups article>header b').filter({hasText:/^TV$/})).toBeVisible()
})
test('conserve la vue dans l’URL, au retour et au rechargement',async({page})=>{
await page.getByRole('button',{name:'Projets',exact:true}).click()
await expect(page).toHaveURL(/view=dashboard/)
await expect(page.getByRole('heading',{name:'Projets et chefs d’équipe'})).toBeVisible()
await page.goBack()
await expect(page).toHaveURL(/view=company/)
await page.reload()
await expect(page.getByRole('heading',{name:'Qui fait quoi ?'})).toBeVisible()
})
test('le lanceur est utilisable au clavier et la vue ne présente pas de violation axe sérieuse',async({page})=>{
await page.keyboard.press('Control+K')
const dialog=page.getByRole('dialog',{name:'Rechercher et ouvrir'})
await expect(dialog).toBeVisible()
await page.keyboard.press('Escape')
await expect(dialog).toBeHidden()
const results=await new AxeBuilder({page}).withTags(['wcag2a','wcag2aa','wcag21a','wcag21aa']).analyze()
expect(results.violations.filter(item=>item.impact==='critical'||item.impact==='serious')).toEqual([])
})
test('capture la vue Organisation de référence',async({page})=>{
await expect(page).toHaveScreenshot('organisation.png',{fullPage:true})
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB