import { test, expect } from '@playwright/test'; import fs from 'node:fs'; import { adminPath, apiList, ensureDataSource, ensureMailshot, cleanupByNames } from './helpers.mjs'; const mailshotPurpose = process.env.E2E_RENEWAL_MAILSHOT_PURPOSE || 'Renewals (pending accounts and contacts)'; const allowCreate = process.env.E2E_RENEWAL_ALLOW_CREATE !== '0'; const runEnabled = process.env.E2E_RENEWAL_ENABLE === '1'; const fallbackPdfTemplate = '
Download PDF test
'; test.describe('renewal dataset: download pdf e2e', () => { test.skip(!runEnabled, 'Enable with E2E_RENEWAL_ENABLE=1'); const clickAndExpectDownload = async (page, buttonName, expectedFilenamePart) => { page.once('dialog', async (dialog) => { await dialog.accept(); }); let downloaded; try { const out = await Promise.all([ page.waitForEvent('download', { timeout: 90000 }), page.getByRole('button', { name: buttonName }).click() ]); downloaded = out[0] || null; } catch { const critical = page.getByText('There has been a critical error on this website.'); if (await critical.count()) { throw new Error(`Download action "${buttonName}" reached a WordPress critical error page.`); } const failBanner = page.locator('strong', { hasText: 'PDF generation failed.' }); if (await failBanner.count()) { const msg = (await page.locator('.wrap').innerText()).replace(/\s+/g, ' ').trim(); throw new Error(`Download action "${buttonName}" failed in UI: ${msg}`); } throw new Error(`Download action "${buttonName}" timed out waiting for file download.`); } if (!downloaded) { const critical = page.getByText('There has been a critical error on this website.'); if (await critical.count()) { throw new Error(`Download action "${buttonName}" reached a WordPress critical error page.`); } const failBanner = page.locator('strong', { hasText: 'PDF generation failed.' }); if (await failBanner.count()) { const msg = (await page.locator('.wrap').innerText()).replace(/\s+/g, ' ').trim(); throw new Error(`Download action "${buttonName}" failed in UI: ${msg}`); } throw new Error(`Download action "${buttonName}" timed out waiting for file download.`); } expect(downloaded.suggestedFilename()).toContain(expectedFilenamePart); const outPath = await downloaded.path(); expect(outPath).toBeTruthy(); const outSize = fs.statSync(outPath).size; expect(outSize).toBeGreaterThan(1000); }; const resolveMailshot = async (request) => { const uniq = `${Date.now()}_${Math.floor(Math.random() * 100000)}`; const purpose = `e2e_renewal_download_${uniq}`; const dsCreatedName = `e2e_renewal_ds_${uniq}`; if (!allowCreate) { const mailshotList = await apiList(request, 'feca_mailshots_mailshots_api'); expect(mailshotList.ok).toBeTruthy(); const existing = (mailshotList.items || []).find( (row) => String(row.Purpose || '') === mailshotPurpose ); if (!existing) { throw new Error(`Required mailshot not found: ${mailshotPurpose}`); } const existingId = String(existing.id || ''); expect(existingId).not.toBe(''); return { mailshotId: existingId, cleanup: async () => {} }; } await ensureDataSource(request, dsCreatedName, 'contacts'); const saved = await ensureMailshot(request, { Purpose: purpose, DataSource: dsCreatedName, CC: '', BCC: '', Subject: 'Renewal PDF e2e', Message: '', PDFAttachment: fallbackPdfTemplate, AttachmentNames: '[]', PDFFilenameDerivedFrom: '', RecipientEmailField: '', ReplyTo: '' }); let mailshotId = String(saved.id || ''); expect(mailshotId).not.toBe(''); return { mailshotId, cleanup: async () => { await cleanupByNames(request, { dataSourceNames: [dsCreatedName], mailshotPurposes: [purpose] }); } }; }; test('downloads merged PDF for renewal_accounts_with_contacts', async ({ page, request }) => { const resolved = await resolveMailshot(request); try { await page.goto(`${adminPath('feca-mailshots-download-pdf')}&mailshot_id=${encodeURIComponent(resolved.mailshotId)}`); await expect(page.getByRole('heading', { name: 'Download PDF' })).toBeVisible(); await page.locator('#dp_mailshot_id').selectOption(resolved.mailshotId); await clickAndExpectDownload(page, 'Download Merged PDF', '_merged.pdf'); } finally { try { await resolved.cleanup(); } catch { // best effort cleanup } } }); test('downloads ZIP of PDFs for renewal_accounts_with_contacts', async ({ page, request }) => { const resolved = await resolveMailshot(request); try { await page.goto(`${adminPath('feca-mailshots-download-pdf')}&mailshot_id=${encodeURIComponent(resolved.mailshotId)}`); await expect(page.getByRole('heading', { name: 'Download PDF' })).toBeVisible(); await page.locator('#dp_mailshot_id').selectOption(resolved.mailshotId); await clickAndExpectDownload(page, 'Download ZIP of PDFs', '_pdfs.zip'); } finally { try { await resolved.cleanup(); } catch { // best effort cleanup } } }); });