0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

Added newsletter relation to subscribe events (#14585)

refs https://github.com/TryGhost/Team/issues/1478

**Changes**
- Added the newsletter relation to subscribe events

**Changes in `members-api`**
- Compare: https://github.com/TryGhost/Members/compare/%40tryghost/members-api%406.0.0-alpha.0...%40tryghost/members-api%406.0.0
- Makes sure the newsletter relation is returned in the activity feed for susbcribe events (aka newsletter events).

**Tests**
- Added first test for activity feed to check if the newsletter relation is correctly fetched
This commit is contained in:
Simon Backx 2022-04-27 16:44:27 +02:00 committed by GitHub
parent d94859f2e5
commit 2cf76cb031
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 222 additions and 9 deletions

View file

@ -8,6 +8,10 @@ const MemberSubscribeEvent = ghostBookshelf.Model.extend({
return this.belongsTo('Member', 'member_id', 'id');
},
newsletter() {
return this.belongsTo('Newsletter', 'newsletter_id', 'id');
},
customQuery(qb, options) {
if (options.aggregateSubscriptionDeltas) {
if (options.limit || options.filter) {

View file

@ -84,7 +84,7 @@
"@tryghost/logging": "2.1.8",
"@tryghost/magic-link": "1.0.21",
"@tryghost/member-events": "0.4.1",
"@tryghost/members-api": "6.0.0-alpha.0",
"@tryghost/members-api": "6.0.0",
"@tryghost/members-events-service": "0.3.3",
"@tryghost/members-importer": "0.5.8",
"@tryghost/members-offers": "0.11.1",

View file

@ -2289,6 +2289,148 @@ Object {
}
`;
exports[`Members API Can subscribe to a newsletter 5: [body] 1`] = `
Object {
"events": Array [
Object {
"data": Object {
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"member": Object {
"avatar_image": null,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"email": "member3change@test.com",
"email_count": 0,
"email_open_rate": null,
"email_opened_count": 0,
"geolocation": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"last_seen_at": null,
"name": "change me",
"note": null,
"status": "free",
"subscribed": true,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"uuid": "afd6010c-53ab-4e33-a1f0-600d942fa1ae",
},
"member_id": "6267babe96506b05ae3a6285",
"newsletter_id": "6267babd96506b05ae3a6050",
"source": "admin",
"subscribed": true,
},
"type": Any<String>,
},
Object {
"data": Object {
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"member": Object {
"avatar_image": null,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"email": "member3change@test.com",
"email_count": 0,
"email_open_rate": null,
"email_opened_count": 0,
"geolocation": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"last_seen_at": null,
"name": "change me",
"note": null,
"status": "free",
"subscribed": true,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"uuid": "afd6010c-53ab-4e33-a1f0-600d942fa1ae",
},
"member_id": "6267babe96506b05ae3a6285",
"newsletter_id": "6267baba96506b05ae3a5db9",
"source": "admin",
"subscribed": true,
},
"type": Any<String>,
},
Object {
"data": Object {
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"member": Object {
"avatar_image": null,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"email": "member3change@test.com",
"email_count": 0,
"email_open_rate": null,
"email_opened_count": 0,
"geolocation": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"last_seen_at": null,
"name": "change me",
"note": null,
"status": "free",
"subscribed": true,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"uuid": "afd6010c-53ab-4e33-a1f0-600d942fa1ae",
},
"member_id": "6267babe96506b05ae3a6285",
"newsletter_id": "6267babd96506b05ae3a6050",
"source": "admin",
"subscribed": false,
},
"type": Any<String>,
},
Object {
"data": Object {
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"from_status": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"member": Object {
"avatar_image": null,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"email": "member3change@test.com",
"email_count": 0,
"email_open_rate": null,
"email_opened_count": 0,
"geolocation": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"last_seen_at": null,
"name": "change me",
"note": null,
"status": "free",
"subscribed": true,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"uuid": "afd6010c-53ab-4e33-a1f0-600d942fa1ae",
},
"member_id": "6267babe96506b05ae3a6285",
"to_status": "free",
},
"type": Any<String>,
},
],
}
`;
exports[`Members API Can subscribe to a newsletter 5: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "4398",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Members API Can subscribe to a newsletter 6: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "2425",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Members API Errors when fetching stats with unknown days param value 1: [body] 1`] = `
Object {
"errors": Array [

View file

@ -117,6 +117,7 @@ describe('Members API', function () {
beforeEach(function () {
mockManager.mockLabsEnabled('multipleProducts');
mockManager.mockLabsEnabled('multipleNewsletters');
mockManager.mockLabsEnabled('membersActivityFeed');
mockManager.mockStripe();
mockManager.mockMail();
});
@ -1190,6 +1191,7 @@ describe('Members API', function () {
});
it('Can subscribe to a newsletter', async function () {
const clock = sinon.useFakeTimers(Date.now());
const memberToChange = {
name: 'change me',
email: 'member3change@test.com',
@ -1216,6 +1218,8 @@ describe('Members API', function () {
location: anyLocationFor('members')
});
const newMember = body.members[0];
const before = new Date();
before.setMilliseconds(0);
await assertMemberEvents({
eventType: 'MemberSubscribeEvent',
@ -1223,9 +1227,16 @@ describe('Members API', function () {
asserts: [{
subscribed: true,
source: 'admin',
newsletter_id: newsletters[0].id
newsletter_id: newsletters[0].id,
created_at: before
}]
});
// Wait 5 second sto guarantee event ordering
clock.tick(5000);
const after = new Date();
after.setMilliseconds(0);
await agent
.put(`/members/${newMember.id}/`)
@ -1245,18 +1256,74 @@ describe('Members API', function () {
{
subscribed: true,
source: 'admin',
newsletter_id: newsletters[0].id
newsletter_id: newsletters[0].id,
created_at: before
}, {
subscribed: true,
source: 'admin',
newsletter_id: newsletters[1].id
newsletter_id: newsletters[1].id,
created_at: after
}, {
subscribed: false,
source: 'admin',
newsletter_id: newsletters[0].id
newsletter_id: newsletters[0].id,
created_at: after
}
]
});
clock.tick(5000);
// Check activity feed
const {body: eventsBody} = await agent
.get(`/members/events?filter=data.member_id:${newMember.id}`)
.body({members: [memberChanged]})
.expectStatus(200)
.matchHeaderSnapshot({
etag: anyEtag
});
const events = eventsBody.events;
events.should.match([
{
type: 'newsletter_event',
data: {
subscribed: true,
source: 'admin',
newsletter_id: newsletters[1].id,
newsletter: {
id: newsletters[1].id
}
}
},
{
type: 'newsletter_event',
data: {
subscribed: false,
source: 'admin',
newsletter_id: newsletters[0].id,
newsletter: {
id: newsletters[0].id
}
}
},
{
type: 'newsletter_event',
data: {
subscribed: true,
source: 'admin',
newsletter_id: newsletters[0].id,
newsletter: {
id: newsletters[0].id
}
}
},
{
type: 'signup_event'
}
]);
clock.restore();
});
it('Subscribes to default newsletters', async function () {

View file

@ -2150,10 +2150,10 @@
"@tryghost/domain-events" "^0.1.9"
"@tryghost/member-events" "^0.4.1"
"@tryghost/members-api@6.0.0-alpha.0":
version "6.0.0-alpha.0"
resolved "https://registry.yarnpkg.com/@tryghost/members-api/-/members-api-6.0.0-alpha.0.tgz#91f99cc7076c612ccb84d8b8dd6135246968b842"
integrity sha512-qV7WEK7GZ3ejenIThj8+bSUa7ubKSN5iqB0LZXXFwihEWaySheZhNXhNJda6e1MiZwQYqQBH1TrVuv4hKfRwCA==
"@tryghost/members-api@6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@tryghost/members-api/-/members-api-6.0.0.tgz#935aee6298154176424c0574d73e290006d67221"
integrity sha512-fMsqb5Tuegw8DBhu9Hdwl/mldzIpZJgor63ub3P4TtRWlF5uNQIAaUi/w8AOQDmTSbkMm3YSXNkescPWBocdkw==
dependencies:
"@nexes/nql" "^0.6.0"
"@tryghost/debug" "^0.1.2"