Merge branch 'main' into docs/dns-page-rework
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Email capture — the customer "Mail Client Setup" section on the Email page.
|
||||
*
|
||||
* Captures, as the demo customer:
|
||||
* - whp-email-autodiscovery.png the Mail Client Setup accordion section,
|
||||
* expanded, with the per-domain autodiscovery
|
||||
* DNS records table + copyable zone block.
|
||||
*
|
||||
* Viewport-only (1440x900), redacted for our multi-server fleet: the mail-server
|
||||
* hostname becomes a neutral placeholder, while the brand demo domain
|
||||
* (whp-demo.anhh.co) is kept visible on purpose.
|
||||
*
|
||||
* Read-only: expands an accordion section for the screenshot, never saves.
|
||||
*/
|
||||
import { chromium, type Page } from 'playwright';
|
||||
import { mkdir } from 'node:fs/promises';
|
||||
import { resolve, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const OUT_DIR = resolve(__dirname, '../../src/assets/screenshots/whp');
|
||||
|
||||
function need(name: string): string {
|
||||
const v = process.env[name];
|
||||
if (!v) throw new Error(`missing env: ${name}`);
|
||||
return v;
|
||||
}
|
||||
|
||||
const BASE = need('WHP_BASE');
|
||||
const USER = need('WHP_USER');
|
||||
const PASS = need('WHP_PASS');
|
||||
|
||||
const HIDE_CSS = `.navbar-text, .brand-full { visibility: hidden !important; }`;
|
||||
|
||||
async function login(page: Page) {
|
||||
await page.goto(`${BASE}/login.php`, { waitUntil: 'domcontentloaded' });
|
||||
await page.fill('input[name="user"]', USER);
|
||||
await page.fill('input[name="password"]', PASS);
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForLoadState('networkidle');
|
||||
}
|
||||
|
||||
/**
|
||||
* Neutralise fleet-identifying text before the screenshot. The brand demo
|
||||
* domain (anhh.co) is intentionally preserved; the mail-server host and any
|
||||
* server hostnames/IPs are swapped for placeholders.
|
||||
*/
|
||||
async function redact(page: Page) {
|
||||
await page.addStyleTag({ content: HIDE_CSS });
|
||||
await page.evaluate(() => {
|
||||
const swaps: [RegExp, string][] = [
|
||||
[/mail\d+\.cloud-hosting\.io/gi, '<mail-server>.cloud-hosting.io'],
|
||||
[/whp\d+(-[a-z0-9]+)?\.cloud-hosting\.io/gi, '<your-server>.cloud-hosting.io'],
|
||||
[/WHP\d+(-[A-Z0-9]+)?\b/g, '<YOUR-SERVER>'],
|
||||
[/whp\d+(-[a-z0-9]+)?\b/gi, '<your-server>'],
|
||||
[/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g, '<server-IP>'],
|
||||
];
|
||||
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
||||
const nodes: Text[] = [];
|
||||
let n: Node | null = walker.nextNode();
|
||||
while (n) { nodes.push(n as Text); n = walker.nextNode(); }
|
||||
for (const node of nodes) {
|
||||
let v = node.nodeValue ?? '';
|
||||
for (const [re, rep] of swaps) v = v.replace(re, rep);
|
||||
if (v !== node.nodeValue) node.nodeValue = v;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await mkdir(OUT_DIR, { recursive: true });
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const ctx = await browser.newContext({
|
||||
ignoreHTTPSErrors: true,
|
||||
viewport: { width: 1440, height: 900 },
|
||||
deviceScaleFactor: 2,
|
||||
});
|
||||
const page = await ctx.newPage();
|
||||
try {
|
||||
await login(page);
|
||||
await page.goto(`${BASE}/index.php?page=email-management`, { waitUntil: 'networkidle' });
|
||||
|
||||
// Expand the (collapsed-by-default) "Mail Client Setup" accordion section.
|
||||
await page.locator('button[data-bs-target="#mail-client-setup"]').click();
|
||||
await page.waitForSelector('#custMailDnsDomain', { state: 'visible' });
|
||||
// The zone <pre> is populated on DOMContentLoaded; re-run to be safe.
|
||||
await page.evaluate(() => {
|
||||
const fn = (window as unknown as { renderCustMailDns?: () => void }).renderCustMailDns;
|
||||
if (typeof fn === 'function') fn();
|
||||
});
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await redact(page);
|
||||
const item = page.locator('#mail-client-setup').locator('xpath=ancestor::div[contains(@class,"accordion-item")]');
|
||||
await item.scrollIntoViewIfNeeded();
|
||||
await page.waitForTimeout(300);
|
||||
const path = resolve(OUT_DIR, 'whp-email-autodiscovery.png');
|
||||
await item.screenshot({ path });
|
||||
console.log(`captured whp-email-autodiscovery -> ${path}`);
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => { console.error(err); process.exit(1); });
|
||||
Reference in New Issue
Block a user