mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-06 22:40:14 -05:00
Added stripe test assertions (#14150)
We've split the tests into two describes, one for when Stripe is enabled and one without, because we setup Stripe in the before method. We use nock to mock the Stripe server and assert that there is no call to delete the subscription.
This commit is contained in:
parent
2b241b4e6a
commit
dc78d273c3
2 changed files with 1693 additions and 216 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,5 @@
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const nock = require('nock');
|
||||||
const {agentProvider, mockManager, fixtureManager, matchers} = require('../../../utils/e2e-framework');
|
const {agentProvider, mockManager, fixtureManager, matchers} = require('../../../utils/e2e-framework');
|
||||||
const {anyString, anyArray, anyObjectId, anyEtag, anyUuid, anyErrorId, anyDate} = matchers;
|
const {anyString, anyArray, anyObjectId, anyEtag, anyUuid, anyErrorId, anyDate} = matchers;
|
||||||
|
|
||||||
|
@ -21,242 +22,263 @@ const memberMatcherShallowIncludes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Members API', function () {
|
describe('Members API', function () {
|
||||||
before(async function () {
|
describe('without Stripe', function () {
|
||||||
agent = await agentProvider.getAdminAPIAgent();
|
before(async function () {
|
||||||
await fixtureManager.init('members');
|
agent = await agentProvider.getAdminAPIAgent();
|
||||||
await agent.loginAsOwner();
|
await fixtureManager.init('members');
|
||||||
});
|
await agent.loginAsOwner();
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockManager.mockLabsEnabled('members');
|
|
||||||
mockManager.mockMail();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
mockManager.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can add and send a signup confirmation email', async function () {
|
|
||||||
const member = {
|
|
||||||
name: 'Send Me Confirmation',
|
|
||||||
email: 'member_getting_confirmation@test.com',
|
|
||||||
subscribed: true
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryParams = {
|
|
||||||
send_email: true,
|
|
||||||
email_type: 'signup'
|
|
||||||
};
|
|
||||||
|
|
||||||
const {body} = await agent
|
|
||||||
.post('/members/?send_email=true&email_type=signup')
|
|
||||||
.body({members: [member]})
|
|
||||||
.expectStatus(201)
|
|
||||||
.matchBodySnapshot({
|
|
||||||
members: [memberMatcherNoIncludes]
|
|
||||||
})
|
|
||||||
.matchHeaderSnapshot({
|
|
||||||
etag: anyEtag,
|
|
||||||
location: anyString
|
|
||||||
});
|
|
||||||
|
|
||||||
mockManager.assert.sentEmail({
|
|
||||||
subject: '🙌 Complete your sign up to Ghost!',
|
|
||||||
to: 'member_getting_confirmation@test.com'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// @TODO: do we really need to delete this member here?
|
beforeEach(function () {
|
||||||
await agent
|
mockManager.mockLabsEnabled('members');
|
||||||
.delete(`members/${body.members[0].id}/`)
|
mockManager.mockMail();
|
||||||
.matchHeaderSnapshot({
|
});
|
||||||
etag: anyEtag
|
|
||||||
})
|
afterEach(function () {
|
||||||
.expectStatus(204);
|
mockManager.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Add should fail when comped flag is passed in but Stripe is not enabled', async function () {
|
||||||
|
const newMember = {
|
||||||
|
email: 'memberTestAdd@test.com',
|
||||||
|
comped: true
|
||||||
|
};
|
||||||
|
|
||||||
|
await agent
|
||||||
|
.post(`members/`)
|
||||||
|
.body({members: [newMember]})
|
||||||
|
.expectStatus(422)
|
||||||
|
.matchHeaderSnapshot({
|
||||||
|
etag: anyEtag
|
||||||
|
})
|
||||||
|
.matchBodySnapshot({
|
||||||
|
errors: [{
|
||||||
|
id: anyErrorId
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can order by email_open_rate', async function () {
|
describe('Members API with Stripe', function () {
|
||||||
await agent
|
before(async function () {
|
||||||
.get('members/?order=email_open_rate%20desc')
|
mockManager.setupStripe();
|
||||||
.expectStatus(200)
|
agent = await agentProvider.getAdminAPIAgent();
|
||||||
.matchHeaderSnapshot({
|
await fixtureManager.init('members');
|
||||||
etag: anyEtag
|
await agent.loginAsOwner();
|
||||||
})
|
});
|
||||||
.matchBodySnapshot({
|
|
||||||
members: new Array(8).fill(memberMatcherShallowIncludes)
|
beforeEach(function () {
|
||||||
})
|
mockManager.mockLabsEnabled('members');
|
||||||
.expect(({body}) => {
|
mockManager.mockMail();
|
||||||
const {members} = body;
|
mockManager.mockStripe();
|
||||||
assert.equal(members[0].email_open_rate > members[1].email_open_rate, true, 'Expected the first member to have a greater open rate than the second.');
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
mockManager.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can add and send a signup confirmation email', async function () {
|
||||||
|
const member = {
|
||||||
|
name: 'Send Me Confirmation',
|
||||||
|
email: 'member_getting_confirmation@test.com',
|
||||||
|
subscribed: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const queryParams = {
|
||||||
|
send_email: true,
|
||||||
|
email_type: 'signup'
|
||||||
|
};
|
||||||
|
|
||||||
|
const {body} = await agent
|
||||||
|
.post('/members/?send_email=true&email_type=signup')
|
||||||
|
.body({members: [member]})
|
||||||
|
.expectStatus(201)
|
||||||
|
.matchBodySnapshot({
|
||||||
|
members: [memberMatcherNoIncludes]
|
||||||
|
})
|
||||||
|
.matchHeaderSnapshot({
|
||||||
|
etag: anyEtag,
|
||||||
|
location: anyString
|
||||||
|
});
|
||||||
|
|
||||||
|
mockManager.assert.sentEmail({
|
||||||
|
subject: '🙌 Complete your sign up to Ghost!',
|
||||||
|
to: 'member_getting_confirmation@test.com'
|
||||||
});
|
});
|
||||||
|
|
||||||
await agent
|
// @TODO: do we really need to delete this member here?
|
||||||
.get('members/?order=email_open_rate%20asc')
|
await agent
|
||||||
.expectStatus(200)
|
.delete(`members/${body.members[0].id}/`)
|
||||||
.matchHeaderSnapshot({
|
.matchHeaderSnapshot({
|
||||||
etag: anyEtag
|
etag: anyEtag
|
||||||
})
|
})
|
||||||
.matchBodySnapshot({
|
.expectStatus(204);
|
||||||
members: new Array(8).fill(memberMatcherShallowIncludes)
|
});
|
||||||
})
|
|
||||||
.expect(({body}) => {
|
|
||||||
const {members} = body;
|
|
||||||
assert.equal(members[0].email_open_rate < members[1].email_open_rate, true, 'Expected the first member to have a smaller open rate than the second.');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Sarch by case-insensitive name egg receives member with name Mr Egg', async function () {
|
it('Can order by email_open_rate', async function () {
|
||||||
await agent
|
await agent
|
||||||
.get('members/?search=egg')
|
.get('members/?order=email_open_rate%20desc')
|
||||||
.expectStatus(200)
|
.expectStatus(200)
|
||||||
.matchBodySnapshot({
|
.matchHeaderSnapshot({
|
||||||
members: [memberMatcherShallowIncludes]
|
etag: anyEtag
|
||||||
})
|
})
|
||||||
.matchHeaderSnapshot({
|
.matchBodySnapshot({
|
||||||
etag: anyEtag
|
members: new Array(8).fill(memberMatcherShallowIncludes)
|
||||||
});
|
})
|
||||||
});
|
.expect(({body}) => {
|
||||||
|
const {members} = body;
|
||||||
|
assert.equal(members[0].email_open_rate > members[1].email_open_rate, true, 'Expected the first member to have a greater open rate than the second.');
|
||||||
|
});
|
||||||
|
|
||||||
it('Search by case-insensitive email MEMBER2 receives member with email member2@test.com', async function () {
|
await agent
|
||||||
await agent
|
.get('members/?order=email_open_rate%20asc')
|
||||||
.get('members/?search=MEMBER2')
|
.expectStatus(200)
|
||||||
.expectStatus(200)
|
.matchHeaderSnapshot({
|
||||||
.matchBodySnapshot({
|
etag: anyEtag
|
||||||
members: [memberMatcherShallowIncludes]
|
})
|
||||||
})
|
.matchBodySnapshot({
|
||||||
.matchHeaderSnapshot({
|
members: new Array(8).fill(memberMatcherShallowIncludes)
|
||||||
etag: anyEtag
|
})
|
||||||
});
|
.expect(({body}) => {
|
||||||
});
|
const {members} = body;
|
||||||
|
assert.equal(members[0].email_open_rate < members[1].email_open_rate, true, 'Expected the first member to have a smaller open rate than the second.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Sarch for paid members retrieves member with email paid@test.com', async function () {
|
it('Sarch by case-insensitive name egg receives member with name Mr Egg', async function () {
|
||||||
await agent
|
await agent
|
||||||
.get('members/?search=egon&paid=true')
|
.get('members/?search=egg')
|
||||||
.expectStatus(200)
|
.expectStatus(200)
|
||||||
.matchBodySnapshot({
|
.matchBodySnapshot({
|
||||||
members: [memberMatcherShallowIncludes]
|
members: [memberMatcherShallowIncludes]
|
||||||
})
|
})
|
||||||
.matchHeaderSnapshot({
|
.matchHeaderSnapshot({
|
||||||
etag: anyEtag
|
etag: anyEtag
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Search for non existing member returns empty result set', async function () {
|
it('Search by case-insensitive email MEMBER2 receives member with email member2@test.com', async function () {
|
||||||
await agent
|
await agent
|
||||||
.get('members/?search=do_not_exist')
|
.get('members/?search=MEMBER2')
|
||||||
.expectStatus(200)
|
.expectStatus(200)
|
||||||
.matchHeaderSnapshot({
|
.matchBodySnapshot({
|
||||||
etag: anyEtag
|
members: [memberMatcherShallowIncludes]
|
||||||
})
|
})
|
||||||
.matchBodySnapshot({
|
.matchHeaderSnapshot({
|
||||||
members: []
|
etag: anyEtag
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can update a member with subscription included, change name to "Updated name"', async function () {
|
it('Sarch for paid members retrieves member with email paid@test.com', async function () {
|
||||||
const memberChanged = {
|
await agent
|
||||||
name: 'Updated name'
|
.get('members/?search=egon&paid=true')
|
||||||
};
|
.expectStatus(200)
|
||||||
|
.matchBodySnapshot({
|
||||||
|
members: [memberMatcherShallowIncludes]
|
||||||
|
})
|
||||||
|
.matchHeaderSnapshot({
|
||||||
|
etag: anyEtag
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const paidMember = fixtureManager.get('members', 2);
|
it('Search for non existing member returns empty result set', async function () {
|
||||||
|
await agent
|
||||||
|
.get('members/?search=do_not_exist')
|
||||||
|
.expectStatus(200)
|
||||||
|
.matchHeaderSnapshot({
|
||||||
|
etag: anyEtag
|
||||||
|
})
|
||||||
|
.matchBodySnapshot({
|
||||||
|
members: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
await agent
|
it('Can update a member with subscription included, change name to "Updated name"', async function () {
|
||||||
.put(`members/${paidMember.id}/`)
|
const memberChanged = {
|
||||||
.body({members: [memberChanged]})
|
name: 'Updated name'
|
||||||
.expectStatus(200)
|
};
|
||||||
.matchHeaderSnapshot({
|
|
||||||
etag: anyEtag
|
|
||||||
})
|
|
||||||
.matchBodySnapshot({
|
|
||||||
members: [memberMatcherShallowIncludes]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Add should fail when passing incorrect email_type query parameter', async function () {
|
const paidMember = fixtureManager.get('members', 2);
|
||||||
const newMember = {
|
|
||||||
name: 'test',
|
|
||||||
email: 'memberTestAdd@test.com'
|
|
||||||
};
|
|
||||||
|
|
||||||
await agent
|
await agent
|
||||||
.post(`members/?send_email=true&email_type=lel`)
|
.put(`members/${paidMember.id}/`)
|
||||||
.body({members: [newMember]})
|
.body({members: [memberChanged]})
|
||||||
.expectStatus(422)
|
.expectStatus(200)
|
||||||
.matchHeaderSnapshot({
|
.matchHeaderSnapshot({
|
||||||
etag: anyEtag
|
etag: anyEtag
|
||||||
})
|
})
|
||||||
.matchBodySnapshot({
|
.matchBodySnapshot({
|
||||||
errors: [{
|
members: [memberMatcherShallowIncludes]
|
||||||
id: anyErrorId
|
});
|
||||||
}]
|
});
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Add should fail when comped flag is passed in but Stripe is not enabled', async function () {
|
it('Add should fail when passing incorrect email_type query parameter', async function () {
|
||||||
const newMember = {
|
const newMember = {
|
||||||
email: 'memberTestAdd@test.com',
|
name: 'test',
|
||||||
comped: true
|
email: 'memberTestAdd@test.com'
|
||||||
};
|
};
|
||||||
|
|
||||||
await agent
|
await agent
|
||||||
.post(`members/`)
|
.post(`members/?send_email=true&email_type=lel`)
|
||||||
.body({members: [newMember]})
|
.body({members: [newMember]})
|
||||||
.expectStatus(422)
|
.expectStatus(422)
|
||||||
.matchHeaderSnapshot({
|
.matchHeaderSnapshot({
|
||||||
etag: anyEtag
|
etag: anyEtag
|
||||||
})
|
})
|
||||||
.matchBodySnapshot({
|
.matchBodySnapshot({
|
||||||
errors: [{
|
errors: [{
|
||||||
id: anyErrorId
|
id: anyErrorId
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can delete a member without cancelling Stripe Subscription', async function () {
|
it('Can delete a member without cancelling Stripe Subscription', async function () {
|
||||||
const newMember = {
|
let subscriptionCanceled = false;
|
||||||
name: 'Member 2 Delete',
|
nock('https://api.stripe.com')
|
||||||
email: 'Member2Delete@test.com'
|
.persist()
|
||||||
};
|
.delete(/v1\/.*/)
|
||||||
|
.reply((uri) => {
|
||||||
|
const [match, resource, id] = uri.match(/\/?v1\/(\w+)\/?(\w+)/) || [null];
|
||||||
|
|
||||||
// @TODO: use a fixture member in the right state using fixtureManager.get('members', x)
|
if (match && resource === 'subscriptions') {
|
||||||
// @TODO: instead of creating a new member as this wastes a request
|
subscriptionCanceled = true;
|
||||||
const createdMember = await agent
|
return [200, {
|
||||||
.post(`members/`)
|
id,
|
||||||
.body({members: [newMember]})
|
status: 'canceled'
|
||||||
.expectStatus(201)
|
}];
|
||||||
.matchHeaderSnapshot({
|
}
|
||||||
etag: anyEtag,
|
|
||||||
location: anyString
|
|
||||||
})
|
|
||||||
.matchBodySnapshot({
|
|
||||||
members: [
|
|
||||||
memberMatcherNoIncludes
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.then(({body}) => {
|
|
||||||
return body.members[0];
|
|
||||||
});
|
|
||||||
|
|
||||||
await agent
|
return [500];
|
||||||
.delete(`members/${createdMember.id}/`)
|
});
|
||||||
.expectStatus(204)
|
|
||||||
.matchHeaderSnapshot({
|
|
||||||
etag: anyEtag
|
|
||||||
})
|
|
||||||
.matchBodySnapshot();
|
|
||||||
// @TODO: assert side effect - stripe subscription is not cancelled
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Errors when fetching stats with unknown days param value', async function () {
|
// TODO This is wrong because it changes the state for teh rest of the tests
|
||||||
await agent
|
// We need to add a member via a fixture and then remove them OR work out how
|
||||||
.get('members/stats/?days=nope')
|
// to reapply fixtures before each test
|
||||||
.expectStatus(422)
|
const memberToDelete = fixtureManager.get('members', 2);
|
||||||
.matchHeaderSnapshot({
|
|
||||||
etag: anyEtag
|
await agent
|
||||||
})
|
.delete(`members/${memberToDelete.id}/`)
|
||||||
.matchBodySnapshot({
|
.expectStatus(204)
|
||||||
errors: [{
|
.matchHeaderSnapshot({
|
||||||
id: anyErrorId
|
etag: anyEtag
|
||||||
}]
|
})
|
||||||
});
|
.matchBodySnapshot();
|
||||||
|
|
||||||
|
assert.equal(subscriptionCanceled, false, 'expected subscription not to be canceled');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Errors when fetching stats with unknown days param value', async function () {
|
||||||
|
await agent
|
||||||
|
.get('members/stats/?days=nope')
|
||||||
|
.expectStatus(422)
|
||||||
|
.matchHeaderSnapshot({
|
||||||
|
etag: anyEtag
|
||||||
|
})
|
||||||
|
.matchBodySnapshot({
|
||||||
|
errors: [{
|
||||||
|
id: anyErrorId
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue