0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-03 23:00:14 -05:00
ghost/test/regression/api/admin/members.test.js
Hannah Wolfe da44ccaf11
Removed querystring dep from members tests
refs: https://github.com/TryGhost/Toolbox/issues/158

- if we had to combine a large list of params then this would make sense
- we could/should also add a .query() method to our agent
- however, I don't think this is worthwhile/necessary for just 2 params right now :)
2022-02-09 21:14:17 +00:00

262 lines
8 KiB
JavaScript

const assert = require('assert');
const {agentProvider, mockManager, fixtureManager, matchers} = require('../../../utils/e2e-framework');
const {anyString, anyArray, anyObjectId, anyEtag, anyUuid, anyErrorId, anyDate} = matchers;
let agent;
const memberMatcherNoIncludes = {
id: anyObjectId,
uuid: anyUuid,
created_at: anyDate,
updated_at: anyDate
};
const memberMatcherShallowIncludes = {
id: anyObjectId,
uuid: anyUuid,
created_at: anyDate,
updated_at: anyDate,
subscriptions: anyArray,
labels: anyArray
};
describe('Members API', function () {
before(async function () {
agent = await agentProvider.getAdminAPIAgent();
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?
await agent
.delete(`members/${body.members[0].id}/`)
.matchHeaderSnapshot({
etag: anyEtag
})
.expectStatus(204);
});
it('Can order by email_open_rate', async function () {
await agent
.get('members/?order=email_open_rate%20desc')
.expectStatus(200)
.matchHeaderSnapshot({
etag: anyEtag
})
.matchBodySnapshot({
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.');
});
await agent
.get('members/?order=email_open_rate%20asc')
.expectStatus(200)
.matchHeaderSnapshot({
etag: anyEtag
})
.matchBodySnapshot({
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 () {
await agent
.get('members/?search=egg')
.expectStatus(200)
.matchBodySnapshot({
members: [memberMatcherShallowIncludes]
})
.matchHeaderSnapshot({
etag: anyEtag
});
});
it('Search by case-insensitive email MEMBER2 receives member with email member2@test.com', async function () {
await agent
.get('members/?search=MEMBER2')
.expectStatus(200)
.matchBodySnapshot({
members: [memberMatcherShallowIncludes]
})
.matchHeaderSnapshot({
etag: anyEtag
});
});
it('Sarch for paid members retrieves member with email paid@test.com', async function () {
await agent
.get('members/?search=egon&paid=true')
.expectStatus(200)
.matchBodySnapshot({
members: [memberMatcherShallowIncludes]
})
.matchHeaderSnapshot({
etag: anyEtag
});
});
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: []
});
});
it('Can update a member with subscription included, change name to "Updated name"', async function () {
const memberChanged = {
name: 'Updated name'
};
const paidMember = fixtureManager.get('members', 2);
await agent
.put(`members/${paidMember.id}/`)
.body({members: [memberChanged]})
.expectStatus(200)
.matchHeaderSnapshot({
etag: anyEtag
})
.matchBodySnapshot({
members: [memberMatcherShallowIncludes]
});
});
it('Add should fail when passing incorrect email_type query parameter', async function () {
const newMember = {
name: 'test',
email: 'memberTestAdd@test.com'
};
await agent
.post(`members/?send_email=true&email_type=lel`)
.body({members: [newMember]})
.expectStatus(422)
.matchHeaderSnapshot({
etag: anyEtag
})
.matchBodySnapshot({
errors: [{
id: anyErrorId
}]
});
});
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 delete a member without cancelling Stripe Subscription', async function () {
const newMember = {
name: 'Member 2 Delete',
email: 'Member2Delete@test.com'
};
// @TODO: use a fixture member in the right state using fixtureManager.get('members', x)
// @TODO: instead of creating a new member as this wastes a request
const createdMember = await agent
.post(`members/`)
.body({members: [newMember]})
.expectStatus(201)
.matchHeaderSnapshot({
etag: anyEtag,
location: anyString
})
.matchBodySnapshot({
members: [
memberMatcherNoIncludes
]
})
.then(({body}) => {
return body.members[0];
});
await agent
.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 () {
await agent
.get('members/stats/?days=nope')
.expectStatus(422)
.matchHeaderSnapshot({
etag: anyEtag
})
.matchBodySnapshot({
errors: [{
id: anyErrorId
}]
});
});
});