20 lines
3.0 KiB
Python
20 lines
3.0 KiB
Python
|
|
"""Comprueba el control PNG compartido mediante el navegador MCP de la auditoría aislada."""
|
|||
|
|
import base64
|
|||
|
|
import json
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
|
|||
|
|
def assert_list_icons(client, code, selector='[data-software-product] img', minimum=1):
|
|||
|
|
code(client, "await page.locator(" + json.dumps(selector) + ").first().scrollIntoViewIfNeeded(); await page.waitForFunction(({selector,minimum})=>{const images=[...document.querySelectorAll(selector)].slice(0,minimum);return images.length===minimum&&images.every(image=>image.complete&&image.naturalWidth>0&&image.getAttribute('src').startsWith('data:image/png;base64,'));},{selector:" + json.dumps(selector) + ",minimum:" + str(minimum) + "}); if(await page.locator('body').innerText().then(text=>text.includes('data:image/png;base64,')))throw Error('Base64 visible como texto');")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def verify(client, code):
|
|||
|
|
icon = Path(__file__).resolve().parent.parent / 'apps/server/data/resource-icons/windows-11.png'
|
|||
|
|
encoded = base64.b64encode(icon.read_bytes()).decode('ascii')
|
|||
|
|
valid = "{name:'icon.png',mimeType:'image/png',buffer:Buffer.from(" + json.dumps(encoded) + ",'base64')}"
|
|||
|
|
code(client, "await page.getByLabel('Icono',{exact:true}).setInputFiles({name:'invalid.jpg',mimeType:'image/jpeg',buffer:Buffer.from('invalid')}); await page.getByText('Selecciona un PNG válido de hasta 512 × 512 píxeles y 2 MiB.',{exact:true}).waitFor(); if(await page.getByLabel('Icono',{exact:true}).evaluate(e=>e.checkValidity()))throw Error('Imagen inválida aceptada');")
|
|||
|
|
code(client, "await page.getByLabel('Icono',{exact:true}).setInputFiles(" + valid + "); await page.getByAltText('Vista previa de Icono',{exact:true}).waitFor(); await page.getByAltText('Vista previa de Icono',{exact:true}).scrollIntoViewIfNeeded(); await page.waitForFunction(()=>[...document.querySelectorAll('dialog img,[role=dialog] img')].some(e=>e.complete&&e.naturalWidth>0));")
|
|||
|
|
code(client, "await page.getByLabel('Icono',{exact:true}).setInputFiles({name:'corrupt.png',mimeType:'image/png',buffer:Buffer.from('invalid')}); await page.getByText('Selecciona un PNG válido de hasta 512 × 512 píxeles y 2 MiB.',{exact:true}).waitFor(); if(!await page.getByAltText('Vista previa de Icono',{exact:true}).count())throw Error('Se perdió el icono anterior'); await page.getByRole('button',{name:'Quitar imagen',exact:true}).focus(); await page.keyboard.press('Space'); await page.getByAltText('Vista previa de Icono',{exact:true}).waitFor({state:'detached'}); if(!await page.getByLabel('Icono',{exact:true}).evaluate(e=>e.checkValidity()))throw Error('Error no retirado');")
|
|||
|
|
code(client, "await page.getByLabel('Icono',{exact:true}).setInputFiles(" + valid + "); await page.getByAltText('Vista previa de Icono',{exact:true}).waitFor(); if(!await page.getByLabel('Icono',{exact:true}).evaluate(e=>e.checkValidity()))throw Error('PNG válido bloqueado');")
|
|||
|
|
return ['png-upload-preview', 'invalid-format-blocked', 'invalid-png-blocked', 'previous-image-preserved', 'remove-with-keyboard', 'replace-png']
|