// Regenerate docs/images/*.png from a running ActivePush panel (Playwright). // node tools/dev/screenshots.js http://127.0.0.1:9091 admin 'password' [outdir] // With SETUP_TOKEN= in the environment the first-run screen is captured and the // administrator is created with the given credentials. const { chromium } = require('playwright'); const path = require('path'); (async () => { const [base, user, pass, out = path.join(__dirname, '../../docs/images')] = process.argv.slice(2); if (!base || !user || !pass) { console.error('usage: node screenshots.js URL USER PASSWORD [OUTDIR]'); process.exit(2); } const browser = await chromium.launch(); const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, locale: 'en-US', deviceScaleFactor: 1 }); const page = await ctx.newPage(); const errors = []; page.on('pageerror', (e) => errors.push(e.message)); const shot = async (name, full = false) => { await page.screenshot({ path: path.join(out, `${name}.png`), fullPage: full }); console.log('saved', name); }; await page.goto(base + '/'); await page.waitForSelector('#auth:not([hidden])'); if (process.env.SETUP_TOKEN) { await page.fill('#setup-token', process.env.SETUP_TOKEN); await page.fill('#username', user); await shot('setup'); await page.fill('#password', pass); await page.fill('#password2', pass); } else { await page.fill('#username', user); await page.fill('#password', pass); } await page.click('#auth-submit'); await page.waitForSelector('#shell:not([hidden])'); const pages = [ ['overview', true, 5000], ['live', false, 6000], ['devices', false, 2500], ['users', false, 2500], ['backends', false, 1500], ['activesync', false, 1500], ['policies', false, 1500], ['security', false, 1500], ['logs', false, 4000], ]; for (const [id, full, wait] of pages) { await page.goto(`${base}/#${id}`); await page.waitForTimeout(wait); await shot(id === 'users' ? 'mailboxes' : id, full); } await page.goto(`${base}/#devices`); await page.waitForTimeout(2000); const chips = await page.$$('.chip[data-pid]'); if (chips.length) { await chips[0].click(); await page.waitForTimeout(1200); await shot('device'); } await page.goto(`${base}/#overview`); await page.waitForTimeout(500); await page.click('#theme'); await page.waitForTimeout(4000); await shot('overview-light'); await page.click('#theme'); const mobile = await browser.newContext({ viewport: { width: 390, height: 844 }, locale: 'en-US', deviceScaleFactor: 2, storageState: await ctx.storageState() }); const mp = await mobile.newPage(); await mp.goto(`${base}/#overview`); await mp.waitForTimeout(4000); await mp.screenshot({ path: path.join(out, 'mobile.png') }); console.log('saved mobile'); if (errors.length) console.error('page errors:', errors); await browser.close(); })();