// Authenticated read-only browser verification; credentials stay in the ignored local file. const fs = require('node:fs'); const path = require('node:path'); const assert = require('node:assert/strict'); const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright'); const repo = path.resolve(__dirname, '..'); const account = JSON.parse(fs.readFileSync(path.join(repo, '.secrets/ikar-admin-access.json'), 'utf8').replace(/^\uFEFF/, '')); (async () => { const browser = await chromium.launch({headless: true, executablePath: process.env.ADMIN_BROWSER || 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe', args: ['--host-resolver-rules=MAP ikar.kusoft.xyz 195.216.241.165']}); try { const context = await browser.newContext({viewport: {width: 1440, height: 1000}}); const page = await context.newPage(); page.setDefaultTimeout(15000); const errors = []; page.on('pageerror', error => errors.push(error.message)); await page.goto(account.url); await page.locator('#loginUsername').fill(account.username); await page.locator('#loginPassword').fill(account.password); await page.locator('#loginForm button').click(); await page.waitForFunction(() => document.querySelector('#usersCount').textContent.includes('пользователей')); assert.equal(await page.locator('#adminIdentity').textContent(), account.username); const cookie = (await context.cookies()).find(x => x.name === 'Ikar.Admin'); assert.ok(cookie && cookie.secure && cookie.httpOnly && cookie.sameSite === 'Strict'); await page.screenshot({path: path.join(repo, 'artifacts/admin-live-overview.png'), fullPage: true}); const sections = ['users', 'chats', 'media', 'reports', 'bots', 'moderation', 'audit', 'security', 'updates', 'operations']; for (const section of sections) { await page.locator(`.nav-item[data-section=${section}]`).click(); await page.waitForFunction(section => document.querySelector(`.section[data-panel=${section}]`).classList.contains('active'), section); if (section === 'security') await page.waitForFunction(() => document.querySelector('#securityContent').textContent.includes('Эта сессия')); if (section === 'updates') await page.waitForFunction(() => document.querySelector('#releasesContent').textContent.includes('1.0.4')); if (section === 'operations') await page.waitForFunction(() => document.querySelector('#operationsDetails').textContent.includes('Свободно на диске')); } assert.deepEqual(errors, []); await page.locator('#logoutButton').click(); await page.locator('#loginForm').waitFor({state: 'visible'}); const result = {passed: true, publicUrl: account.url, authenticatedBrowser: true, secureCookie: true, sections, browserErrors: errors, logout: true}; fs.writeFileSync(path.join(repo, 'artifacts/admin-public-ui-verification.json'), JSON.stringify(result, null, 2)); console.log(JSON.stringify(result)); } finally { await browser.close(); } })().catch(error => { console.error(error.message); process.exitCode = 1; });