526 lines
19 KiB
JavaScript
526 lines
19 KiB
JavaScript
|
|
const apiUrl = Cypress.env('apiUrl');
|
||
|
|
const headers = '[{"X-Custom": "Custom-Value"}]';
|
||
|
|
|
||
|
|
describe('Campaigns', () => {
|
||
|
|
it('Opens campaigns page', () => {
|
||
|
|
cy.resetDB();
|
||
|
|
cy.loginAndVisit('/admin/campaigns');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Counts campaigns', () => {
|
||
|
|
cy.get('tbody td[data-label=Status]').should('have.length', 1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Creates campaign', () => {
|
||
|
|
cy.get('a[data-cy=btn-new]').click();
|
||
|
|
|
||
|
|
// Fill fields.
|
||
|
|
cy.get('input[name=name]').clear().type('new-attach');
|
||
|
|
cy.get('input[name=subject]').clear().type('new-subject');
|
||
|
|
cy.get('input[name=from_email]').clear().type('new <from@email>');
|
||
|
|
cy.get('.list-selector input').click();
|
||
|
|
cy.get('.list-selector .autocomplete a').eq(0).click();
|
||
|
|
|
||
|
|
cy.get('button[data-cy=btn-continue]').click();
|
||
|
|
cy.wait(500);
|
||
|
|
|
||
|
|
cy.get('a[data-cy=btn-attach]').click();
|
||
|
|
cy.get('button[data-cy=btn-toggle-upload]').click();
|
||
|
|
cy.wait(500);
|
||
|
|
cy.get('input[type=file]').attachFile('example.json');
|
||
|
|
cy.get('form[data-cy="upload"] button').click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
cy.wait(500);
|
||
|
|
cy.get('.modal a.thumb-link').click();
|
||
|
|
cy.get('button[data-cy=btn-save]').click();
|
||
|
|
cy.wait(500);
|
||
|
|
|
||
|
|
// Re-open and check that the file still exists.
|
||
|
|
cy.loginAndVisit('/admin/campaigns');
|
||
|
|
cy.get('td[data-label=Status] a').eq(0).click();
|
||
|
|
cy.get('.b-tabs nav a').eq(1).click();
|
||
|
|
cy.get('div.field[data-cy=media]').contains('example');
|
||
|
|
|
||
|
|
// Start.
|
||
|
|
cy.get('button[data-cy=btn-start]').click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
cy.wait(500);
|
||
|
|
cy.get('tbody tr').eq(0).within(() => {
|
||
|
|
cy.get('td[data-label=Status] .tag').should(($tag) => {
|
||
|
|
expect($tag.hasClass('running') || $tag.hasClass('finished')).to.be.true;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Edits campaign', () => {
|
||
|
|
cy.get('td[data-label=Status] a').eq(1).click();
|
||
|
|
|
||
|
|
// Fill fields.
|
||
|
|
cy.get('input[name=name]').clear().type('new-name');
|
||
|
|
cy.get('input[name=subject]').clear().type('new-subject');
|
||
|
|
cy.get('input[name=from_email]').clear().type('new <from@email>');
|
||
|
|
|
||
|
|
// Change the list.
|
||
|
|
cy.get('.list-selector a.delete').click();
|
||
|
|
cy.get('.list-selector input').click();
|
||
|
|
cy.get('.list-selector .autocomplete a').eq(0).click();
|
||
|
|
|
||
|
|
// Clear and redo tags.
|
||
|
|
cy.get('input[name=tags]').type('{backspace}new-tag{enter}');
|
||
|
|
|
||
|
|
// Enable schedule.
|
||
|
|
cy.get('[data-cy=btn-send-later] .check').click();
|
||
|
|
cy.wait(100);
|
||
|
|
cy.get('.datepicker input').click();
|
||
|
|
cy.wait(100);
|
||
|
|
cy.get('.datepicker-header .control:nth-child(2) select').select((new Date().getFullYear() + 1).toString());
|
||
|
|
cy.wait(100);
|
||
|
|
cy.get('.datepicker-body a.is-selectable:first').click();
|
||
|
|
cy.wait(100);
|
||
|
|
cy.get('body').click(1, 1);
|
||
|
|
|
||
|
|
// Add custom headers.
|
||
|
|
cy.get('[data-cy=btn-headers]').click();
|
||
|
|
cy.get('textarea[name=headers]').invoke('val', headers).trigger('input');
|
||
|
|
|
||
|
|
// Switch to content tab.
|
||
|
|
cy.get('.b-tabs nav a').eq(1).click();
|
||
|
|
|
||
|
|
// Switch format to plain text.
|
||
|
|
cy.get('select[name=content_type]').select('plain');
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
|
||
|
|
// Enter body value.
|
||
|
|
cy.get('textarea[name=content]').clear().type('new-content');
|
||
|
|
cy.get('button[data-cy=btn-save]').click();
|
||
|
|
|
||
|
|
// Schedule.
|
||
|
|
cy.get('button[data-cy=btn-schedule]').click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
|
||
|
|
cy.wait(250);
|
||
|
|
|
||
|
|
// Verify the changes.
|
||
|
|
cy.request(`${apiUrl}/api/campaigns/1`).should((response) => {
|
||
|
|
const { data } = response.body;
|
||
|
|
expect(data.status).to.equal('scheduled');
|
||
|
|
expect(data.name).to.equal('new-name');
|
||
|
|
expect(data.subject).to.equal('new-subject');
|
||
|
|
expect(data.content_type).to.equal('plain');
|
||
|
|
expect(data.altbody).to.equal(null);
|
||
|
|
expect(data.send_at).to.not.equal(null);
|
||
|
|
expect(data.body).to.equal('new-content');
|
||
|
|
|
||
|
|
expect(data.lists.length).to.equal(1);
|
||
|
|
expect(data.lists[0].id).to.equal(1);
|
||
|
|
expect(data.tags.length).to.equal(1);
|
||
|
|
expect(data.tags[0]).to.equal('new-tag');
|
||
|
|
expect(data.headers[0]['X-Custom']).to.equal('Custom-Value');
|
||
|
|
});
|
||
|
|
|
||
|
|
cy.get('tbody td[data-label=Status] .tag.scheduled');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Unschedules campaign', () => {
|
||
|
|
cy.get('td[data-label=Status] a').eq(1).click();
|
||
|
|
cy.wait(250);
|
||
|
|
cy.get('button[data-cy=btn-unschedule]').click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
cy.wait(250);
|
||
|
|
cy.visit('/admin/campaigns');
|
||
|
|
|
||
|
|
// Check if the status label has the inner text `Draft`.
|
||
|
|
cy.get('td[data-label=Status] .tag.draft').should('have.length', 1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Switches formats', () => {
|
||
|
|
cy.resetDB();
|
||
|
|
cy.loginAndVisit('/admin/campaigns');
|
||
|
|
const formats = ['html', 'markdown', 'plain'];
|
||
|
|
const htmlBody = '<strong>hello</strong> \{\{ .Subscriber.Name \}\} from {\{ .Subscriber.Attribs.city \}\}';
|
||
|
|
const plainBody = 'hello Demo Subscriber from Bengaluru';
|
||
|
|
|
||
|
|
// Set test content the first time.
|
||
|
|
cy.get('td[data-label=Status] a').click();
|
||
|
|
cy.get('.b-tabs nav a').eq(1).click();
|
||
|
|
cy.window().then((win) => {
|
||
|
|
win.tinymce.editors[0].setContent(htmlBody);
|
||
|
|
win.tinymce.editors[0].save();
|
||
|
|
});
|
||
|
|
cy.get('button[data-cy=btn-save]').click();
|
||
|
|
|
||
|
|
formats.forEach((c) => {
|
||
|
|
cy.visit('/admin/campaigns');
|
||
|
|
cy.get('td[data-label=Status] a').click();
|
||
|
|
|
||
|
|
// Switch to content tab.
|
||
|
|
cy.get('.b-tabs nav a').eq(1).click();
|
||
|
|
|
||
|
|
// Switch format.
|
||
|
|
cy.get('select[name=content_type]').select(c);
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
|
||
|
|
// Check content via the preview API (the iframe is sandboxed and inaccessible to JS).
|
||
|
|
if (c !== 'plain') {
|
||
|
|
cy.location('pathname').then((p) => {
|
||
|
|
cy.request(`${apiUrl}/api/campaigns/${p.split('/').at(-1).replace(/#.*/, '')}/preview`).then((resp) => {
|
||
|
|
// Strip HTML tags and normalize whitespace.
|
||
|
|
const text = resp.body.replace(/<[^>]+>/g, ' ').replace(/ /g, ' ').replace(/\s+/g, ' ').trim();
|
||
|
|
expect(text).to.contain(plainBody);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
cy.visit('/admin/campaigns');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Clones campaign', () => {
|
||
|
|
cy.loginAndVisit('/admin/campaigns');
|
||
|
|
for (let n = 0; n < 3; n++) {
|
||
|
|
// Clone the campaign.
|
||
|
|
cy.get('[data-cy=btn-clone]').first().click();
|
||
|
|
cy.get('.modal input').clear().type(`clone${n}`).click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
cy.wait(250);
|
||
|
|
cy.clickMenu('all-campaigns');
|
||
|
|
cy.wait(100);
|
||
|
|
|
||
|
|
// Verify the newly created row.
|
||
|
|
cy.get('tbody td[data-label="Name"]').first().contains(`clone${n}`);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Searches campaigns', () => {
|
||
|
|
cy.get('input[name=query]').clear().type('clone2{enter}');
|
||
|
|
cy.get('tbody tr').its('length').should('eq', 1);
|
||
|
|
cy.get('tbody td[data-label="Name"]').first().contains('clone2');
|
||
|
|
cy.get('input[name=query]').clear().type('{enter}');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Deletes campaigns', () => {
|
||
|
|
cy.wait(1000);
|
||
|
|
// Delete all visible lists.
|
||
|
|
cy.get('tbody tr').each(() => {
|
||
|
|
cy.get('tbody a[data-cy=btn-delete]').first().click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
});
|
||
|
|
|
||
|
|
// Confirm deletion.
|
||
|
|
cy.get('table tr.is-empty');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Adds new campaigns', () => {
|
||
|
|
const lists = [[1], [1, 2]];
|
||
|
|
const cTypes = ['richtext', 'html', 'markdown', 'plain', 'visual'];
|
||
|
|
|
||
|
|
let n = 0;
|
||
|
|
cTypes.forEach((c) => {
|
||
|
|
lists.forEach((l) => {
|
||
|
|
// Click the 'new button'
|
||
|
|
cy.get('[data-cy=btn-new]').click();
|
||
|
|
cy.wait(100);
|
||
|
|
|
||
|
|
// Fill fields.
|
||
|
|
cy.get('input[name=name]').clear().type(`name${n}`);
|
||
|
|
cy.get('input[name=subject]').clear().type(`subject${n}`);
|
||
|
|
|
||
|
|
l.forEach(() => {
|
||
|
|
cy.get('.list-selector input').click();
|
||
|
|
cy.get('.list-selector .autocomplete a').first().click();
|
||
|
|
});
|
||
|
|
|
||
|
|
// Add tags.
|
||
|
|
for (let i = 0; i < 3; i++) {
|
||
|
|
cy.get('input[name=tags]').type(`tag${i}{enter}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add headers.
|
||
|
|
cy.get('[data-cy=btn-headers]').click();
|
||
|
|
cy.get('textarea[name=headers]').invoke('val', `[{"X-Header-${n}": "Value-${n}"}]`).trigger('input');
|
||
|
|
|
||
|
|
// Hit 'Continue'.
|
||
|
|
cy.get('button[data-cy=btn-continue]').click();
|
||
|
|
cy.wait(250);
|
||
|
|
|
||
|
|
// Verify the changes.
|
||
|
|
(function (n) {
|
||
|
|
cy.location('pathname').then((p) => {
|
||
|
|
cy.request(`${apiUrl}/api/campaigns/${p.split('/').at(-1).replace(/#.*/, '')}`).should((response) => {
|
||
|
|
const { data } = response.body;
|
||
|
|
expect(data.status).to.equal('draft');
|
||
|
|
expect(data.name).to.equal(`name${n}`);
|
||
|
|
expect(data.subject).to.equal(`subject${n}`);
|
||
|
|
expect(data.content_type).to.equal('richtext');
|
||
|
|
expect(data.altbody).to.equal(null);
|
||
|
|
expect(data.send_at).to.equal(null);
|
||
|
|
expect(data.headers[0][`X-Header-${n}`]).to.equal(`Value-${n}`);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}(n));
|
||
|
|
|
||
|
|
// Select content type.
|
||
|
|
cy.get('select[name=content_type]').select(c);
|
||
|
|
|
||
|
|
// Insert content.
|
||
|
|
const htmlBody = `<strong>hello${n}</strong> \{\{ .Subscriber.Name \}\} from {\{ .Subscriber.Attribs.city \}\}`;
|
||
|
|
const plainBody = `hello${n} Demo Subscriber from Bengaluru`;
|
||
|
|
const markdownBody = `**hello${n}** Demo Subscriber from Bengaluru`;
|
||
|
|
|
||
|
|
cy.log(`format = ${c}`);
|
||
|
|
if (c === 'richtext') {
|
||
|
|
cy.window().then((win) => {
|
||
|
|
win.tinymce.editors[0].setContent(htmlBody);
|
||
|
|
win.tinymce.editors[0].save();
|
||
|
|
});
|
||
|
|
cy.wait(500);
|
||
|
|
} else if (c === 'html') {
|
||
|
|
// Use CodeMirror 6 via the Vue component's editor instance.
|
||
|
|
cy.get('.code-editor').then(($el) => {
|
||
|
|
const view = $el[0].__vue__.editor;
|
||
|
|
view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: htmlBody } });
|
||
|
|
});
|
||
|
|
} else if (c === 'markdown') {
|
||
|
|
cy.get('.code-editor').then(($el) => {
|
||
|
|
const view = $el[0].__vue__.editor;
|
||
|
|
view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: markdownBody } });
|
||
|
|
});
|
||
|
|
} else if (c === 'plain') {
|
||
|
|
cy.get('textarea[name=content]').invoke('val', plainBody).trigger('input');
|
||
|
|
} else if (c === 'visual') {
|
||
|
|
cy.wait(200);
|
||
|
|
cy.get('iframe').then((el) => {
|
||
|
|
cy.wait(200);
|
||
|
|
cy.wrap(el.contents()).find('table td').click();
|
||
|
|
cy.wait(200);
|
||
|
|
cy.wrap(el.contents()).find('textarea').eq(0).type(plainBody);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// Save.
|
||
|
|
cy.get('button[data-cy=btn-save]').click();
|
||
|
|
|
||
|
|
// Verify the preview content via the API (the iframe is sandboxed).
|
||
|
|
if (c !== 'plain') {
|
||
|
|
cy.location('pathname').then((p) => {
|
||
|
|
cy.request(`${apiUrl}/api/campaigns/${p.split('/').at(-1).replace(/#.*/, '')}/preview`).then((resp) => {
|
||
|
|
const text = resp.body.replace(/<[^>]+>/g, ' ').replace(/ /g, ' ').replace(/\s+/g, ' ').trim();
|
||
|
|
expect(text).to.contain(plainBody);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
cy.clickMenu('all-campaigns');
|
||
|
|
cy.wait(500);
|
||
|
|
|
||
|
|
// Verify the newly created campaign in the table.
|
||
|
|
cy.get('tbody td[data-label="Name"]').first().contains(`name${n}`);
|
||
|
|
cy.get('tbody td[data-label="Name"]').first().contains(`subject${n}`);
|
||
|
|
cy.get('tbody td[data-label="Lists"]').first().then(($el) => {
|
||
|
|
cy.wrap($el).find('li').should('have.length', l.length);
|
||
|
|
});
|
||
|
|
|
||
|
|
n++;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Fetch the campaigns API and verfiy the values that couldn't be verified on the table UI.
|
||
|
|
cy.request(`${apiUrl}/api/campaigns?order=asc&order_by=created_at`).should((response) => {
|
||
|
|
const { data } = response.body;
|
||
|
|
expect(data.total).to.equal(lists.length * cTypes.length);
|
||
|
|
|
||
|
|
let n = 0;
|
||
|
|
cTypes.forEach((c) => {
|
||
|
|
lists.forEach((l) => {
|
||
|
|
expect(data.results[n].content_type).to.equal(c);
|
||
|
|
expect(data.results[n].lists.map((ls) => ls.id)).to.deep.equal(l);
|
||
|
|
n++;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Starts and cancels campaigns', () => {
|
||
|
|
for (let n = 1; n <= 2; n++) {
|
||
|
|
cy.get(`tbody tr:nth-child(${n}) [data-cy=btn-start]`).click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
cy.wait(250);
|
||
|
|
cy.get(`tbody tr:nth-child(${n}) td[data-label=Status] .tag.running`);
|
||
|
|
|
||
|
|
if (n > 1) {
|
||
|
|
cy.get(`tbody tr:nth-child(${n}) [data-cy=btn-cancel]`).click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
cy.wait(250);
|
||
|
|
cy.get(`tbody tr:nth-child(${n}) td[data-label=Status] .tag.cancelled`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Sorts campaigns', () => {
|
||
|
|
const asc = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
|
||
|
|
const desc = [14, 13, 12, 11, 10, 9, 8, 7, 6, 5];
|
||
|
|
const cases = ['cy-name', 'cy-timestamp'];
|
||
|
|
|
||
|
|
cases.forEach((c) => {
|
||
|
|
cy.sortTable(`thead th.${c}`, asc);
|
||
|
|
cy.wait(250);
|
||
|
|
cy.sortTable(`thead th.${c}`, desc);
|
||
|
|
cy.wait(250);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Bulk deletes campaigns', () => {
|
||
|
|
const apiUrl = Cypress.env('apiUrl');
|
||
|
|
|
||
|
|
const params = {
|
||
|
|
name: 'test-campaign-bulk',
|
||
|
|
subject: 'subject',
|
||
|
|
type: 'regular',
|
||
|
|
content_type: 'richtext',
|
||
|
|
template_id: 1,
|
||
|
|
lists: [1],
|
||
|
|
};
|
||
|
|
|
||
|
|
// Create 30 in a loop.
|
||
|
|
for (let i = 0; i < 30; i += 1) {
|
||
|
|
cy.request('POST', `${apiUrl}/api/campaigns`, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
cy.loginAndVisit('/admin/campaigns');
|
||
|
|
|
||
|
|
// Bulk delete with the `all` flag.
|
||
|
|
cy.window().scrollTo('top');
|
||
|
|
cy.wait(500);
|
||
|
|
cy.get('thead input[type="checkbox"]').click({ force: true });
|
||
|
|
cy.get('a[data-cy=select-all-campaigns]').click();
|
||
|
|
cy.get('a[data-cy=btn-delete-campaigns]').click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
cy.get('table tr.is-empty');
|
||
|
|
|
||
|
|
// Bulk delete with the selected IDs.
|
||
|
|
// Create 5 campaigns in a loop.
|
||
|
|
for (let i = 0; i < 5; i += 1) {
|
||
|
|
cy.request('POST', `${apiUrl}/api/campaigns`, params);
|
||
|
|
}
|
||
|
|
|
||
|
|
cy.visit('/admin/campaigns');
|
||
|
|
cy.wait(500);
|
||
|
|
cy.get('thead input[type="checkbox"]').click({ force: true });
|
||
|
|
cy.get('a[data-cy=btn-delete-campaigns]').click();
|
||
|
|
cy.get('.modal button.is-primary:eq(0)').click();
|
||
|
|
cy.get('table tr.is-empty');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('Campaign image embed', () => {
|
||
|
|
const mailhog = 'http://localhost:8025';
|
||
|
|
const logoUrl = `${apiUrl}/uploads/logo.png`;
|
||
|
|
|
||
|
|
// Create a campaign of the given content type via the API and open its content tab.
|
||
|
|
const newCampaign = (name, contentType) => cy.request('POST', `${apiUrl}/api/campaigns`, {
|
||
|
|
name, subject: name, type: 'regular', content_type: contentType, lists: [1],
|
||
|
|
}).then((r) => cy.visit(`/admin/campaigns/${r.body.data.id}#content`).then(() => r.body.data.id));
|
||
|
|
|
||
|
|
// Start the campaign and assert (via the MailHog API) whether the delivered e-mail
|
||
|
|
// embedded the image as a MIME/CID part (embed=true) or left it as a plain URL.
|
||
|
|
const send = (id, name, embed) => {
|
||
|
|
cy.request('PUT', `${apiUrl}/api/campaigns/${id}/status`, { status: 'running' });
|
||
|
|
cy.waitUntil(() => cy.request(`${mailhog}/api/v2/search?kind=containing&query=${name}`)
|
||
|
|
.then((r) => r.body.total > 0), { timeout: 20000, interval: 1000 });
|
||
|
|
cy.request(`${mailhog}/api/v2/search?kind=containing&query=${name}`).then((r) => {
|
||
|
|
const raw = JSON.stringify(r.body.items[0]);
|
||
|
|
expect(/image\/png/.test(raw), 'has inline image part').to.equal(embed);
|
||
|
|
expect(/cid:/.test(raw), 'references cid').to.equal(embed);
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
// Open the image dialog's media picker and upload/select image.
|
||
|
|
const pickLogo = (upload) => {
|
||
|
|
cy.window().then((win) => win.tinymce.editors[0].execCommand('mceImage'));
|
||
|
|
cy.get('.tox-dialog .tox-browse-url').click();
|
||
|
|
if (upload) {
|
||
|
|
cy.get('[data-cy=btn-toggle-upload]').click();
|
||
|
|
cy.get('input[type=file]').attachFile('logo.png');
|
||
|
|
cy.get('form[data-cy="upload"] button').click();
|
||
|
|
}
|
||
|
|
cy.get('.modal a.thumb-link', { timeout: 10000 }).first().click();
|
||
|
|
cy.get('.tox-dialog input[type=url]').should('have.value', logoUrl);
|
||
|
|
};
|
||
|
|
|
||
|
|
const richtext = (name, embed, upload) => {
|
||
|
|
let id;
|
||
|
|
newCampaign(name, 'richtext').then((cid) => { id = cid; });
|
||
|
|
cy.window().its('tinymce.editors.0').should('exist');
|
||
|
|
pickLogo(upload);
|
||
|
|
if (embed) {
|
||
|
|
cy.get('.tox-dialog input[type=checkbox]').check({ force: true });
|
||
|
|
}
|
||
|
|
cy.get('.tox-dialog__footer button').last().click();
|
||
|
|
cy.get('button[data-cy=btn-save]').click();
|
||
|
|
cy.wait(500);
|
||
|
|
|
||
|
|
// The 'embed?' selection is stored on the <img data-embed> and must persist across reloads.
|
||
|
|
cy.then(() => cy.visit(`/admin/campaigns/${id}#content`));
|
||
|
|
cy.window().its('tinymce.editors.0').should('exist');
|
||
|
|
cy.window().then((win) => {
|
||
|
|
const ed = win.tinymce.editors[0];
|
||
|
|
ed.selection.select(ed.getBody().querySelector('img'));
|
||
|
|
ed.execCommand('mceImage');
|
||
|
|
});
|
||
|
|
cy.get('.tox-dialog input[type=checkbox]').should(embed ? 'be.checked' : 'not.be.checked');
|
||
|
|
cy.get('.tox-dialog__footer button').first().click();
|
||
|
|
|
||
|
|
cy.then(() => send(id, name, embed));
|
||
|
|
};
|
||
|
|
|
||
|
|
const visual = (name, embed) => {
|
||
|
|
let id;
|
||
|
|
newCampaign(name, 'visual').then((cid) => { id = cid; });
|
||
|
|
|
||
|
|
// Add an image block pointing at the uploaded image.
|
||
|
|
cy.waitUntil(() => cy.get('#visual-editor')
|
||
|
|
.then(($f) => Boolean($f[0].contentWindow.EmailBuilder
|
||
|
|
&& $f[0].contentWindow.EmailBuilder.isRendered('visual-editor-container'))));
|
||
|
|
cy.get('#visual-editor').then(($f) => $f[0].contentWindow.EmailBuilder.resetDocument({
|
||
|
|
root: { type: 'EmailLayout', data: { childrenIds: ['blk'] } },
|
||
|
|
blk: { type: 'Image', data: { props: { url: logoUrl, embed: false }, style: {} } },
|
||
|
|
}));
|
||
|
|
cy.wait(500);
|
||
|
|
|
||
|
|
// Select image and check 'embed?' checkbox.
|
||
|
|
const clickImage = () => cy.get('#visual-editor')
|
||
|
|
.then(($f) => $f[0].contentDocument.querySelector('#visual-editor-container img').click());
|
||
|
|
clickImage();
|
||
|
|
cy.wait(300);
|
||
|
|
if (embed) {
|
||
|
|
cy.get('#visual-editor').then(($f) => $f[0].contentDocument.querySelector('input[type=checkbox]').click());
|
||
|
|
cy.wait(300);
|
||
|
|
}
|
||
|
|
cy.get('button[data-cy=btn-save]').click();
|
||
|
|
cy.wait(500);
|
||
|
|
|
||
|
|
// Reload and confirm checkbox peristence.
|
||
|
|
cy.then(() => cy.visit(`/admin/campaigns/${id}#content`));
|
||
|
|
cy.waitUntil(() => cy.get('#visual-editor')
|
||
|
|
.then(($f) => Boolean($f[0].contentDocument.querySelector('#visual-editor-container img'))));
|
||
|
|
clickImage();
|
||
|
|
cy.wait(300);
|
||
|
|
cy.get('#visual-editor').then(($f) => {
|
||
|
|
expect($f[0].contentDocument.querySelector('input[type=checkbox]').checked).to.equal(embed);
|
||
|
|
});
|
||
|
|
|
||
|
|
cy.then(() => send(id, name, embed));
|
||
|
|
};
|
||
|
|
|
||
|
|
it('Resets DB and MailHog', () => {
|
||
|
|
cy.resetDB();
|
||
|
|
cy.request('DELETE', `${mailhog}/api/v1/messages`);
|
||
|
|
cy.loginAndVisit('/admin/campaigns');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Embeds a rich text image as a MIME/CID part', () => richtext('embedrich', true, true));
|
||
|
|
it('Sends a rich text image as a plain URL', () => richtext('plainrich', false, false));
|
||
|
|
it('Embeds a visual image as a MIME/CID part', () => visual('embedvis', true));
|
||
|
|
it('Sends a visual image as a plain URL', () => visual('plainvis', false));
|
||
|
|
});
|