mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 03:44:29 +03:00
Added acceptance test for /member/:id/?include=email_recipients
(#12477)
refs c1d66f0b01
- fixed base model allowing '@@INDEXES@@' as a permitted attribute/order
- fixed base model automatically setting `@@INDEXES@@` to null on the model when creating
- added `doAuth('members:emails')`
- creates an `email_batch` record attached to the first email in the fixtures
- creates an `email_recipients` record for each member
- runs analytics aggregation so the email and member counts are as expected
- added acceptance test for `/member/:id/?include=email_recipients`
This commit is contained in:
parent
90adc9ed98
commit
8aa55feaf8
@ -172,13 +172,15 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
|
||||
// Ghost option handling - get permitted attributes from server/data/schema.js, where the DB schema is defined
|
||||
permittedAttributes: function permittedAttributes() {
|
||||
return _.keys(schema.tables[this.tableName]);
|
||||
return _.keys(schema.tables[this.tableName])
|
||||
.filter(key => key.indexOf('@@') === -1);
|
||||
},
|
||||
|
||||
// Ghost ordering handling, allows to order by permitted attributes by default and can be overriden on specific model level
|
||||
orderAttributes: function orderAttributes() {
|
||||
return Object.keys(schema.tables[this.tableName])
|
||||
.map(key => `${this.tableName}.${key}`);
|
||||
.map(key => `${this.tableName}.${key}`)
|
||||
.filter(key => key.indexOf('@@') === -1);
|
||||
},
|
||||
|
||||
// When loading an instance, subclasses can specify default to fetch
|
||||
@ -354,7 +356,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
*
|
||||
* Happens after validation to ensure we don't set fields which are not nullable on db level.
|
||||
*/
|
||||
_.each(Object.keys(schema.tables[this.tableName]), (columnKey) => {
|
||||
_.each(Object.keys(schema.tables[this.tableName]).filter(key => key.indexOf('@@') === -1), (columnKey) => {
|
||||
if (model.get(columnKey) === undefined) {
|
||||
model.set(columnKey, null);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ describe('Members API', function () {
|
||||
before(async function () {
|
||||
await testUtils.startGhost();
|
||||
request = supertest.agent(config.get('url'));
|
||||
await localUtils.doAuth(request, 'members');
|
||||
await localUtils.doAuth(request, 'members', 'members:emails');
|
||||
sinon.stub(labs, 'isSet').withArgs('members').returns(true);
|
||||
});
|
||||
|
||||
@ -123,6 +123,25 @@ describe('Members API', function () {
|
||||
localUtils.API.checkResponse(jsonResponse.members[0], 'member', 'stripe');
|
||||
});
|
||||
|
||||
it('Can read and include email_recipients', async function () {
|
||||
const res = await request
|
||||
.get(localUtils.API.getApiQuery(`members/${testUtils.DataGenerator.Content.members[0].id}/?include=email_recipients`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.members);
|
||||
jsonResponse.members.should.have.length(1);
|
||||
localUtils.API.checkResponse(jsonResponse.members[0], 'member', ['stripe', 'email_recipients']);
|
||||
jsonResponse.members[0].email_recipients.length.should.equal(1);
|
||||
localUtils.API.checkResponse(jsonResponse.members[0].email_recipients[0], 'email_recipient', ['email']);
|
||||
localUtils.API.checkResponse(jsonResponse.members[0].email_recipients[0].email, 'email');
|
||||
});
|
||||
|
||||
it('Can add', async function () {
|
||||
const member = {
|
||||
name: 'test',
|
||||
|
@ -115,6 +115,9 @@ const expectedProperties = {
|
||||
email: _(schema.emails)
|
||||
.keys(),
|
||||
email_preview: ['html', 'subject', 'plaintext'],
|
||||
email_recipient: _(schema.email_recipients)
|
||||
.keys()
|
||||
.filter(key => key.indexOf('@@') === -1),
|
||||
snippet: _(schema.snippets).keys()
|
||||
};
|
||||
|
||||
|
@ -310,23 +310,27 @@ DataGenerator.Content = {
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email: 'member1@test.com',
|
||||
name: 'Mr Egg'
|
||||
name: 'Mr Egg',
|
||||
uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b340'
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email: 'member2@test.com',
|
||||
email_open_rate: 50
|
||||
email_open_rate: 50,
|
||||
uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b341'
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email: 'paid@test.com',
|
||||
name: 'Egon Spengler',
|
||||
email_open_rate: 80
|
||||
email_open_rate: 80,
|
||||
uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b342'
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email: 'trialing@test.com',
|
||||
name: 'Ray Stantz'
|
||||
name: 'Ray Stantz',
|
||||
uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b343'
|
||||
}
|
||||
],
|
||||
|
||||
@ -446,9 +450,11 @@ DataGenerator.Content = {
|
||||
uuid: '6b6afda6-4b5e-4893-bff6-f16859e8349a',
|
||||
status: 'submitted',
|
||||
email_count: 2,
|
||||
recipient_filter: 'all',
|
||||
subject: 'You got mailed!',
|
||||
html: '<p>Look! I\'m an email</p>',
|
||||
plaintext: 'Waba-daba-dab-da',
|
||||
track_opens: false,
|
||||
submitted_at: moment().toDate()
|
||||
},
|
||||
{
|
||||
@ -456,15 +462,72 @@ DataGenerator.Content = {
|
||||
uuid: '365daa11-4bf0-4614-ad43-6346387ffa00',
|
||||
status: 'failed',
|
||||
error: 'Everything went south',
|
||||
stats: '',
|
||||
email_count: 3,
|
||||
subject: 'You got mailed! Again!',
|
||||
html: '<p>What\'s that? Another email!</p>',
|
||||
plaintext: 'yes this is an email',
|
||||
track_opens: false,
|
||||
submitted_at: moment().toDate()
|
||||
}
|
||||
],
|
||||
|
||||
email_batches: [
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email_id: null, // emails[0] relation added later
|
||||
// TODO: cleanup <> in provider_id
|
||||
provider_id: '<email1@testing.mailgun.net>',
|
||||
status: 'submitted'
|
||||
}
|
||||
],
|
||||
|
||||
email_recipients: [
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email_id: null, // emails[0] relation added later
|
||||
member_id: null, // members[0] relation added later
|
||||
batch_id: null, // email_batches[0] relation added later
|
||||
processed_at: moment().toDate(),
|
||||
failed_at: null,
|
||||
member_uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b340',
|
||||
member_email: 'member1@test.com',
|
||||
member_name: 'Mr Egg'
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email_id: null, // emails[0] relation added later
|
||||
member_id: null, // members[1] relation added later
|
||||
batch_id: null, // email_batches[0] relation added later
|
||||
processed_at: moment().toDate(),
|
||||
failed_at: null,
|
||||
member_uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b341',
|
||||
member_email: 'member2@test.com',
|
||||
member_name: null
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email_id: null, // emails[0] relation added later
|
||||
member_id: null, // members[2] relation added later
|
||||
batch_id: null, // email_batches[0] relation added later
|
||||
processed_at: moment().toDate(),
|
||||
failed_at: null,
|
||||
member_uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b342',
|
||||
member_email: 'member1@test.com',
|
||||
member_name: 'Mr Egg'
|
||||
},
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
email_id: null, // emails[0] relation added later
|
||||
member_id: null, // members[3] relation added later
|
||||
batch_id: null, // email_batches[0] relation added later
|
||||
processed_at: moment().toDate(),
|
||||
failed_at: null,
|
||||
member_uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b343',
|
||||
member_email: 'member1@test.com',
|
||||
member_name: 'Mr Egg'
|
||||
}
|
||||
],
|
||||
|
||||
snippets: [
|
||||
{
|
||||
id: ObjectId.generate(),
|
||||
@ -480,6 +543,19 @@ DataGenerator.Content.api_keys[0].integration_id = DataGenerator.Content.integra
|
||||
DataGenerator.Content.api_keys[1].integration_id = DataGenerator.Content.integrations[0].id;
|
||||
DataGenerator.Content.emails[0].post_id = DataGenerator.Content.posts[0].id;
|
||||
DataGenerator.Content.emails[1].post_id = DataGenerator.Content.posts[1].id;
|
||||
DataGenerator.Content.email_batches[0].email_id = DataGenerator.Content.emails[0].id;
|
||||
DataGenerator.Content.email_recipients[0].batch_id = DataGenerator.Content.email_batches[0].id;
|
||||
DataGenerator.Content.email_recipients[0].email_id = DataGenerator.Content.email_batches[0].email_id;
|
||||
DataGenerator.Content.email_recipients[0].member_id = DataGenerator.Content.members[0].id;
|
||||
DataGenerator.Content.email_recipients[1].batch_id = DataGenerator.Content.email_batches[0].id;
|
||||
DataGenerator.Content.email_recipients[1].email_id = DataGenerator.Content.email_batches[0].email_id;
|
||||
DataGenerator.Content.email_recipients[1].member_id = DataGenerator.Content.members[1].id;
|
||||
DataGenerator.Content.email_recipients[2].batch_id = DataGenerator.Content.email_batches[0].id;
|
||||
DataGenerator.Content.email_recipients[2].email_id = DataGenerator.Content.email_batches[0].email_id;
|
||||
DataGenerator.Content.email_recipients[2].member_id = DataGenerator.Content.members[2].id;
|
||||
DataGenerator.Content.email_recipients[3].batch_id = DataGenerator.Content.email_batches[0].id;
|
||||
DataGenerator.Content.email_recipients[3].email_id = DataGenerator.Content.email_batches[0].email_id;
|
||||
DataGenerator.Content.email_recipients[3].member_id = DataGenerator.Content.members[3].id;
|
||||
DataGenerator.Content.members_stripe_customers[0].member_id = DataGenerator.Content.members[2].id;
|
||||
DataGenerator.Content.members_stripe_customers[1].member_id = DataGenerator.Content.members[3].id;
|
||||
|
||||
@ -758,6 +834,22 @@ DataGenerator.forKnex = (function () {
|
||||
});
|
||||
}
|
||||
|
||||
function createEmailBatch(overrides) {
|
||||
const newObj = _.cloneDeep(overrides);
|
||||
return _.defaults(newObj, {
|
||||
id: ObjectId.generate(),
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
});
|
||||
}
|
||||
|
||||
function createEmailRecipient(overrides) {
|
||||
const newObj = _.cloneDeep(overrides);
|
||||
return _.defaults(newObj, {
|
||||
id: ObjectId.generate()
|
||||
});
|
||||
}
|
||||
|
||||
const posts = [
|
||||
createPost(DataGenerator.Content.posts[0]),
|
||||
createPost(DataGenerator.Content.posts[1]),
|
||||
@ -965,6 +1057,17 @@ DataGenerator.forKnex = (function () {
|
||||
createEmail(DataGenerator.Content.emails[1])
|
||||
];
|
||||
|
||||
const email_batches = [
|
||||
createEmailBatch(DataGenerator.Content.email_batches[0])
|
||||
];
|
||||
|
||||
const email_recipients = [
|
||||
createEmailRecipient(DataGenerator.Content.email_recipients[0]),
|
||||
createEmailRecipient(DataGenerator.Content.email_recipients[1]),
|
||||
createEmailRecipient(DataGenerator.Content.email_recipients[2]),
|
||||
createEmailRecipient(DataGenerator.Content.email_recipients[3])
|
||||
];
|
||||
|
||||
const members = [
|
||||
createMember(DataGenerator.Content.members[0]),
|
||||
createMember(DataGenerator.Content.members[1]),
|
||||
@ -1035,6 +1138,8 @@ DataGenerator.forKnex = (function () {
|
||||
integrations,
|
||||
api_keys,
|
||||
emails,
|
||||
email_batches,
|
||||
email_recipients,
|
||||
labels,
|
||||
members,
|
||||
members_labels,
|
||||
|
@ -22,6 +22,7 @@ const routingService = require('../../core/frontend/services/routing');
|
||||
const settingsService = require('../../core/server/services/settings');
|
||||
const frontendSettingsService = require('../../core/frontend/services/settings');
|
||||
const settingsCache = require('../../core/server/services/settings/cache');
|
||||
const emailAnalyticsService = require('../../core/server/services/email-analytics');
|
||||
const imageLib = require('../../core/server/lib/image');
|
||||
const web = require('../../core/server/web');
|
||||
const permissions = require('../../core/server/services/permissions');
|
||||
@ -501,6 +502,27 @@ fixtures = {
|
||||
});
|
||||
},
|
||||
|
||||
insertEmailsAndRecipients: function insertEmailsAndRecipients() {
|
||||
return Promise.each(_.cloneDeep(DataGenerator.forKnex.emails), function (email) {
|
||||
return models.Email.add(email, module.exports.context.internal);
|
||||
}).then(function () {
|
||||
return Promise.each(_.cloneDeep(DataGenerator.forKnex.email_batches), function (emailBatch) {
|
||||
return models.EmailBatch.add(emailBatch, module.exports.context.internal);
|
||||
});
|
||||
}).then(function () {
|
||||
return Promise.each(_.cloneDeep(DataGenerator.forKnex.email_recipients), (emailRecipient) => {
|
||||
return models.EmailRecipient.add(emailRecipient, module.exports.context.internal);
|
||||
});
|
||||
}).then(function () {
|
||||
const toAggregate = {
|
||||
emailIds: DataGenerator.forKnex.emails.map(email => email.id),
|
||||
memberIds: DataGenerator.forKnex.members.map(member => member.id)
|
||||
};
|
||||
|
||||
return emailAnalyticsService.aggregateStats(toAggregate);
|
||||
});
|
||||
},
|
||||
|
||||
insertSnippets: function insertSnippets() {
|
||||
return Promise.map(DataGenerator.forKnex.snippets, function (snippet) {
|
||||
return models.Snippet.add(snippet, module.exports.context.internal);
|
||||
@ -576,6 +598,9 @@ toDoList = {
|
||||
members: function insertMembersAndLabels() {
|
||||
return fixtures.insertMembersAndLabels();
|
||||
},
|
||||
'members:emails': function insertEmailsAndRecipients() {
|
||||
return fixtures.insertEmailsAndRecipients();
|
||||
},
|
||||
posts: function insertPostsAndTags() {
|
||||
return fixtures.insertPostsAndTags();
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user