test(ci): add exporter heading levels and a11y typography smoke; update MAIN_PLAN
CI / test (pull_request) Has been cancelled
CI / test (pull_request) Has been cancelled
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import JSZip from 'jszip'
|
||||
|
||||
const builderUrl = '/en/builder'
|
||||
type WindowWithExport = Window & {
|
||||
__captureExport?: boolean
|
||||
__lastExport?: { html: string; css: string; js: string }
|
||||
__lastBlob?: Blob
|
||||
__exportPreview?: () => { html: string; css: string; js: string }
|
||||
}
|
||||
|
||||
test('Export ZIP contains expected SEO/OG/Analytics meta in index.html', async ({ page }) => {
|
||||
await page.goto(builderUrl)
|
||||
// enable capture hook in app
|
||||
await page.evaluate(() => {
|
||||
const w = window as unknown as WindowWithExport
|
||||
w.__captureExport = true
|
||||
w.__lastBlob = undefined
|
||||
})
|
||||
|
||||
// set SEO/Analytics/OG values
|
||||
await page.getByLabel('SEO Title').fill('E2E SEO Title')
|
||||
await page.getByLabel('SEO Description').fill('E2E SEO Description')
|
||||
await page.getByLabel('OG Image URL').fill('https://example.com/e2e-og.png')
|
||||
await page.getByLabel('GA4 Measurement ID').fill('G-E2E1234567')
|
||||
await page.getByLabel('Meta Pixel ID').fill('9876543210')
|
||||
|
||||
// Prefer calling exporter directly for deterministic output
|
||||
const exported = await page.evaluate(() => (window as unknown as WindowWithExport).__exportPreview?.() ?? null)
|
||||
let indexHtml: string | null = exported?.html ?? null
|
||||
|
||||
// Fallback: also click Export to exercise button and capture via test hook
|
||||
if (!indexHtml) {
|
||||
await page.getByRole('button', { name: /Export/i }).click()
|
||||
await page.waitForFunction(() => {
|
||||
const w = window as unknown as WindowWithExport
|
||||
return Boolean(w.__lastExport || w.__lastBlob)
|
||||
}, { timeout: 20000 })
|
||||
const exp2 = await page.evaluate(() => (window as unknown as WindowWithExport).__lastExport ?? null)
|
||||
indexHtml = exp2?.html ?? null
|
||||
}
|
||||
|
||||
// if not present, fall back to reading from ZIP blob (slower)
|
||||
if (!indexHtml) {
|
||||
await page.waitForFunction(() => Boolean((window as unknown as WindowWithExport).__lastBlob), { timeout: 20000 })
|
||||
const base64 = await page.evaluate(async () => {
|
||||
const blob: Blob | undefined = (window as unknown as WindowWithExport).__lastBlob
|
||||
if (!blob) return null
|
||||
const ab = await blob.arrayBuffer()
|
||||
const bytes = new Uint8Array(ab)
|
||||
return btoa(String.fromCharCode(...bytes))
|
||||
})
|
||||
expect(base64, 'export blob should be captured').not.toBeNull()
|
||||
const buf = Buffer.from(base64 as string, 'base64')
|
||||
const zip = await JSZip.loadAsync(buf)
|
||||
const index = zip.file('index.html')
|
||||
expect(index, 'index.html exists in zip').toBeTruthy()
|
||||
indexHtml = await index!.async('string')
|
||||
}
|
||||
// assert we have HTML
|
||||
expect(indexHtml).not.toBeNull()
|
||||
|
||||
// assertions: language, title/description, og tags, GA4 id presence
|
||||
expect(indexHtml!).toContain('<html lang="en">')
|
||||
expect(indexHtml!).toContain('<meta name="description" content="E2E SEO Description" />')
|
||||
expect(indexHtml!).toContain('<meta property="og:title" content="E2E SEO Title" />')
|
||||
expect(indexHtml!).toContain('<meta property="og:description" content="E2E SEO Description" />')
|
||||
expect(indexHtml!).toContain('<meta property="og:image" content="https://example.com/e2e-og.png" />')
|
||||
expect(indexHtml!).toContain('G-E2E1234567')
|
||||
expect(indexHtml!).toContain('9876543210')
|
||||
|
||||
// accessibility scaffolding in exported HTML
|
||||
expect(indexHtml!).toContain('<a href="#main" class="skip-link">')
|
||||
expect(indexHtml!).toContain('<main id="main" role="main">')
|
||||
})
|
||||
Reference in New Issue
Block a user