2022-04-25 23:07:46 +03:00
|
|
|
const assert = require('assert');
|
2023-03-03 20:58:19 +03:00
|
|
|
const sinon = require('sinon');
|
2023-04-07 15:34:38 +03:00
|
|
|
const {agentProvider, mockManager, fixtureManager, configUtils, dbUtils, matchers, regexes} = require('../../utils/e2e-framework');
|
2023-01-17 14:56:29 +03:00
|
|
|
const {anyContentVersion, anyEtag, anyObjectId, anyUuid, anyISODateTime, anyLocationFor, anyNumber} = matchers;
|
2023-04-07 15:34:38 +03:00
|
|
|
const {queryStringToken} = regexes;
|
2022-05-12 15:28:45 +03:00
|
|
|
const models = require('../../../core/server/models');
|
2023-03-03 20:58:19 +03:00
|
|
|
const logging = require('@tryghost/logging');
|
2022-04-25 23:07:46 +03:00
|
|
|
|
|
|
|
const assertMemberRelationCount = async (newsletterId, expectedCount) => {
|
2022-05-06 14:15:12 +03:00
|
|
|
const relations = await dbUtils.knex('members_newsletters').where({newsletter_id: newsletterId}).pluck('id');
|
2022-04-25 23:07:46 +03:00
|
|
|
|
2022-05-06 14:15:12 +03:00
|
|
|
assert.equal(relations.length, expectedCount);
|
2022-04-25 23:07:46 +03:00
|
|
|
};
|
2022-03-28 18:24:51 +03:00
|
|
|
|
|
|
|
const newsletterSnapshot = {
|
2022-04-22 15:39:27 +03:00
|
|
|
id: anyObjectId,
|
2022-04-27 16:50:25 +03:00
|
|
|
uuid: anyUuid,
|
2022-04-22 15:39:27 +03:00
|
|
|
created_at: anyISODateTime,
|
|
|
|
updated_at: anyISODateTime
|
2022-03-28 18:24:51 +03:00
|
|
|
};
|
|
|
|
|
2022-05-03 16:33:56 +03:00
|
|
|
const newsletterSnapshotWithoutSortOrder = {
|
|
|
|
id: anyObjectId,
|
|
|
|
uuid: anyUuid,
|
|
|
|
created_at: anyISODateTime,
|
|
|
|
updated_at: anyISODateTime,
|
2022-05-06 14:15:12 +03:00
|
|
|
sort_order: anyNumber
|
2022-05-03 16:33:56 +03:00
|
|
|
};
|
|
|
|
|
2022-03-28 18:24:51 +03:00
|
|
|
describe('Newsletters API', function () {
|
2022-05-06 14:15:12 +03:00
|
|
|
let agent;
|
2023-04-07 15:34:38 +03:00
|
|
|
let emailMockReceiver;
|
2022-04-22 15:20:44 +03:00
|
|
|
|
2022-03-28 18:24:51 +03:00
|
|
|
before(async function () {
|
|
|
|
agent = await agentProvider.getAdminAPIAgent();
|
2022-04-25 17:14:22 +03:00
|
|
|
await fixtureManager.init('newsletters', 'members:newsletters');
|
2022-03-28 18:24:51 +03:00
|
|
|
await agent.loginAsOwner();
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(function () {
|
2023-04-07 15:34:38 +03:00
|
|
|
emailMockReceiver = mockManager.mockMail();
|
2022-03-28 18:24:51 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
mockManager.restore();
|
2023-03-03 20:58:19 +03:00
|
|
|
sinon.restore();
|
2022-03-28 18:24:51 +03:00
|
|
|
});
|
|
|
|
|
2022-04-25 17:14:22 +03:00
|
|
|
it('Can browse newsletters', async function () {
|
|
|
|
await agent.get('newsletters/')
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: new Array(4).fill(newsletterSnapshot)
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-25 17:14:22 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Can read a newsletter', async function () {
|
|
|
|
await agent
|
2022-04-25 23:07:46 +03:00
|
|
|
.get(`newsletters/${fixtureManager.get('newsletters', 0).id}/`)
|
2022-04-25 17:14:22 +03:00
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-25 17:14:22 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Can include members & posts counts when browsing newsletters', async function () {
|
|
|
|
await agent
|
|
|
|
.get(`newsletters/?include=count.members,count.posts`)
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: new Array(4).fill(newsletterSnapshot)
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-25 17:14:22 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Can include members & posts counts when reading a newsletter', async function () {
|
|
|
|
await agent
|
2022-04-25 23:07:46 +03:00
|
|
|
.get(`newsletters/${fixtureManager.get('newsletters', 0).id}/?include=count.members,count.posts`)
|
2022-04-25 17:14:22 +03:00
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: new Array(1).fill(newsletterSnapshot)
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-25 17:14:22 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-03-31 11:52:04 +03:00
|
|
|
it('Can add a newsletter', async function () {
|
2022-05-06 14:15:12 +03:00
|
|
|
const siteUrl = configUtils.config.getSiteUrl();
|
2022-05-04 15:47:39 +03:00
|
|
|
const relativePath = 'content/images/2022/05/cover-image.jpg';
|
|
|
|
const absolutePath = siteUrl + relativePath;
|
|
|
|
const transformReadyPath = '__GHOST_URL__/' + relativePath;
|
2022-03-31 11:52:04 +03:00
|
|
|
const newsletter = {
|
|
|
|
name: 'My test newsletter',
|
|
|
|
sender_name: 'Test',
|
2022-04-22 15:20:44 +03:00
|
|
|
sender_email: null,
|
2022-04-08 16:36:30 +03:00
|
|
|
sender_reply_to: 'newsletter',
|
2022-03-31 11:52:04 +03:00
|
|
|
status: 'active',
|
|
|
|
subscribe_on_signup: true,
|
2022-04-08 16:36:30 +03:00
|
|
|
title_font_category: 'serif',
|
|
|
|
body_font_category: 'serif',
|
|
|
|
show_header_icon: true,
|
|
|
|
show_header_title: true,
|
|
|
|
show_badge: true,
|
2022-05-04 15:47:39 +03:00
|
|
|
sort_order: 0,
|
|
|
|
header_image: absolutePath
|
2022-03-31 11:52:04 +03:00
|
|
|
};
|
2022-03-28 18:24:51 +03:00
|
|
|
|
2022-05-04 15:47:39 +03:00
|
|
|
const {body: body2} = await agent
|
2022-03-31 11:52:04 +03:00
|
|
|
.post(`newsletters/`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
2022-04-28 13:16:14 +03:00
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
2022-05-04 15:47:39 +03:00
|
|
|
.expect(({body}) => {
|
|
|
|
// Should still be absolute
|
2022-05-06 14:15:12 +03:00
|
|
|
assert.equal(body.newsletters[0].header_image, absolutePath);
|
2022-05-04 15:47:39 +03:00
|
|
|
})
|
2022-04-28 13:16:14 +03:00
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-28 13:16:14 +03:00
|
|
|
etag: anyEtag,
|
|
|
|
location: anyLocationFor('newsletters')
|
|
|
|
});
|
2022-05-04 15:47:39 +03:00
|
|
|
|
|
|
|
const id = body2.newsletters[0].id;
|
|
|
|
|
|
|
|
// Check with a database query if the header_image is saved correctly with a 'transformReady' path
|
2022-05-06 14:15:12 +03:00
|
|
|
const [header_image] = await dbUtils.knex('newsletters').where('id', id).pluck('header_image');
|
|
|
|
assert.equal(header_image, transformReadyPath);
|
2022-04-28 13:16:14 +03:00
|
|
|
});
|
|
|
|
|
2022-05-05 12:20:15 +03:00
|
|
|
it('Can include members & posts counts when adding a newsletter', async function () {
|
|
|
|
const newsletter = {
|
|
|
|
name: 'My test newsletter 2',
|
|
|
|
sender_name: 'Test',
|
|
|
|
sender_email: null,
|
|
|
|
sender_reply_to: 'newsletter',
|
|
|
|
status: 'active',
|
|
|
|
subscribe_on_signup: true,
|
|
|
|
title_font_category: 'serif',
|
|
|
|
body_font_category: 'serif',
|
|
|
|
show_header_icon: true,
|
|
|
|
show_header_title: true,
|
|
|
|
show_badge: true,
|
|
|
|
sort_order: 0
|
|
|
|
};
|
|
|
|
|
|
|
|
await agent
|
|
|
|
.post(`newsletters/?include=count.members,count.posts`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-05 12:20:15 +03:00
|
|
|
etag: anyEtag,
|
|
|
|
location: anyLocationFor('newsletters')
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-04-28 13:16:14 +03:00
|
|
|
it('Can add multiple newsletters', async function () {
|
|
|
|
const firstNewsletter = {
|
|
|
|
name: 'My first test newsletter'
|
|
|
|
};
|
|
|
|
|
|
|
|
const secondNewsletter = {
|
|
|
|
name: 'My second test newsletter'
|
|
|
|
};
|
|
|
|
|
|
|
|
await agent
|
|
|
|
.post(`newsletters/`)
|
|
|
|
.body({newsletters: [firstNewsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-28 13:16:14 +03:00
|
|
|
etag: anyEtag,
|
|
|
|
location: anyLocationFor('newsletters')
|
|
|
|
});
|
|
|
|
|
|
|
|
await agent
|
|
|
|
.post(`newsletters/`)
|
|
|
|
.body({newsletters: [secondNewsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
2022-04-25 23:07:46 +03:00
|
|
|
newsletters: [newsletterSnapshot]
|
2022-03-31 11:52:04 +03:00
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-03-31 11:52:04 +03:00
|
|
|
etag: anyEtag,
|
2022-04-25 17:14:22 +03:00
|
|
|
location: anyLocationFor('newsletters')
|
2022-03-31 11:52:04 +03:00
|
|
|
});
|
|
|
|
});
|
2022-03-28 18:24:51 +03:00
|
|
|
|
2022-04-22 15:20:44 +03:00
|
|
|
it('Can add a newsletter - with custom sender_email', async function () {
|
|
|
|
const newsletter = {
|
|
|
|
name: 'My test newsletter with custom sender_email',
|
|
|
|
sender_name: 'Test',
|
|
|
|
sender_email: 'test@example.com',
|
|
|
|
sender_reply_to: 'newsletter',
|
|
|
|
status: 'active',
|
|
|
|
subscribe_on_signup: true,
|
|
|
|
title_font_category: 'serif',
|
|
|
|
body_font_category: 'serif',
|
|
|
|
show_header_icon: true,
|
|
|
|
show_header_title: true,
|
|
|
|
show_badge: true,
|
|
|
|
sort_order: 0
|
|
|
|
};
|
|
|
|
|
|
|
|
await agent
|
|
|
|
.post(`newsletters/`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
2022-04-25 23:07:46 +03:00
|
|
|
newsletters: [newsletterSnapshot],
|
2022-04-22 15:20:44 +03:00
|
|
|
meta: {
|
|
|
|
sent_email_verification: ['sender_email']
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-22 15:20:44 +03:00
|
|
|
etag: anyEtag,
|
2022-04-25 17:14:22 +03:00
|
|
|
location: anyLocationFor('newsletters')
|
2022-04-22 15:20:44 +03:00
|
|
|
});
|
|
|
|
|
2023-04-07 15:34:38 +03:00
|
|
|
emailMockReceiver
|
|
|
|
.assertSentEmailCount(1)
|
|
|
|
.matchMetadataSnapshot()
|
|
|
|
.matchHTMLSnapshot([{
|
|
|
|
pattern: queryStringToken('verifyEmail'),
|
|
|
|
replacement: 'verifyEmail=REPLACED_TOKEN'
|
|
|
|
}])
|
|
|
|
.matchPlaintextSnapshot([{
|
|
|
|
pattern: queryStringToken('verifyEmail'),
|
|
|
|
replacement: 'verifyEmail=REPLACED_TOKEN'
|
|
|
|
}]);
|
2022-03-31 11:52:04 +03:00
|
|
|
});
|
2022-03-28 18:24:51 +03:00
|
|
|
|
2022-04-25 23:07:46 +03:00
|
|
|
it('Can add a newsletter - and subscribe existing members', async function () {
|
|
|
|
const newsletter = {
|
|
|
|
name: 'New newsletter with existing members subscribed',
|
|
|
|
sender_name: 'Test',
|
|
|
|
sender_email: null,
|
|
|
|
sender_reply_to: 'newsletter',
|
|
|
|
status: 'active',
|
|
|
|
subscribe_on_signup: true,
|
|
|
|
title_font_category: 'serif',
|
|
|
|
body_font_category: 'serif',
|
|
|
|
show_header_icon: true,
|
|
|
|
show_header_title: true,
|
|
|
|
show_badge: true,
|
|
|
|
sort_order: 0
|
|
|
|
};
|
|
|
|
|
|
|
|
const {body} = await agent
|
|
|
|
.post(`newsletters/?opt_in_existing=true`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-25 23:07:46 +03:00
|
|
|
etag: anyEtag,
|
|
|
|
location: anyLocationFor('newsletters')
|
|
|
|
});
|
|
|
|
|
|
|
|
// Assert that the newsletter has 6 related members in the DB
|
|
|
|
await assertMemberRelationCount(body.newsletters[0].id, 6);
|
|
|
|
});
|
|
|
|
|
2022-03-31 11:52:04 +03:00
|
|
|
it('Can edit newsletters', async function () {
|
2022-04-25 17:14:22 +03:00
|
|
|
const id = fixtureManager.get('newsletters', 0).id;
|
2022-03-31 11:52:04 +03:00
|
|
|
await agent.put(`newsletters/${id}`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
name: 'Updated newsletter name'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-03-31 11:52:04 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
2022-04-22 15:20:44 +03:00
|
|
|
|
2022-05-05 12:20:15 +03:00
|
|
|
it('Can include members & posts counts when editing newsletters', async function () {
|
|
|
|
const id = fixtureManager.get('newsletters', 0).id;
|
|
|
|
await agent.put(`newsletters/${id}/?include=count.members,count.posts`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
name: 'Updated newsletter name 2'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-05 12:20:15 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-04-25 17:14:22 +03:00
|
|
|
it('Can edit a newsletters and update the sender_email when already set', async function () {
|
|
|
|
const id = fixtureManager.get('newsletters', 0).id;
|
2022-04-22 15:20:44 +03:00
|
|
|
|
|
|
|
await agent.put(`newsletters/${id}`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
name: 'Updated newsletter name',
|
|
|
|
sender_email: 'updated@example.com'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot],
|
|
|
|
meta: {
|
|
|
|
sent_email_verification: ['sender_email']
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-22 15:20:44 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
|
2023-04-07 15:34:38 +03:00
|
|
|
emailMockReceiver
|
|
|
|
.assertSentEmailCount(1)
|
|
|
|
.matchMetadataSnapshot()
|
|
|
|
.matchHTMLSnapshot([{
|
|
|
|
pattern: queryStringToken('verifyEmail'),
|
|
|
|
replacement: 'verifyEmail=REPLACED_TOKEN'
|
|
|
|
}])
|
|
|
|
.matchPlaintextSnapshot([{
|
|
|
|
pattern: queryStringToken('verifyEmail'),
|
|
|
|
replacement: 'verifyEmail=REPLACED_TOKEN'
|
|
|
|
}]);
|
2022-04-22 15:20:44 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
it('Can verify property updates', async function () {
|
|
|
|
const cheerio = require('cheerio');
|
|
|
|
|
2022-04-25 17:14:22 +03:00
|
|
|
const id = fixtureManager.get('newsletters', 0).id;
|
2022-04-22 15:20:44 +03:00
|
|
|
|
|
|
|
await agent.put(`newsletters/${id}`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
name: 'Updated newsletter name',
|
|
|
|
sender_email: 'verify@example.com'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(200);
|
|
|
|
|
2023-04-07 15:34:38 +03:00
|
|
|
// @NOTE: need a way to return snapshot of sent email from email mock receiver
|
2023-01-13 14:45:58 +03:00
|
|
|
const mail = mockManager.assert.sentEmail([]);
|
2023-04-07 15:34:38 +03:00
|
|
|
emailMockReceiver
|
|
|
|
.assertSentEmailCount(1)
|
|
|
|
.matchMetadataSnapshot()
|
|
|
|
.matchHTMLSnapshot([{
|
|
|
|
pattern: queryStringToken('verifyEmail'),
|
|
|
|
replacement: 'verifyEmail=REPLACED_TOKEN'
|
|
|
|
}])
|
|
|
|
.matchPlaintextSnapshot([{
|
|
|
|
pattern: queryStringToken('verifyEmail'),
|
|
|
|
replacement: 'verifyEmail=REPLACED_TOKEN'
|
|
|
|
}]);
|
|
|
|
|
2023-01-13 14:45:58 +03:00
|
|
|
const $mailHtml = cheerio.load(mail.html);
|
2022-04-22 15:20:44 +03:00
|
|
|
|
|
|
|
const verifyUrl = new URL($mailHtml('[data-test-verify-link]').attr('href'));
|
|
|
|
// convert Admin URL hash to native URL for easier token param extraction
|
|
|
|
const token = (new URL(verifyUrl.hash.replace('#', ''), 'http://example.com')).searchParams.get('verifyEmail');
|
|
|
|
|
|
|
|
await agent.put(`newsletters/verifications`)
|
|
|
|
.body({
|
|
|
|
token
|
|
|
|
})
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
});
|
|
|
|
});
|
2022-04-27 19:44:16 +03:00
|
|
|
|
|
|
|
describe('Host Settings: newsletter limits', function () {
|
2022-05-12 15:28:45 +03:00
|
|
|
after(function () {
|
2022-04-27 19:44:16 +03:00
|
|
|
configUtils.set('hostSettings:limits', undefined);
|
|
|
|
});
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-04-27 19:44:16 +03:00
|
|
|
it('Request fails when newsletter limit is in place', async function () {
|
|
|
|
configUtils.set('hostSettings:limits', {
|
|
|
|
newsletters: {
|
|
|
|
disabled: true,
|
|
|
|
error: 'Nuh uh'
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
agent = await agentProvider.getAdminAPIAgent();
|
|
|
|
await fixtureManager.init('newsletters', 'members:newsletters');
|
|
|
|
await agent.loginAsOwner();
|
|
|
|
|
|
|
|
const newsletter = {
|
|
|
|
name: 'Naughty newsletter'
|
|
|
|
};
|
|
|
|
|
2023-03-03 20:58:19 +03:00
|
|
|
sinon.stub(logging, 'error');
|
2022-04-27 19:44:16 +03:00
|
|
|
await agent
|
|
|
|
.post(`newsletters/?opt_in_existing=true`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(403)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
errors: [{
|
|
|
|
id: anyUuid
|
|
|
|
}]
|
|
|
|
});
|
|
|
|
});
|
2022-05-12 15:28:45 +03:00
|
|
|
|
|
|
|
describe('Max limit', function () {
|
|
|
|
before(async function () {
|
|
|
|
configUtils.set('hostSettings:limits', {
|
|
|
|
newsletters: {
|
|
|
|
max: 3,
|
|
|
|
error: 'Your plan supports up to {{max}} newsletters. Please upgrade to add more.'
|
|
|
|
}
|
|
|
|
});
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
agent = await agentProvider.getAdminAPIAgent();
|
|
|
|
await fixtureManager.init('newsletters', 'members:newsletters');
|
|
|
|
await agent.loginAsOwner();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Adding newsletter fails', async function () {
|
|
|
|
const allNewsletters = await models.Newsletter.findAll();
|
|
|
|
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
|
|
|
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const newsletter = {
|
|
|
|
name: 'Naughty newsletter'
|
|
|
|
};
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2023-03-03 20:58:19 +03:00
|
|
|
sinon.stub(logging, 'error');
|
2022-05-12 15:28:45 +03:00
|
|
|
await agent
|
|
|
|
.post(`newsletters/?opt_in_existing=true`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(403)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
errors: [{
|
|
|
|
id: anyUuid
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect(({body}) => {
|
|
|
|
assert.equal(body.errors[0].context, 'Your plan supports up to 3 newsletters. Please upgrade to add more.');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Adding newsletter fails without transaction', async function () {
|
|
|
|
const allNewsletters = await models.Newsletter.findAll();
|
|
|
|
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
|
|
|
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const newsletter = {
|
|
|
|
name: 'Naughty newsletter'
|
|
|
|
};
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2023-03-03 20:58:19 +03:00
|
|
|
sinon.stub(logging, 'error');
|
2022-05-12 15:28:45 +03:00
|
|
|
// Note that ?opt_in_existing=true will trigger a transaction, so we explicitly test here without a
|
|
|
|
// transaction
|
|
|
|
await agent
|
|
|
|
.post(`newsletters/`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(403)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
errors: [{
|
|
|
|
id: anyUuid
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect(({body}) => {
|
|
|
|
assert.equal(body.errors[0].context, 'Your plan supports up to 3 newsletters. Please upgrade to add more.');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Adding an archived newsletter doesn\'t fail', async function () {
|
|
|
|
const allNewsletters = await models.Newsletter.findAll();
|
|
|
|
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
|
|
|
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const newsletter = {
|
|
|
|
name: 'Archived newsletter',
|
|
|
|
status: 'archived'
|
|
|
|
};
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
await agent
|
|
|
|
.post(`newsletters/?opt_in_existing=true`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-12 15:28:45 +03:00
|
|
|
etag: anyEtag,
|
|
|
|
location: anyLocationFor('newsletters')
|
|
|
|
});
|
|
|
|
});
|
2022-05-13 11:15:35 +03:00
|
|
|
|
|
|
|
it('Editing an active newsletter doesn\'t fail', async function () {
|
|
|
|
const allNewsletters = await models.Newsletter.findAll();
|
|
|
|
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
|
|
|
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-13 11:15:35 +03:00
|
|
|
const activeNewsletter = allNewsletters.find(n => n.get('status') !== 'active');
|
|
|
|
assert.ok(activeNewsletter, 'This test expects to have an active newsletter in the test fixtures');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-13 11:15:35 +03:00
|
|
|
const id = activeNewsletter.id;
|
|
|
|
await agent.put(`newsletters/${id}`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
name: 'Updated active newsletter name'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-13 11:15:35 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
it('Editing an archived newsletter doesn\'t fail', async function () {
|
|
|
|
const allNewsletters = await models.Newsletter.findAll();
|
|
|
|
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
|
|
|
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const archivedNewsletter = allNewsletters.find(n => n.get('status') !== 'active');
|
|
|
|
assert.ok(archivedNewsletter, 'This test expects to have an archived newsletter in the test fixtures');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const id = archivedNewsletter.id;
|
|
|
|
await agent.put(`newsletters/${id}`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
name: 'Updated archived newsletter name'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-12 15:28:45 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
it('Unarchiving a newsletter fails', async function () {
|
|
|
|
const allNewsletters = await models.Newsletter.findAll();
|
|
|
|
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
|
|
|
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const archivedNewsletter = allNewsletters.find(n => n.get('status') !== 'active');
|
|
|
|
assert.ok(archivedNewsletter, 'This test expects to have an archived newsletter in the test fixtures');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2023-03-03 20:58:19 +03:00
|
|
|
sinon.stub(logging, 'error');
|
2022-05-12 15:28:45 +03:00
|
|
|
const id = archivedNewsletter.id;
|
|
|
|
await agent.put(`newsletters/${id}`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
status: 'active'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(403)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
errors: [{
|
|
|
|
id: anyUuid
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect(({body}) => {
|
|
|
|
assert.equal(body.errors[0].context, 'Your plan supports up to 3 newsletters. Please upgrade to add more.');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Archiving a newsletter doesn\'t fail', async function () {
|
|
|
|
const allNewsletters = await models.Newsletter.findAll();
|
|
|
|
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
|
|
|
assert.equal(newsletterCount, 3, 'This test expects to have 3 current active newsletters');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const activeNewsletter = allNewsletters.find(n => n.get('status') === 'active');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const id = activeNewsletter.id;
|
|
|
|
await agent.put(`newsletters/${id}`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
status: 'archived'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(200)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-12 15:28:45 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Adding a newsletter now doesn\'t fail', async function () {
|
|
|
|
const allNewsletters = await models.Newsletter.findAll();
|
|
|
|
const newsletterCount = allNewsletters.filter(n => n.get('status') === 'active').length;
|
|
|
|
assert.equal(newsletterCount, 2, 'This test expects to have 2 current active newsletters');
|
2023-01-13 14:45:58 +03:00
|
|
|
|
2022-05-12 15:28:45 +03:00
|
|
|
const newsletter = {
|
|
|
|
name: 'Naughty newsletter'
|
|
|
|
};
|
|
|
|
|
|
|
|
await agent
|
|
|
|
.post(`newsletters/?opt_in_existing=true`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-12 15:28:45 +03:00
|
|
|
etag: anyEtag,
|
|
|
|
location: anyLocationFor('newsletters')
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2022-04-27 19:44:16 +03:00
|
|
|
});
|
2022-04-27 12:11:16 +03:00
|
|
|
|
2022-05-05 12:20:15 +03:00
|
|
|
it(`Can't add multiple newsletters with same name`, async function () {
|
|
|
|
const firstNewsletter = {
|
|
|
|
name: 'Duplicate newsletter'
|
|
|
|
};
|
|
|
|
|
|
|
|
const secondNewsletter = {...firstNewsletter};
|
|
|
|
|
|
|
|
await agent
|
|
|
|
.post(`newsletters/`)
|
|
|
|
.body({newsletters: [firstNewsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshotWithoutSortOrder]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-05 12:20:15 +03:00
|
|
|
etag: anyEtag,
|
|
|
|
location: anyLocationFor('newsletters')
|
|
|
|
});
|
|
|
|
|
2023-03-03 20:58:19 +03:00
|
|
|
sinon.stub(logging, 'error');
|
2022-05-05 12:20:15 +03:00
|
|
|
await agent
|
|
|
|
.post(`newsletters/`)
|
|
|
|
.body({newsletters: [secondNewsletter]})
|
|
|
|
.expectStatus(422)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
errors: [{
|
|
|
|
id: anyUuid,
|
|
|
|
message: 'Validation error, cannot save newsletter.',
|
|
|
|
context: 'A newsletter with the same name already exists'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-05 12:20:15 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-04-27 12:11:16 +03:00
|
|
|
it('Can add a newsletter - with custom sender_email and subscribe existing members', async function () {
|
2022-05-06 14:15:12 +03:00
|
|
|
if (dbUtils.isSQLite()) {
|
2022-05-05 12:20:15 +03:00
|
|
|
// This breaks snapshot tests if you don't update snapshot tests on MySQL + make sure this is the last ADD test
|
2022-04-27 12:11:16 +03:00
|
|
|
return;
|
|
|
|
}
|
2022-05-06 14:15:12 +03:00
|
|
|
|
2022-04-27 12:11:16 +03:00
|
|
|
const newsletter = {
|
|
|
|
name: 'My test newsletter with custom sender_email and subscribe existing',
|
|
|
|
sender_name: 'Test',
|
|
|
|
sender_email: 'test@example.com',
|
|
|
|
sender_reply_to: 'newsletter',
|
|
|
|
status: 'active',
|
|
|
|
subscribe_on_signup: true,
|
|
|
|
title_font_category: 'serif',
|
|
|
|
body_font_category: 'serif',
|
|
|
|
show_header_icon: true,
|
|
|
|
show_header_title: true,
|
|
|
|
show_badge: true,
|
|
|
|
sort_order: 0
|
|
|
|
};
|
|
|
|
|
|
|
|
await agent
|
|
|
|
.post(`newsletters/?opt_in_existing=true`)
|
|
|
|
.body({newsletters: [newsletter]})
|
|
|
|
.expectStatus(201)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
newsletters: [newsletterSnapshot],
|
|
|
|
meta: {
|
|
|
|
sent_email_verification: ['sender_email']
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-04-27 12:11:16 +03:00
|
|
|
etag: anyEtag,
|
|
|
|
location: anyLocationFor('newsletters')
|
|
|
|
});
|
|
|
|
|
2023-04-07 15:34:38 +03:00
|
|
|
emailMockReceiver
|
|
|
|
.assertSentEmailCount(1)
|
|
|
|
.matchHTMLSnapshot()
|
|
|
|
.matchPlaintextSnapshot()
|
|
|
|
.matchMetadataSnapshot();
|
2022-04-27 12:11:16 +03:00
|
|
|
});
|
2022-05-03 16:33:56 +03:00
|
|
|
|
|
|
|
it(`Can't edit multiple newsletters to existing name`, async function () {
|
|
|
|
const id = fixtureManager.get('newsletters', 0).id;
|
|
|
|
|
2023-03-03 20:58:19 +03:00
|
|
|
sinon.stub(logging, 'error');
|
2022-05-03 16:33:56 +03:00
|
|
|
await agent.put(`newsletters/${id}`)
|
|
|
|
.body({
|
|
|
|
newsletters: [{
|
|
|
|
name: 'Duplicate newsletter'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expectStatus(422)
|
|
|
|
.matchBodySnapshot({
|
|
|
|
errors: [{
|
|
|
|
id: anyUuid,
|
|
|
|
message: 'Validation error, cannot edit newsletter.',
|
|
|
|
context: 'A newsletter with the same name already exists'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.matchHeaderSnapshot({
|
2023-01-17 14:56:29 +03:00
|
|
|
'content-version': anyContentVersion,
|
2022-05-03 16:33:56 +03:00
|
|
|
etag: anyEtag
|
|
|
|
});
|
|
|
|
});
|
2022-03-28 18:24:51 +03:00
|
|
|
});
|