const { chromium, } = require('C:/Users/macbook/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright'); const fs = require('node:fs'), assert = require('node:assert/strict'), zlib = require('node:zlib'); const base = 'http://127.0.0.1:18096', dir = 'storage/app/private/investmoz-v2/'; function png() { function crc(bytes) { let c = 0xffffffff; for (const b of bytes) { c ^= b; for (let i = 0; i < 8; i++) c = (c >>> 1) ^ (c & 1 ? 0xedb88320 : 0); } return (c ^ 0xffffffff) >>> 0; } function chunk(name, bytes) { const n = Buffer.from(name), body = Buffer.concat([n, bytes]), head = Buffer.alloc(4), tail = Buffer.alloc(4); head.writeUInt32BE(bytes.length); tail.writeUInt32BE(crc(body)); return Buffer.concat([head, body, tail]); } const hdr = Buffer.alloc(13); hdr.writeUInt32BE(500, 0); hdr.writeUInt32BE(500, 4); hdr[8] = 8; hdr[9] = 2; return Buffer.concat([ Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]), chunk('IHDR', hdr), chunk('IDAT', zlib.deflateSync(Buffer.alloc(500 * 1501))), chunk('IEND', Buffer.alloc(0)), ]); } (async () => { const browser = await chromium.launch({ headless: true, executablePath: 'C:/Users/macbook/AppData/Local/ms-playwright/chromium-1243/chrome-win64/chrome.exe', }); const errors = []; async function session(viewport) { const context = await browser.newContext({ viewport }); await context.route('**/*', (r) => r.request().url().startsWith(base) || r.request().url().startsWith('data:') ? r.continue() : r.abort(), ); const page = await context.newPage(); page.on('pageerror', (e) => errors.push(e.message)); await page.goto(base + '/login'); await page .getByLabel('Email address') .fill('opportunity-manager@example.invalid'); await page .getByLabel('Password', { exact: true }) .fill('Opportunity-QA-2026!'); await page.getByRole('button', { name: 'Log in', exact: true }).click(); await page.waitForURL('**/dashboard'); return { context, page }; } const desktop = await session({ width: 1280, height: 900 }), page = desktop.page; await page .getByRole('link', { name: 'Gestão de Oportunidades', exact: true }) .click(); await page .getByRole('link', { name: 'Nova oportunidade', exact: true }) .click(); await page .getByLabel('Motivo da alteração') .fill('Criação de recursos somente na cópia QA'); await page .getByRole('button', { name: 'Guardar rascunho', exact: true }) .click(); await page.waitForURL(/\/opportunities\/\d+\/edit$/); const id = Number(page.url().match(/(\d+)\/edit$/)[1]); assert(id > 6); await page .getByRole('link', { name: 'Imagens, documentos e localizações', exact: true, }) .click(); await page.waitForURL('**/resources'); await page .getByLabel('Título', { exact: true }) .fill('QA production location'); await page .getByLabel('Papel da localização', { exact: true }) .selectOption('production'); const provinceSelect = page.getByLabel('Província', { exact: true }); await provinceSelect .locator('option') .nth(1) .waitFor({ state: 'attached' }); const province = await provinceSelect .locator('option') .nth(1) .getAttribute('value'); await provinceSelect.selectOption(province); const districtSelect = page.getByLabel('Distrito', { exact: true }); await districtSelect .locator('option') .nth(1) .waitFor({ state: 'attached' }); const district = await districtSelect .locator('option') .nth(1) .getAttribute('value'); await districtSelect.selectOption(district); await page.getByLabel('Distribuição (%)', { exact: true }).fill('60'); await page.getByLabel('Localização principal', { exact: true }).check(); await page .getByLabel('Motivo (20–1000 caracteres)') .fill('Localização e distribuição declaradas em QA'); await page .getByRole('button', { name: 'Guardar recurso', exact: true }) .click(); await page .locator('article') .filter({ hasText: 'QA production location' }) .waitFor(); await page.getByLabel('Título', { exact: true }).fill('QA market location'); await page .getByLabel('Papel da localização', { exact: true }) .selectOption('market'); await provinceSelect.selectOption(province); await districtSelect .locator('option') .nth(1) .waitFor({ state: 'attached' }); await districtSelect.selectOption(district); await page.getByLabel('Distribuição (%)', { exact: true }).fill('40'); await page .getByRole('button', { name: 'Guardar recurso', exact: true }) .click(); await page .locator('article') .filter({ hasText: 'QA market location' }) .waitFor(); assert.equal(await page.locator('article').count(), 2); await page.getByRole('button', { name: 'Documentos', exact: true }).click(); await page.getByLabel('Título', { exact: true }).fill('QA source document'); await page .getByLabel('Original / substituir por nova versão') .setInputFiles({ name: 'qa.pdf', mimeType: 'application/pdf', buffer: Buffer.from('%PDF-1.7\nSynthetic QA document\n%%EOF'), }); await page .getByRole('button', { name: 'Guardar recurso', exact: true }) .click(); await page .locator('article') .filter({ hasText: 'QA source document' }) .waitFor(); await page.getByRole('button', { name: 'Imagens', exact: true }).click(); await page.getByLabel('Título', { exact: true }).fill('QA synthetic image'); await page .getByLabel('Legenda', { exact: true }) .fill('Synthetic image only used in isolated QA'); await page .getByLabel('Texto alternativo', { exact: true }) .fill('Black square generated for isolated QA'); await page .getByLabel('Direitos de utilização', { exact: true }) .selectOption('owned'); await page .getByLabel('Original / substituir por nova versão') .setInputFiles({ name: 'qa.png', mimeType: 'image/png', buffer: png(), }); await page .getByRole('button', { name: 'Guardar recurso', exact: true }) .click(); const imageArticle = page .locator('article') .filter({ hasText: 'QA synthetic image' }); await imageArticle.waitFor(); await imageArticle .getByRole('button', { name: 'Ver / editar / restaurar' }) .click(); const prepareButton = page.getByRole('button', { name: 'Preparar WebP e miniaturas', }); if (await prepareButton.isDisabled()) { await page.getByText(/Processamento de imagens indisponível/).waitFor(); } else { await prepareButton.click(); await page.getByText(/Scan do original pendente ou inseguro/).waitFor(); } assert.equal( await page.getByLabel('Título', { exact: true }).inputValue(), 'QA synthetic image', ); await page.screenshot({ path: dir + 'opportunity-resources-desktop.png', fullPage: true, }); await desktop.context.close(); const mobile = await session({ width: 390, height: 844 }), mp = mobile.page; await mp.goto(base + `/management/opportunities/${id}/resources`); await mp.evaluate(() => localStorage.clear()); await mp.reload(); assert.equal(await mp.locator('article').count(), 2); await mp.getByRole('button', { name: 'Imagens', exact: true }).click(); const mi = mp.locator('article').filter({ hasText: 'QA synthetic image' }); await mi.getByRole('button', { name: 'Ver / editar / restaurar' }).click(); assert.equal( await mp.getByLabel('Texto alternativo', { exact: true }).inputValue(), 'Black square generated for isolated QA', ); await mp .getByLabel('Motivo (20–1000 caracteres)') .fill('Exclusão lógica de imagem somente no ensaio QA'); await mp.getByLabel('Confirmar exclusão lógica / restauração').check(); await mp .getByRole('button', { name: 'Excluir recurso logicamente' }) .click(); await mp .getByText('eliminado logicamente', { exact: false }) .first() .waitFor(); await mi.getByRole('button', { name: 'Ver / editar / restaurar' }).click(); await mp.getByLabel('Confirmar exclusão lógica / restauração').check(); await mp.getByRole('button', { name: 'Restaurar recurso' }).click(); await mi.getByText(/rascunho/).waitFor(); await mp.screenshot({ path: dir + 'opportunity-resources-mobile.png', fullPage: true, }); assert( await mp.evaluate( () => document.documentElement.scrollWidth <= innerWidth + 1, ), ); assert.deepEqual(errors, []); const proof = { recorded_at: new Date().toISOString(), id, desktop: true, mobile: true, new_session_recovery: true, multiple_locations: true, documents: true, images: true, scan_failure_visible: true, soft_delete_restore: true, errors, active_writes: 0, }; fs.writeFileSync( dir + 'opportunity-resources-browser.json', JSON.stringify(proof, null, 2), ); console.log(JSON.stringify(proof)); await browser.close(); })().catch((e) => { console.error(e); process.exit(1); });