Added E2E tests for bulk post API

refs https://github.com/TryGhost/Team/issues/2925
This commit is contained in:
Simon Backx 2023-04-27 12:45:24 +02:00
parent ec5ee76d0b
commit 57557cb2f7
5 changed files with 445 additions and 3 deletions

View File

@ -52,6 +52,16 @@ module.exports = {
},
bulkDestroy(bulkActionResult, _apiConfig, frame) {
frame.response = bulkActionResult;
frame.response = {
bulk: {
meta: {
stats: {
successful: bulkActionResult.successful,
unsuccessful: bulkActionResult.unsuccessful
},
errors: bulkActionResult.errors
}
}
};
}
};

View File

@ -56,6 +56,16 @@ module.exports = {
},
bulkDestroy(bulkActionResult, _apiConfig, frame) {
frame.response = bulkActionResult;
frame.response = {
bulk: {
meta: {
stats: {
successful: bulkActionResult.successful,
unsuccessful: bulkActionResult.unsuccessful
},
errors: bulkActionResult.errors
}
}
};
}
};

View File

@ -0,0 +1,115 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Posts Bulk API Delete Can delete all posts 1: [body] 1`] = `
Object {
"bulk": Object {
"meta": Object {
"errors": Array [],
"stats": Object {
"successful": 2,
"unsuccessful": 0,
},
},
},
}
`;
exports[`Posts Bulk API Delete Can delete posts that match a tag 1: [body] 1`] = `
Object {
"bulk": Object {
"meta": Object {
"errors": Array [],
"stats": Object {
"successful": 11,
"unsuccessful": 0,
},
},
},
}
`;
exports[`Posts Bulk API Edit Can add a single tag to posts 1: [body] 1`] = `
Object {
"bulk": Object {
"meta": Object {
"stats": Object {
"successful": 11,
"unsuccessful": 0,
},
},
},
}
`;
exports[`Posts Bulk API Edit Can add multiple tags to posts and create new tags 1: [body] 1`] = `
Object {
"bulk": Object {
"meta": Object {
"stats": Object {
"successful": 1,
"unsuccessful": 0,
},
},
},
}
`;
exports[`Posts Bulk API Edit Can change access of posts 1: [body] 1`] = `
Object {
"bulk": Object {
"meta": Object {
"errors": Array [],
"stats": Object {
"successful": 13,
"unsuccessful": 0,
},
"unsuccessfulData": Array [],
},
},
}
`;
exports[`Posts Bulk API Edit Can change access of posts to tiers 1: [body] 1`] = `
Object {
"bulk": Object {
"meta": Object {
"errors": Array [],
"stats": Object {
"successful": 13,
"unsuccessful": 0,
},
"unsuccessfulData": Array [],
},
},
}
`;
exports[`Posts Bulk API Edit Can feature multiple posts 1: [body] 1`] = `
Object {
"bulk": Object {
"meta": Object {
"errors": Array [],
"stats": Object {
"successful": 13,
"unsuccessful": 0,
},
"unsuccessfulData": Array [],
},
},
}
`;
exports[`Posts Bulk API Edit Can unfeature multiple posts 1: [body] 1`] = `
Object {
"bulk": Object {
"meta": Object {
"errors": Array [],
"stats": Object {
"successful": 13,
"unsuccessful": 0,
},
"unsuccessfulData": Array [],
},
},
}
`;

View File

@ -0,0 +1,304 @@
const {agentProvider, fixtureManager, mockManager} = require('../../utils/e2e-framework');
const models = require('../../../core/server/models');
const assert = require('assert');
describe('Posts Bulk API', function () {
let agent;
before(async function () {
agent = await agentProvider.getAdminAPIAgent();
// Note that we generate lots of fixtures here to test the bulk deletion correctly
await fixtureManager.init('posts', 'newsletters', 'members:newsletters', 'emails', 'redirects', 'clicks', 'comments', 'feedback', 'links', 'mentions');
await agent.loginAsOwner();
});
afterEach(function () {
mockManager.restore();
});
describe('Edit', function () {
it('Can feature multiple posts', async function () {
const filter = 'status:[published,draft,scheduled,sent]';
// Check all the posts that should be affected
const changedPosts = await models.Post.findPage({filter, limit: 1, status: 'all'});
const amount = changedPosts.meta.pagination.total;
assert(amount > 0, 'Expect at least one post to be affected for this test to work');
const response = await agent
.put('/posts/bulk/?filter=' + encodeURIComponent(filter))
.body({
bulk: {
action: 'feature'
}
})
.expectStatus(200)
.matchBodySnapshot();
assert.equal(response.body.bulk.meta.stats.successful, amount, `Expect all matching posts (${amount}) to be changed`);
// Fetch all posts and check if they are featured
const posts = await models.Post.findAll({filter, status: 'all'});
assert.equal(posts.length, amount, `Expect all matching posts (${amount}) to be changed`);
for (const post of posts) {
assert(post.get('featured') === true, `Expect post ${post.id} to be featured`);
}
});
it('Can unfeature multiple posts', async function () {
const filter = 'status:[published,draft,scheduled,sent]';
// Check all the posts that should be affected
const changedPosts = await models.Post.findPage({filter, limit: 1, status: 'all'});
const amount = changedPosts.meta.pagination.total;
assert(amount > 0, 'Expect at least one post to be affected for this test to work');
const response = await agent
.put('/posts/bulk/?filter=' + encodeURIComponent(filter))
.body({
bulk: {
action: 'unfeature'
}
})
.expectStatus(200)
.matchBodySnapshot();
assert.equal(response.body.bulk.meta.stats.successful, amount, `Expect all matching posts (${amount}) to be changed`);
// Fetch all posts and check if they are featured
const posts = await models.Post.findAll({filter, status: 'all'});
assert.equal(posts.length, amount, `Expect all matching posts (${amount}) to be changed`);
for (const post of posts) {
assert(post.get('featured') === false, `Expect post ${post.id} to be unfeatured`);
}
});
it('Can change access of posts', async function () {
const filter = 'status:[published,draft,scheduled,sent]';
// Check all the posts that should be affected
const changedPosts = await models.Post.findPage({filter, limit: 1, status: 'all'});
const amount = changedPosts.meta.pagination.total;
assert(amount > 0, 'Expect at least one post to be affected for this test to work');
const response = await agent
.put('/posts/bulk/?filter=' + encodeURIComponent(filter))
.body({
bulk: {
action: 'access',
meta: {
visibility: 'paid'
}
}
})
.expectStatus(200)
.matchBodySnapshot();
assert.equal(response.body.bulk.meta.stats.successful, amount, `Expect all matching posts (${amount}) to be changed`);
// Fetch all posts and check if they have the correct access
const posts = await models.Post.findAll({filter, status: 'all'});
assert.equal(posts.length, amount, `Expect all matching posts (${amount}) to be changed`);
for (const post of posts) {
assert(post.get('visibility') === 'paid', `Expect post ${post.id} to have access 'paid'`);
}
});
it('Can change access of posts to tiers', async function () {
const filter = 'status:[published,draft,scheduled,sent]';
const products = await models.Product.findAll();
const tier1 = products.models[0];
const tier2 = products.models[1];
assert(tier1.id && tier2.id);
// Check all the posts that should be affected
const changedPosts = await models.Post.findPage({filter, limit: 1, status: 'all'});
const amount = changedPosts.meta.pagination.total;
assert(amount > 0, 'Expect at least one post to be affected for this test to work');
const response = await agent
.put('/posts/bulk/?filter=' + encodeURIComponent(filter))
.body({
bulk: {
action: 'access',
meta: {
visibility: 'tiers',
tiers: [
{
id: tier1.id
},
{
id: tier2.id
}
]
}
}
})
.expectStatus(200)
.matchBodySnapshot();
assert.equal(response.body.bulk.meta.stats.successful, amount, `Expect all matching posts (${amount}) to be changed`);
// Fetch all posts and check if they have the correct access
const posts = await models.Post.findAll({filter, status: 'all', withRelated: ['tiers']});
assert.equal(posts.length, amount, `Expect all matching posts (${amount}) to be changed`);
for (const post of posts) {
assert(post.get('visibility') === 'tiers', `Expect post ${post.id} to have access 'tiers'`);
assert.equal(post.related('tiers').length, 2);
}
});
it('Can add a single tag to posts', async function () {
const filter = 'status:[published]';
const tag = await models.Tag.findOne({slug: fixtureManager.get('tags', 0).slug});
assert(tag);
// Check all the posts that should be affected
const changedPosts = await models.Post.findPage({filter, limit: 1, status: 'all'});
const amount = changedPosts.meta.pagination.total;
assert(amount > 0, 'Expect at least one post to be affected for this test to work');
const response = await agent
.put('/posts/bulk/?filter=' + encodeURIComponent(filter))
.body({
bulk: {
action: 'addTag',
meta: {
tags: [
{
id: tag.id
}
]
}
}
})
.expectStatus(200)
.matchBodySnapshot();
assert.equal(response.body.bulk.meta.stats.successful, amount, `Expect all matching posts (${amount}) to be changed, got ${response.body.bulk.meta.stats.successful} instead`);
// Fetch all posts and check if they have the tag
const posts = await models.Post.findAll({filter, status: 'all', withRelated: ['tags']});
assert.equal(posts.length, amount, `Expect all matching posts (${amount}) to be changed`);
for (const post of posts) {
const tags = post.related('tags');
// Check tag is in the list
assert(tags.find(t => t.id === tag.id), `Expect post ${post.id} to have tag ${tag.id}`);
}
});
it('Can add multiple tags to posts and create new tags', async function () {
const filter = 'status:[draft]';
const tag = await models.Tag.findOne({id: fixtureManager.get('tags', 1).id});
assert(tag);
const newTag = {
name: 'Just a random new tag'
};
// Check all the posts that should be affected
const changedPosts = await models.Post.findPage({filter, limit: 1, status: 'all'});
const amount = changedPosts.meta.pagination.total;
assert(amount > 0, 'Expect at least one post to be affected for this test to work');
const response = await agent
.put('/posts/bulk/?filter=' + encodeURIComponent(filter))
.body({
bulk: {
action: 'addTag',
meta: {
tags: [
{
id: tag.id
},
{
name: newTag.name
}
]
}
}
})
.expectStatus(200)
.matchBodySnapshot();
assert.equal(response.body.bulk.meta.stats.successful, amount, `Expect all matching posts (${amount}) to be changed, got ${response.body.bulk.meta.stats.successful} instead`);
// Check if the new tag was created
const newTags = await models.Tag.findAll({filter: `name:'${newTag.name}'`});
assert.equal(newTags.length, 1, `Expect tag to be created`);
const newTagModel = newTags.models[0];
// Fetch all posts and check if they have the tag
const posts = await models.Post.findAll({filter, status: 'all', withRelated: ['tags']});
assert.equal(posts.length, amount, `Expect all matching posts (${amount}) to be changed`);
for (const post of posts) {
const tags = post.related('tags');
// Check tag is in the list
assert(tags.find(t => t.id === tag.id), `Expect post ${post.id} to have tag ${tag.id}`);
assert(tags.find(t => t.id === newTagModel.id), `Expect post ${post.id} to have new tag ${newTagModel.id}`);
}
});
});
describe('Delete', function () {
it('Can delete posts that match a tag', async function () {
const tag = await models.Tag.findOne({id: fixtureManager.get('tags', 0).id});
const filter = 'tag:' + tag.get('slug');
// Check all the posts that should be affected
const changedPosts = await models.Post.findPage({filter, limit: 1, status: 'all'});
const amount = changedPosts.meta.pagination.total;
assert(amount > 0, 'Expect at least one post to be affected for this test to work');
const response = await agent
.delete('/posts/?filter=' + encodeURIComponent(filter))
.expectStatus(200)
.matchBodySnapshot();
assert.equal(response.body.bulk.meta.stats.successful, amount, `Expect all matching posts (${amount}) to be deleted, got ${response.body.bulk.meta.stats.successful} instead`);
// Check if all posts were deleted
const posts = await models.Post.findPage({filter, status: 'all'});
assert.equal(posts.meta.pagination.total, 0, `Expect all matching posts (${amount}) to be deleted`);
});
it('Can delete all posts', async function () {
const filter = 'status:[published,draft,scheduled,sent]';
// Check all the posts that should be affected
const changedPosts = await models.Post.findPage({filter, limit: 1, status: 'all'});
const amount = changedPosts.meta.pagination.total;
assert(amount > 0, 'Expect at least one post to be affected for this test to work');
const response = await agent
.delete('/posts/?filter=' + encodeURIComponent(filter))
.expectStatus(200)
.matchBodySnapshot();
assert.equal(response.body.bulk.meta.stats.successful, amount, `Expect all matching posts (${amount}) to be deleted, got ${response.body.bulk.meta.stats.successful} instead`);
// Check if all posts were deleted
const posts = await models.Post.findPage({filter, status: 'all'});
assert.equal(posts.meta.pagination.total, 0, `Expect all matching posts (${amount}) to be deleted`);
});
});
});

View File

@ -163,7 +163,10 @@ class PostsService {
await options.transacting('posts_tags').insert(postTags);
return true;
return {
successful: postRows.length,
unsuccessful: 0
};
}
/**