import { test, expect } from '@playwright/test'; import { adminPath, ensureDataSource, cleanupByNames } from './helpers.mjs'; const setJoditHtml = async (page, html) => { await page.evaluate((nextHtml) => { const host = /** @type {any} */ (document.getElementById('ms-template-jodit')); const instances = (window.Jodit && window.Jodit.instances) ? window.Jodit.instances : null; let jodit = host && host.jodit ? host.jodit : null; if (!jodit && instances) { jodit = instances['ms-template-jodit'] || instances.ms_template_jodit || null; } if (!jodit && instances && typeof instances === 'object') { const vals = Array.isArray(instances) ? instances : Object.values(instances); jodit = vals.find((x) => x && x.container && x.container.isConnected) || null; } if (!jodit) { throw new Error('Jodit instance not available'); } if (typeof jodit.setEditorValue === 'function') { jodit.setEditorValue(nextHtml); } else { jodit.value = nextHtml; } if (typeof jodit.synchronizeValues === 'function') { jodit.synchronizeValues(); } }, html); }; const setJoditMode = async (page, modeName) => { await page.evaluate((nextModeName) => { const host = /** @type {any} */ (document.getElementById('ms-template-jodit')); const instances = (window.Jodit && window.Jodit.instances) ? window.Jodit.instances : null; let jodit = host && host.jodit ? host.jodit : null; if (!jodit && instances) { jodit = instances['ms-template-jodit'] || instances.ms_template_jodit || null; } if (!jodit && instances && typeof instances === 'object') { const vals = Array.isArray(instances) ? instances : Object.values(instances); jodit = vals.find((x) => x && x.container && x.container.isConnected) || null; } if (!jodit) { throw new Error('Jodit instance not available'); } const modeValue = nextModeName === 'wysiwyg' ? window.Jodit.MODE_WYSIWYG : window.Jodit.MODE_SOURCE; if (typeof jodit.setMode !== 'function') { throw new Error('Jodit setMode is unavailable'); } jodit.setMode(modeValue); }, modeName); }; test('mailshots editor: datasource-driven options + overlay editors + create', async ({ page, request }) => { const uniq = `${Date.now()}_${Math.floor(Math.random() * 100000)}`; const dsName = `e2e_ms_ds_${uniq}`; const purpose = `e2e_mailshot_${uniq}`; try { await ensureDataSource(request, dsName, 'contacts'); await page.goto(adminPath('feca-mailshots-mailshots')); await expect(page.locator('h1', { hasText: 'Mailshots' })).toBeVisible(); await page.locator('#ms-open-new').click(); await expect(page.locator('#ms-editor-modal')).toBeVisible(); await page.locator('#ms_purpose').fill(purpose); await page.locator('#ms_ds').selectOption({ label: dsName }); await expect.poll(async () => await page.locator('#ms-token-controls button, #ms-token-controls select option').count()).toBeGreaterThan(0); await expect.poll(async () => await page.locator('#ms_pdfname option').count()).toBeGreaterThan(1); await expect.poll(async () => await page.locator('#ms_email_field option').count()).toBeGreaterThan(1); await page.locator('#ms_subject').fill('Subject {{ contacts.id }}'); await page.locator('#ms-edit-message').click(); await expect(page.locator('#ms-template-modal')).toBeVisible(); await expect(page.locator('.jodit-container')).toBeVisible(); await setJoditHtml(page, '
PDF {{ contacts.id }}
'); await page.locator('#ms-template-save').click(); await expect(page.locator('#ms_pdfa')).toHaveValue(/PDF \{\{ contacts\.id \}\}<\/p>/); await page.locator('#ms_email_field').evaluate((el) => { const select = /** @type {HTMLSelectElement} */ (el); const option = Array.from(select.options).find((o) => o.value && /email/i.test(o.value)) || Array.from(select.options).find((o) => o.value); if (option) { select.value = option.value; select.dispatchEvent(new Event('change', { bubbles: true })); } }); await page.getByRole('button', { name: 'Save' }).first().click(); await expect(page.getByRole('cell', { name: purpose })).toBeVisible(); } finally { try { await cleanupByNames(request, { dataSourceNames: [dsName], mailshotPurposes: [purpose] }); } catch { // best effort } } }); test('mailshots editor: message save closes modal and persists on reopen', async ({ page }) => { const html = '\n