216 lines
9.5 KiB
JavaScript
216 lines
9.5 KiB
JavaScript
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, '<style>.red-note{color:red;}</style><div class="red-note">Hello <strong>bold</strong> {{ contacts.id }}</div>');
|
|
await page.locator('#ms-template-save').click();
|
|
await expect(page.locator('#ms_message')).toHaveValue(/\.red-note\{color:red;\}/);
|
|
await expect(page.locator('#ms_message')).toHaveValue(/class="red-note"/);
|
|
await expect(page.locator('#ms_message')).toHaveValue(/<strong>bold<\/strong>/);
|
|
|
|
await page.locator('#ms-edit-pdf').click();
|
|
await expect(page.locator('#ms-template-modal')).toBeVisible();
|
|
await setJoditHtml(page, '<p>PDF {{ contacts.id }}</p>');
|
|
await page.locator('#ms-template-save').click();
|
|
await expect(page.locator('#ms_pdfa')).toHaveValue(/<p>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 = '<style>.red-note{color:red;}</style>\n<div class="red-note">Hello <strong>bold</strong> {{ contacts.id }}</div>';
|
|
|
|
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-edit-message').click();
|
|
await expect(page.locator('#ms-template-modal')).toBeVisible();
|
|
await setJoditHtml(page, html);
|
|
|
|
await page.locator('#ms-template-save').click();
|
|
await expect(page.locator('#ms-template-modal')).toBeHidden();
|
|
await expect(page.locator('#ms_message')).toHaveValue(/<style>\.red-note\{color:red;\}<\/style>/);
|
|
await expect(page.locator('#ms_message')).toHaveValue(/<div class="red-note">Hello <strong>bold<\/strong> {{ contacts\.id }}<\/div>/);
|
|
await expect.poll(async () => {
|
|
const text = (await page.locator('#ms-message-meta').innerText()).trim();
|
|
const match = text.match(/^(\d+)\s+chars$/);
|
|
return match ? Number(match[1]) : 0;
|
|
}).toBeGreaterThan(0);
|
|
|
|
await page.locator('#ms-edit-message').click();
|
|
await expect(page.locator('#ms-template-modal')).toBeVisible();
|
|
const reopened = await page.evaluate(() => {
|
|
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.synchronizeValues === 'function') {
|
|
jodit.synchronizeValues();
|
|
}
|
|
if (typeof jodit.getEditorValue === 'function') {
|
|
return String(jodit.getEditorValue() || '');
|
|
}
|
|
return String(jodit.value || '');
|
|
});
|
|
expect(reopened).toContain('.red-note{color:red;}');
|
|
expect(reopened).toContain('class="red-note"');
|
|
expect(reopened).toContain('<strong>bold</strong>');
|
|
});
|
|
|
|
test('mailshots editor: save works in WYSIWYG mode with a single click', async ({ page }) => {
|
|
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-edit-message').click();
|
|
await expect(page.locator('#ms-template-modal')).toBeVisible();
|
|
await setJoditMode(page, 'wysiwyg');
|
|
await setJoditHtml(page, '<p>WYSIWYG body {{ contacts_id }}</p>');
|
|
await page.locator('#ms-template-save').click();
|
|
|
|
await expect(page.locator('#ms-template-modal')).toBeHidden();
|
|
await expect(page.locator('#ms_message')).toHaveValue(/WYSIWYG body/);
|
|
});
|
|
|
|
test('mailshots editor: allows save without recipient field and shows warning', async ({ page, request }) => {
|
|
const uniq = `${Date.now()}_${Math.floor(Math.random() * 100000)}`;
|
|
const dsName = `e2e_ms_ds_norec_${uniq}`;
|
|
const purpose = `e2e_mailshot_norec_${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 page.locator('#ms_subject').fill('No recipient email field');
|
|
await page.locator('#ms-edit-message').click();
|
|
await expect(page.locator('#ms-template-modal')).toBeVisible();
|
|
await setJoditHtml(page, '<p>PDF-only workflow {{ contacts.id }}</p>');
|
|
await page.locator('#ms-template-save').click();
|
|
|
|
await expect(page.locator('#ms-recipient-warning')).toBeVisible();
|
|
await expect(page.locator('#ms-recipient-warning')).toContainText('cannot be used to send a mailshot');
|
|
|
|
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
|
|
}
|
|
}
|
|
});
|