mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Updated members API to return subscriptions' offers from the offer_id (#14515)
refs https://github.com/TryGhost/Team/issues/1520 **Changes in members repo** Bumped to `5.12.0`, with the following changes: - Compare differences via https://github.com/TryGhost/Members/compare/%40tryghost/members-api%405.11.1...%40tryghost/members-api%405.12.0 - Instead of doing the matching of the offers and subscriptions by looking at the offer redemptions, we can now look at the offer_id from subscriptions. - This also fixes an issue where we don't attach the offer object to subscriptions in the members' browse method - Updated browse behaviour to match the read behaviour of members (product relation needs to get loaded because it is missing in member.products if the subscription is expired). **Tests** - Includes test to see if the API correctly returns the offer object when fetching one or multiple members - Check if the return format is the same for the read, edit and browse members admin API endpoints (offer was missing in subscriptions) - Snapshot files have been updated because now the offer is returned in subscriptions (content length increased)
This commit is contained in:
parent
9def4e6edc
commit
b9646cceb1
5 changed files with 65 additions and 11 deletions
|
@ -83,7 +83,7 @@
|
|||
"@tryghost/logging": "2.1.5",
|
||||
"@tryghost/magic-link": "1.0.21",
|
||||
"@tryghost/member-events": "0.4.1",
|
||||
"@tryghost/members-api": "5.11.1",
|
||||
"@tryghost/members-api": "5.12.0",
|
||||
"@tryghost/members-events-service": "0.3.3",
|
||||
"@tryghost/members-importer": "0.5.8",
|
||||
"@tryghost/members-offers": "0.11.1",
|
||||
|
|
|
@ -537,7 +537,7 @@ exports[`Members API Can browse 2: [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": "8299",
|
||||
"content-length": "8426",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
|
@ -1126,7 +1126,7 @@ exports[`Members API Can filter by paid status 2: [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": "6764",
|
||||
"content-length": "6891",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
|
@ -1304,7 +1304,7 @@ exports[`Members API Can ignore any unknown includes 2: [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": "6764",
|
||||
"content-length": "6891",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
|
@ -1967,7 +1967,7 @@ exports[`Members API Search for paid members retrieves member with email paid@te
|
|||
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": "1682",
|
||||
"content-length": "1720",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
|
@ -2409,7 +2409,7 @@ exports[`Members API: with multiple newsletters Can browse 2: [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": "8435",
|
||||
"content-length": "8562",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Origin, Accept-Encoding",
|
||||
|
|
|
@ -847,6 +847,8 @@ describe('Members API', function () {
|
|||
});
|
||||
});
|
||||
|
||||
let memberWithPaidSubscription;
|
||||
|
||||
it('Can create a member with an existing paid subscription', async function () {
|
||||
const fakePrice = {
|
||||
id: 'price_1',
|
||||
|
@ -934,6 +936,7 @@ describe('Members API', function () {
|
|||
});
|
||||
|
||||
const newMember = body.members[0];
|
||||
|
||||
assert.equal(newMember.status, 'paid', 'The created member should have the paid status');
|
||||
assert.equal(newMember.subscriptions.length, 1, 'The member should have a single subscription');
|
||||
assert.equal(newMember.subscriptions[0].id, fakeSubscription.id, 'The returned subscription should have an ID assigned');
|
||||
|
@ -980,6 +983,30 @@ describe('Members API', function () {
|
|||
plan_currency: 'usd',
|
||||
mrr: 100
|
||||
});
|
||||
|
||||
// Save this member for the next test
|
||||
memberWithPaidSubscription = newMember;
|
||||
});
|
||||
|
||||
it('Returns an identical member format for read, edit and browse', async function () {
|
||||
if (!memberWithPaidSubscription) {
|
||||
// Previous test failed
|
||||
this.skip();
|
||||
}
|
||||
|
||||
// Check status has been updated to 'free' after cancelling
|
||||
const {body: readBody} = await agent.get('/members/' + memberWithPaidSubscription.id + '/');
|
||||
assert.equal(readBody.members.length, 1, 'The member was not found in read');
|
||||
const readMember = readBody.members[0];
|
||||
|
||||
// Note that we explicitly need to ask to include products while browsing
|
||||
const {body: browseBody} = await agent.get(`/members/?search=${memberWithPaidSubscription.email}&include=products`);
|
||||
assert.equal(browseBody.members.length, 1, 'The member was not found in browse');
|
||||
const browseMember = browseBody.members[0];
|
||||
|
||||
// Check for this member with a paid subscription that the body results for the patch, get and browse endpoints are 100% identical
|
||||
should.deepEqual(browseMember, readMember, 'Browsing a member returns a different format than reading a member');
|
||||
should.deepEqual(memberWithPaidSubscription, readMember, 'Editing a member returns a different format than reading a member');
|
||||
});
|
||||
|
||||
it('Can edit by id', async function () {
|
||||
|
|
|
@ -1203,6 +1203,13 @@ describe('Members API', function () {
|
|||
offer_id: offer_id
|
||||
});
|
||||
|
||||
// Check whether the offer attribute is passed correctly in the response when fetching a single member
|
||||
member.subscriptions[0].should.match({
|
||||
offer: {
|
||||
id: offer_id
|
||||
}
|
||||
});
|
||||
|
||||
await assertMemberEvents({
|
||||
eventType: 'MemberPaidSubscriptionEvent',
|
||||
memberId: member.id,
|
||||
|
@ -1245,7 +1252,10 @@ describe('Members API', function () {
|
|||
assert.equal(updatedMember.products.length, 0, 'The member should have no products');
|
||||
should(updatedMember.subscriptions).match([
|
||||
{
|
||||
status: 'canceled'
|
||||
status: 'canceled',
|
||||
offer: {
|
||||
id: offer_id
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
|
@ -1592,6 +1602,11 @@ describe('Members API', function () {
|
|||
offer_id: null
|
||||
});
|
||||
|
||||
// Check whether the offer attribute is passed correctly in the response when fetching a single member
|
||||
member.subscriptions[0].should.match({
|
||||
offer: null
|
||||
});
|
||||
|
||||
await assertMemberEvents({
|
||||
eventType: 'MemberPaidSubscriptionEvent',
|
||||
memberId: member.id,
|
||||
|
@ -1642,6 +1657,13 @@ describe('Members API', function () {
|
|||
offer_id: offer.id
|
||||
});
|
||||
|
||||
// Check whether the offer attribute is passed correctly in the response when fetching a single member
|
||||
updatedMember.subscriptions[0].should.match({
|
||||
offer: {
|
||||
id: offer.id
|
||||
}
|
||||
});
|
||||
|
||||
await assertMemberEvents({
|
||||
eventType: 'MemberPaidSubscriptionEvent',
|
||||
memberId: updatedMember.id,
|
||||
|
@ -1776,6 +1798,11 @@ describe('Members API', function () {
|
|||
offer_id: null
|
||||
});
|
||||
|
||||
// Check whether the offer attribute is passed correctly in the response when fetching a single member
|
||||
member.subscriptions[0].should.match({
|
||||
offer: null
|
||||
});
|
||||
|
||||
await assertMemberEvents({
|
||||
eventType: 'MemberPaidSubscriptionEvent',
|
||||
memberId: member.id,
|
||||
|
|
|
@ -2009,10 +2009,10 @@
|
|||
"@tryghost/domain-events" "^0.1.9"
|
||||
"@tryghost/member-events" "^0.4.1"
|
||||
|
||||
"@tryghost/members-api@5.11.1":
|
||||
version "5.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/members-api/-/members-api-5.11.1.tgz#5b32fe806d5ce6f5d6743525fda74ea6667ffff4"
|
||||
integrity sha512-yeaC6WpqNA+4qXqpLN5+Yo5ms3R1diMmQe6JnsMcjI6Nuby8ltPJi4uazFd09uFI2b+Bj/yucEzStbkT5lUS4g==
|
||||
"@tryghost/members-api@5.12.0":
|
||||
version "5.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/members-api/-/members-api-5.12.0.tgz#b26389fef5e66602768e953cdc37da6714bd693f"
|
||||
integrity sha512-lczUcc5Vd3WKUaBu4x2aP5y9CqFqqHEFOS5Rh/KvYD6Nu8UDdjxtb6mok9IngH48UG2RS8y3WoWkJFNtSNBfpQ==
|
||||
dependencies:
|
||||
"@nexes/nql" "^0.6.0"
|
||||
"@tryghost/debug" "^0.1.2"
|
||||
|
|
Loading…
Add table
Reference in a new issue