mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
af367a2a18
no issue - post_revisions will now be included in any request to the /posts endpoint - updated admin models to include post_revisions - post revisions can now be accessed in the modal-portal-history via this.post.post_revisions
1863 lines
75 KiB
JavaScript
1863 lines
75 KiB
JavaScript
const should = require('should');
|
|
const nock = require('nock');
|
|
const path = require('path');
|
|
const supertest = require('supertest');
|
|
const _ = require('lodash');
|
|
const ObjectId = require('bson-objectid').default;
|
|
const moment = require('moment-timezone');
|
|
const testUtils = require('../../utils');
|
|
const config = require('../../../core/shared/config');
|
|
const models = require('../../../core/server/models');
|
|
const localUtils = require('./utils');
|
|
const configUtils = require('../../utils/configUtils');
|
|
const mockManager = require('../../utils/e2e-framework-mock-manager');
|
|
const sinon = require('sinon');
|
|
const logging = require('@tryghost/logging');
|
|
|
|
describe('Posts API', function () {
|
|
let request;
|
|
|
|
before(async function () {
|
|
await localUtils.startGhost();
|
|
request = supertest.agent(config.get('url'));
|
|
/**
|
|
* Members are needed to enable mega to create an email record so that we can test that newsletter_id
|
|
* can't be overwritten after an email record is created.
|
|
*/
|
|
await localUtils.doAuth(request, 'users:extra', 'posts', 'emails', 'newsletters', 'members:newsletters');
|
|
|
|
// Assign a newsletter to one of the posts
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[0].id;
|
|
const postId = testUtils.DataGenerator.Content.posts[0].id;
|
|
await models.Post.edit({newsletter_id: newsletterId}, {id: postId});
|
|
});
|
|
|
|
beforeEach(function () {
|
|
mockManager.mockMailgun();
|
|
// Disable network to prevent sending webmentions
|
|
mockManager.disableNetwork();
|
|
});
|
|
|
|
afterEach(function () {
|
|
mockManager.restore();
|
|
});
|
|
|
|
it('Can retrieve all posts', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('posts/'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
const jsonResponse = res.body;
|
|
should.exist(jsonResponse.posts);
|
|
localUtils.API.checkResponse(jsonResponse, 'posts');
|
|
jsonResponse.posts.should.have.length(13);
|
|
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
|
|
_.isBoolean(jsonResponse.posts[0].email_only).should.eql(true);
|
|
jsonResponse.posts[0].email_only.should.eql(false);
|
|
|
|
// Ensure default order
|
|
jsonResponse.posts[0].slug.should.eql('scheduled-post');
|
|
jsonResponse.posts[12].slug.should.eql('html-ipsum');
|
|
|
|
// Absolute urls by default
|
|
jsonResponse.posts[0].url.should.match(new RegExp(`${config.get('url')}/p/[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}`));
|
|
jsonResponse.posts[2].url.should.eql(`${config.get('url')}/welcome/`);
|
|
jsonResponse.posts[11].feature_image.should.eql(`${config.get('url')}/content/images/2018/hey.jpg`);
|
|
|
|
jsonResponse.posts[0].tags.length.should.eql(0);
|
|
jsonResponse.posts[2].tags.length.should.eql(1);
|
|
jsonResponse.posts[2].authors.length.should.eql(1);
|
|
jsonResponse.posts[2].tags[0].url.should.eql(`${config.get('url')}/tag/getting-started/`);
|
|
jsonResponse.posts[2].authors[0].url.should.eql(`${config.get('url')}/author/ghost/`);
|
|
|
|
// Check if the newsletter relation is loaded by default and newsletter_id is not returned
|
|
jsonResponse.posts[12].id.should.eql(testUtils.DataGenerator.Content.posts[0].id);
|
|
jsonResponse.posts[12].newsletter.id.should.eql(testUtils.DataGenerator.Content.newsletters[0].id);
|
|
should.not.exist(jsonResponse.posts[12].newsletter_id);
|
|
|
|
should(jsonResponse.posts[0].newsletter).be.null();
|
|
should.not.exist(jsonResponse.posts[0].newsletter_id);
|
|
});
|
|
|
|
it('Can retrieve multiple post formats', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('posts/?formats=plaintext,mobiledoc&limit=3&order=title%20ASC'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
const jsonResponse = res.body;
|
|
should.exist(jsonResponse.posts);
|
|
localUtils.API.checkResponse(jsonResponse, 'posts');
|
|
jsonResponse.posts.should.have.length(3);
|
|
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', ['plaintext']);
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
|
|
|
|
// ensure order works
|
|
jsonResponse.posts[0].slug.should.eql('portal');
|
|
});
|
|
|
|
it('Can include single relation', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('posts/?include=tags'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
const jsonResponse = res.body;
|
|
should.exist(jsonResponse.posts);
|
|
localUtils.API.checkResponse(jsonResponse, 'posts');
|
|
jsonResponse.posts.should.have.length(13);
|
|
localUtils.API.checkResponse(
|
|
jsonResponse.posts[0],
|
|
'post',
|
|
null,
|
|
['authors', 'primary_author', 'email', 'tiers', 'newsletter', 'count', 'post_revisions']
|
|
);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
});
|
|
|
|
it('Can filter posts', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('posts/?filter=featured:true'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
const jsonResponse = res.body;
|
|
should.exist(jsonResponse.posts);
|
|
localUtils.API.checkResponse(jsonResponse, 'posts');
|
|
jsonResponse.posts.should.have.length(2);
|
|
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
});
|
|
|
|
it('Returns a validation error when unknown filter key is used', async function () {
|
|
const loggingStub = sinon.stub(logging, 'error');
|
|
await request.get(localUtils.API.getApiQuery('posts/?filter=page:true'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(400);
|
|
sinon.assert.calledOnce(loggingStub);
|
|
});
|
|
|
|
it('Can paginate posts', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('posts/?page=2'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const jsonResponse = res.body;
|
|
should.equal(jsonResponse.meta.pagination.page, 2);
|
|
});
|
|
|
|
it('Can request a post by id', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
const jsonResponse = res.body;
|
|
should.exist(jsonResponse);
|
|
should.exist(jsonResponse.posts);
|
|
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
|
jsonResponse.posts[0].id.should.equal(testUtils.DataGenerator.Content.posts[0].id);
|
|
|
|
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
|
|
|
|
testUtils.API.isISO8601(jsonResponse.posts[0].created_at).should.be.true();
|
|
|
|
// Check if the newsletter relation is loaded by default and newsletter_id is not returned
|
|
jsonResponse.posts[0].newsletter.id.should.eql(testUtils.DataGenerator.Content.newsletters[0].id);
|
|
should.not.exist(jsonResponse.posts[0].newsletter_id);
|
|
});
|
|
|
|
it('Can request a post by id without newsletter', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[1].id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
const jsonResponse = res.body;
|
|
should.exist(jsonResponse);
|
|
should.exist(jsonResponse.posts);
|
|
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
|
jsonResponse.posts[0].id.should.equal(testUtils.DataGenerator.Content.posts[1].id);
|
|
|
|
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
|
|
|
|
testUtils.API.isISO8601(jsonResponse.posts[0].created_at).should.be.true();
|
|
|
|
// Newsletter should be returned as null
|
|
should(jsonResponse.posts[0].newsletter).be.null();
|
|
should.not.exist(jsonResponse.posts[0].newsletter_id);
|
|
});
|
|
|
|
it('Can retrieve a post by slug', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('posts/slug/welcome/'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
const jsonResponse = res.body;
|
|
should.exist(jsonResponse);
|
|
should.exist(jsonResponse.posts);
|
|
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
|
jsonResponse.posts[0].slug.should.equal('welcome');
|
|
|
|
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
|
|
|
|
// Newsletter should be returned as null
|
|
should(jsonResponse.posts[0].newsletter).be.null();
|
|
should.not.exist(jsonResponse.posts[0].newsletter_id);
|
|
});
|
|
|
|
it('Can include relations for a single post', async function () {
|
|
const res = await request
|
|
.get(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/?include=authors,tags,email,tiers,newsletter,post_revisions'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
const jsonResponse = res.body;
|
|
should.exist(jsonResponse);
|
|
should.exist(jsonResponse.posts);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', null, ['count']);
|
|
|
|
jsonResponse.posts[0].authors[0].should.be.an.Object();
|
|
localUtils.API.checkResponse(jsonResponse.posts[0].authors[0], 'user');
|
|
|
|
jsonResponse.posts[0].tags[0].should.be.an.Object();
|
|
localUtils.API.checkResponse(jsonResponse.posts[0].tags[0], 'tag', ['url']);
|
|
|
|
jsonResponse.posts[0].email.should.be.an.Object();
|
|
localUtils.API.checkResponse(jsonResponse.posts[0].email, 'email');
|
|
|
|
jsonResponse.posts[0].newsletter.id.should.eql(testUtils.DataGenerator.Content.newsletters[0].id);
|
|
should.not.exist(jsonResponse.posts[0].newsletter_id);
|
|
});
|
|
|
|
it('Can add a post', async function () {
|
|
this.retries(1);
|
|
const post = {
|
|
title: 'My post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing feature image alt',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
published_at: '2016-05-30T07:00:00.000Z',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
res.body.posts.length.should.eql(1);
|
|
localUtils.API.checkResponse(res.body.posts[0], 'post');
|
|
res.body.posts[0].url.should.match(new RegExp(`${config.get('url')}/p/[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}`));
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
|
|
should.exist(res.headers.location);
|
|
res.headers.location.should.equal(`http://127.0.0.1:2369${localUtils.API.getApiQuery('posts/')}${res.body.posts[0].id}/`);
|
|
|
|
// Newsletter should be returned as null
|
|
should(res.body.posts[0].newsletter).be.null();
|
|
should.not.exist(res.body.posts[0].newsletter_id);
|
|
|
|
const model = await models.Post.findOne({
|
|
id: res.body.posts[0].id,
|
|
status: 'draft'
|
|
}, testUtils.context.internal);
|
|
|
|
const modelJson = model.toJSON();
|
|
|
|
modelJson.title.should.eql(post.title);
|
|
modelJson.status.should.eql(post.status);
|
|
modelJson.published_at.toISOString().should.eql('2016-05-30T07:00:00.000Z');
|
|
modelJson.created_at.toISOString().should.not.eql(post.created_at.toISOString());
|
|
modelJson.updated_at.toISOString().should.not.eql(post.updated_at.toISOString());
|
|
modelJson.updated_by.should.not.eql(post.updated_by);
|
|
modelJson.created_by.should.not.eql(post.created_by);
|
|
|
|
modelJson.posts_meta.feature_image_alt.should.eql(post.feature_image_alt);
|
|
modelJson.posts_meta.feature_image_caption.should.eql(post.feature_image_caption);
|
|
});
|
|
|
|
it('Can include free and paid tiers for public post', async function () {
|
|
const publicPost = testUtils.DataGenerator.forKnex.createPost({
|
|
slug: 'free-to-see',
|
|
visibility: 'public',
|
|
published_at: moment().add(15, 'seconds').toDate() // here to ensure sorting is not modified
|
|
});
|
|
await models.Post.add(publicPost, {context: {internal: true}});
|
|
|
|
const publicPostRes = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${publicPost.id}/`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
const publicPostData = publicPostRes.body.posts[0];
|
|
publicPostData.tiers.length.should.eql(2);
|
|
});
|
|
|
|
it('Can include free and paid tiers for members only post', async function () {
|
|
const membersPost = testUtils.DataGenerator.forKnex.createPost({
|
|
slug: 'thou-shalt-not-be-seen',
|
|
visibility: 'members',
|
|
published_at: moment().add(45, 'seconds').toDate() // here to ensure sorting is not modified
|
|
});
|
|
await models.Post.add(membersPost, {context: {internal: true}});
|
|
|
|
const membersPostRes = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
const membersPostData = membersPostRes.body.posts[0];
|
|
membersPostData.tiers.length.should.eql(2);
|
|
});
|
|
|
|
it('Can include only paid tier for paid post', async function () {
|
|
const paidPost = testUtils.DataGenerator.forKnex.createPost({
|
|
slug: 'thou-shalt-be-paid-for',
|
|
visibility: 'paid',
|
|
published_at: moment().add(30, 'seconds').toDate() // here to ensure sorting is not modified
|
|
});
|
|
await models.Post.add(paidPost, {context: {internal: true}});
|
|
|
|
const paidPostRes = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${paidPost.id}/`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
const paidPostData = paidPostRes.body.posts[0];
|
|
paidPostData.tiers.length.should.eql(1);
|
|
});
|
|
|
|
it('Can include specific tier for post with tiers visibility', async function () {
|
|
const res = await request.get(localUtils.API.getApiQuery('tiers/'))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
const paidTier = jsonResponse.tiers.find(p => p.type === 'paid');
|
|
|
|
const tiersPost = testUtils.DataGenerator.forKnex.createPost({
|
|
slug: 'thou-shalt-be-for-specific-tiers',
|
|
visibility: 'tiers',
|
|
published_at: moment().add(30, 'seconds').toDate() // here to ensure sorting is not modified
|
|
});
|
|
|
|
tiersPost.tiers = [paidTier];
|
|
|
|
await models.Post.add(tiersPost, {context: {internal: true}});
|
|
|
|
const tiersPostRes = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${tiersPost.id}/`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
const tiersPostData = tiersPostRes.body.posts[0];
|
|
|
|
tiersPostData.tiers.length.should.eql(1);
|
|
});
|
|
|
|
it('Can update draft', async function () {
|
|
const post = {
|
|
title: 'update draft'
|
|
};
|
|
|
|
const res = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[3].id}/`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
|
|
post.updated_at = res.body.posts[0].updated_at;
|
|
|
|
const res2 = await request.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[3].id))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
res2.headers['x-cache-invalidate'].should.eql('/p/' + res2.body.posts[0].uuid + '/');
|
|
|
|
// Newsletter should be returned as null
|
|
should(res2.body.posts[0].newsletter).be.null();
|
|
should.not.exist(res2.body.posts[0].newsletter_id);
|
|
});
|
|
|
|
it('Can update and force re-render', async function () {
|
|
const unsplashMock = nock('https://images.unsplash.com/')
|
|
.get('/favicon_too_large')
|
|
.query(true)
|
|
.replyWithFile(200, path.join(__dirname, '../../utils/fixtures/images/ghost-logo.png'), {
|
|
'Content-Type': 'image/png'
|
|
});
|
|
|
|
const mobiledoc = JSON.parse(testUtils.DataGenerator.Content.posts[3].mobiledoc);
|
|
mobiledoc.cards.push(['image', {src: 'https://images.unsplash.com/favicon_too_large?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=2000&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ'}]);
|
|
mobiledoc.sections.push([10, mobiledoc.cards.length - 1]);
|
|
|
|
const post = {
|
|
mobiledoc: JSON.stringify(mobiledoc)
|
|
};
|
|
|
|
const res = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[3].id}/`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
|
|
post.updated_at = res.body.posts[0].updated_at;
|
|
|
|
const res2 = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[3].id + '/?force_rerender=true&formats=mobiledoc,html'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private);
|
|
|
|
res2.headers['x-cache-invalidate'].should.eql('/p/' + res2.body.posts[0].uuid + '/');
|
|
|
|
unsplashMock.isDone().should.be.true();
|
|
|
|
// mobiledoc is updated with image sizes
|
|
const resMobiledoc = JSON.parse(res2.body.posts[0].mobiledoc);
|
|
const cardPayload = resMobiledoc.cards[mobiledoc.cards.length - 1][1];
|
|
cardPayload.width.should.eql(800);
|
|
cardPayload.height.should.eql(257);
|
|
|
|
// html is re-rendered to include srcset
|
|
res2.body.posts[0].html.should.match(/srcset="https:\/\/images\.unsplash\.com\/favicon_too_large\?ixlib=rb-1\.2\.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=600&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ 600w, https:\/\/images\.unsplash\.com\/favicon_too_large\?ixlib=rb-1\.2\.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=800&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ 800w"/);
|
|
});
|
|
|
|
it('Can unpublish a post', async function () {
|
|
const post = {
|
|
status: 'draft'
|
|
};
|
|
|
|
const res = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[1].id}/?`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
|
|
post.updated_at = res.body.posts[0].updated_at;
|
|
|
|
const res2 = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[1].id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
res2.headers['x-cache-invalidate'].should.eql('/*');
|
|
res2.body.posts[0].status.should.eql('draft');
|
|
});
|
|
|
|
it(`Can't change the newsletter of a post from the post body`, async function () {
|
|
const post = {
|
|
newsletter: testUtils.DataGenerator.Content.newsletters[0].id
|
|
};
|
|
|
|
const postId = testUtils.DataGenerator.Content.posts[2].id;
|
|
|
|
const modelBefore = await models.Post.findOne({
|
|
id: postId
|
|
}, testUtils.context.internal);
|
|
|
|
should(modelBefore.get('newsletter_id')).eql(null, 'This test requires the initial post to not have a newsletter');
|
|
|
|
const res = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${postId}/?`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
|
|
post.updated_at = res.body.posts[0].updated_at;
|
|
|
|
await request
|
|
.put(localUtils.API.getApiQuery('posts/' + postId + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const model = await models.Post.findOne({
|
|
id: postId
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(null);
|
|
});
|
|
|
|
it(`Can't change the newsletter of a post from the post body`, async function () {
|
|
const post = {
|
|
newsletter: {
|
|
id: testUtils.DataGenerator.Content.newsletters[0].id
|
|
}
|
|
};
|
|
|
|
const postId = testUtils.DataGenerator.Content.posts[2].id;
|
|
|
|
const modelBefore = await models.Post.findOne({
|
|
id: postId
|
|
}, testUtils.context.internal);
|
|
|
|
should(modelBefore.get('newsletter_id')).eql(null, 'This test requires the initial post to not have a newsletter');
|
|
|
|
const res = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${postId}/?`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
|
|
post.updated_at = res.body.posts[0].updated_at;
|
|
|
|
await request
|
|
.put(localUtils.API.getApiQuery('posts/' + postId + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const model = await models.Post.findOne({
|
|
id: postId
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(null);
|
|
});
|
|
|
|
it('Cannot change the newsletter via body when adding', async function () {
|
|
const post = {
|
|
title: 'My newsletter post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString(),
|
|
newsletter: {
|
|
// This should be ignored, the default one should be used instead
|
|
id: testUtils.DataGenerator.Content.newsletters[0].id
|
|
}
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
// Check that the default newsletter is used instead of the one in body (not allowed)
|
|
should(res.body.posts[0].status).eql('draft');
|
|
should(res.body.posts[0].newsletter).eql(null);
|
|
should.not.exist(res.body.posts[0].newsletter_id);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const model = await models.Post.findOne({
|
|
id,
|
|
status: 'draft' // Fix for default filter
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(null);
|
|
});
|
|
|
|
it('Cannot send to an archived newsletter', async function () {
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[2].slug;
|
|
|
|
should(testUtils.DataGenerator.Content.newsletters[2].status).eql('archived', 'This test expects an archived newsletter in the test fixtures');
|
|
|
|
const post = {
|
|
title: 'My archived newsletter post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
// Check newsletter relation is loaded, but null in response.
|
|
should(res.body.posts[0].newsletter).eql(null);
|
|
should(res.body.posts[0].email_segment).eql('all');
|
|
should.not.exist(res.body.posts[0].newsletter_id);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'published';
|
|
|
|
const loggingStub = sinon.stub(logging, 'error');
|
|
|
|
await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(400);
|
|
|
|
sinon.assert.calledOnce(loggingStub);
|
|
});
|
|
|
|
it('Can publish a post without email', async function () {
|
|
const post = {
|
|
title: 'My publish only post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
// Check newsletter relation is loaded, but null in response.
|
|
should(res.body.posts[0].newsletter).eql(null);
|
|
should.not.exist(res.body.posts[0].newsletter_id);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'published';
|
|
|
|
const finalPost = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
should(finalPost.body.posts[0].newsletter).eql(null);
|
|
should(finalPost.body.posts[0].email_segment).eql('all');
|
|
should.not.exist(finalPost.body.posts[0].newsletter_id);
|
|
|
|
const model = await models.Post.findOne({
|
|
id
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(null);
|
|
|
|
// Check email
|
|
// Note: we only create an email if we have members susbcribed to the newsletter
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.not.exist(email);
|
|
});
|
|
|
|
it('Interprets sent status as published for not email only posts', async function () {
|
|
const post = {
|
|
title: 'My publish only post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
// Check newsletter relation is loaded, but null in response.
|
|
should(res.body.posts[0].newsletter).eql(null);
|
|
should.not.exist(res.body.posts[0].newsletter_id);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'sent';
|
|
|
|
const initialModel = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
should.not.exist(initialModel.get('published_by'));
|
|
|
|
const finalPost = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
should(finalPost.body.posts[0].newsletter).eql(null);
|
|
should(finalPost.body.posts[0].email_segment).eql('all');
|
|
should.not.exist(finalPost.body.posts[0].newsletter_id);
|
|
|
|
// Check status is set to published
|
|
finalPost.body.posts[0].status.should.eql('published');
|
|
|
|
const model = await models.Post.findOne({
|
|
id
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(null);
|
|
should.exist(model.get('published_by'));
|
|
|
|
// Check email
|
|
// Note: we only create an email if we have members susbcribed to the newsletter
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.not.exist(email);
|
|
});
|
|
|
|
it('Can publish a post and send as email', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My newsletter_id post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter_id',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
// Check newsletter relation is loaded, but null in response.
|
|
should(res.body.posts[0].newsletter).eql(null);
|
|
should.not.exist(res.body.posts[0].newsletter_id);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'published';
|
|
|
|
const initialModel = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
should.not.exist(initialModel.get('published_by'));
|
|
|
|
const finalPost = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
should(finalPost.body.posts[0].newsletter.id).eql(newsletterId);
|
|
should(finalPost.body.posts[0].email_segment).eql('all');
|
|
should.not.exist(finalPost.body.posts[0].newsletter_id);
|
|
|
|
const model = await models.Post.findOne({
|
|
id
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should.exist(model.get('published_by'));
|
|
|
|
// Check email
|
|
// Note: we only create an email if we have members susbcribed to the newsletter
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.exist(email);
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Interprets sent as published for a post with email', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My newsletter_id post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter_id',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
// Check newsletter relation is loaded, but null in response.
|
|
should(res.body.posts[0].newsletter).eql(null);
|
|
should.not.exist(res.body.posts[0].newsletter_id);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'sent';
|
|
|
|
const initialModel = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
should.not.exist(initialModel.get('published_by'));
|
|
|
|
const finalPost = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
should(finalPost.body.posts[0].newsletter.id).eql(newsletterId);
|
|
should(finalPost.body.posts[0].email_segment).eql('all');
|
|
should.not.exist(finalPost.body.posts[0].newsletter_id);
|
|
|
|
// Check status
|
|
should(finalPost.body.posts[0].status).eql('published');
|
|
|
|
const model = await models.Post.findOne({
|
|
id
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should.exist(model.get('published_by'));
|
|
|
|
// Check email
|
|
// Note: we only create an email if we have members susbcribed to the newsletter
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.exist(email);
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Can publish an email_only post by setting status to published', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter in posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'published';
|
|
//updatedPost.published_at = moment().add(2, 'days').toDate();
|
|
updatedPost.email_only = true;
|
|
|
|
const initialModel = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
should.not.exist(initialModel.get('published_by'));
|
|
|
|
const publishedRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const publishedPost = publishedRes.body.posts[0];
|
|
|
|
publishedPost.newsletter.id.should.eql(newsletterId);
|
|
publishedPost.email_segment.should.eql('all');
|
|
publishedPost.status.should.eql('sent');
|
|
should.not.exist(publishedPost.newsletter_id);
|
|
|
|
let model = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('status')).eql('sent');
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
should.exist(model.get('published_by'));
|
|
|
|
// We should have an email
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('recipient_filter')).eql('all');
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Can publish an email_only post with free filter', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter in posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'published';
|
|
updatedPost.email_only = true;
|
|
|
|
const initialModel = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
should.not.exist(initialModel.get('published_by'));
|
|
|
|
const publishedRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug + '&email_segment=status%3Afree'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const publishedPost = publishedRes.body.posts[0];
|
|
|
|
publishedPost.newsletter.id.should.eql(newsletterId);
|
|
publishedPost.email_segment.should.eql('status:free');
|
|
publishedPost.status.should.eql('sent');
|
|
should.not.exist(publishedPost.newsletter_id);
|
|
|
|
let model = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('status')).eql('sent');
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('status:free');
|
|
should.exist(model.get('published_by'));
|
|
|
|
// We should have an email
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('recipient_filter')).eql('status:free');
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Can publish an email_only post by setting the status to sent', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter in posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'sent';
|
|
updatedPost.email_only = true;
|
|
|
|
const initialModel = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
should.not.exist(initialModel.get('published_by'));
|
|
|
|
const publishedRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug + '&email_segment=status%3Afree'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const publishedPost = publishedRes.body.posts[0];
|
|
|
|
publishedPost.newsletter.id.should.eql(newsletterId);
|
|
publishedPost.email_segment.should.eql('status:free');
|
|
publishedPost.status.should.eql('sent');
|
|
should.not.exist(publishedPost.newsletter_id);
|
|
|
|
let model = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('status')).eql('sent');
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('status:free');
|
|
should.exist(model.get('published_by'));
|
|
|
|
// We should have an email
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('recipient_filter')).eql('status:free');
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Can publish a scheduled post', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My scheduled post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter_id in scheduled posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'scheduled';
|
|
updatedPost.published_at = moment().add(2, 'days').toDate();
|
|
|
|
const scheduledRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const scheduledPost = scheduledRes.body.posts[0];
|
|
|
|
scheduledPost.newsletter.id.should.eql(newsletterId);
|
|
scheduledPost.email_segment.should.eql('all');
|
|
should.not.exist(scheduledPost.newsletter_id);
|
|
|
|
let model = await models.Post.findOne({
|
|
id,
|
|
status: 'scheduled'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
should.not.exist(model.get('published_by'));
|
|
|
|
// We should not have an email
|
|
let email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.not.exist(email);
|
|
|
|
// Publish now, without passing the newsletter_id or other options again!
|
|
scheduledPost.status = 'published';
|
|
scheduledPost.published_at = moment().toDate();
|
|
|
|
const publishedRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [scheduledPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const publishedPost = publishedRes.body.posts[0];
|
|
|
|
model = await models.Post.findOne({
|
|
id
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
should.exist(model.get('published_by'));
|
|
|
|
publishedPost.newsletter.id.should.eql(newsletterId);
|
|
should.not.exist(publishedPost.newsletter_id);
|
|
|
|
// Check email is sent to the correct newsletter
|
|
email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('recipient_filter')).eql('all');
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Can publish a scheduled post with custom email segment', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My scheduled post 2',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter_id in scheduled posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'scheduled';
|
|
updatedPost.published_at = moment().add(2, 'days').toDate();
|
|
|
|
const scheduledRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug + '&email_segment=status:free'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const scheduledPost = scheduledRes.body.posts[0];
|
|
|
|
scheduledPost.newsletter.id.should.eql(newsletterId);
|
|
scheduledPost.email_segment.should.eql('status:free');
|
|
should.not.exist(scheduledPost.newsletter_id);
|
|
|
|
let model = await models.Post.findOne({
|
|
id,
|
|
status: 'scheduled'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('status:free');
|
|
|
|
// We should not have an email
|
|
let email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.not.exist(email);
|
|
|
|
// Publish now, without passing the newsletter_id or other options again!
|
|
scheduledPost.status = 'published';
|
|
scheduledPost.published_at = moment().toDate();
|
|
|
|
const publishedRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [scheduledPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const publishedPost = publishedRes.body.posts[0];
|
|
|
|
model = await models.Post.findOne({
|
|
id
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('status:free');
|
|
|
|
publishedPost.newsletter.id.should.eql(newsletterId);
|
|
should.not.exist(publishedPost.newsletter_id);
|
|
|
|
// Check email is sent to the correct newsletter
|
|
email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('recipient_filter')).eql('status:free');
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Can publish a scheduled post without newsletter', async function () {
|
|
const post = {
|
|
title: 'My scheduled post 3',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing no newsletter in scheduled posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'scheduled';
|
|
updatedPost.published_at = moment().add(2, 'days').toDate();
|
|
|
|
const scheduledRes = await request
|
|
// We also test whether email_segment is ignored if no newsletter is sent
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?email_segment=status:-free'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const scheduledPost = scheduledRes.body.posts[0];
|
|
|
|
should(scheduledPost.newsletter).eql(null);
|
|
scheduledPost.email_segment.should.eql('all'); // should be igored
|
|
should.not.exist(scheduledPost.newsletter_id);
|
|
|
|
let model = await models.Post.findOne({
|
|
id,
|
|
status: 'scheduled'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(null);
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
|
|
// We should not have an email
|
|
let email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.not.exist(email);
|
|
|
|
// Publish now, without passing the newsletter_id or other options again!
|
|
scheduledPost.status = 'published';
|
|
scheduledPost.published_at = moment().toDate();
|
|
|
|
const publishedRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [scheduledPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const publishedPost = publishedRes.body.posts[0];
|
|
|
|
model = await models.Post.findOne({
|
|
id
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(null);
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
|
|
should(publishedPost.newsletter).eql(null);
|
|
should.not.exist(publishedPost.newsletter_id);
|
|
|
|
// Check email is sent to the correct newsletter
|
|
email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.not.exist(email);
|
|
});
|
|
|
|
it('Can publish a scheduled email only post', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My scheduled email only post',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter in scheduled posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'scheduled';
|
|
updatedPost.email_only = true;
|
|
updatedPost.published_at = moment().add(2, 'days').toDate();
|
|
|
|
const scheduledRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const scheduledPost = scheduledRes.body.posts[0];
|
|
|
|
scheduledPost.newsletter.id.should.eql(newsletterId);
|
|
scheduledPost.email_segment.should.eql('all');
|
|
scheduledPost.status.should.eql('scheduled');
|
|
scheduledPost.email_only.should.eql(true);
|
|
should.not.exist(scheduledPost.newsletter_id);
|
|
|
|
let model = await models.Post.findOne({
|
|
id,
|
|
status: 'scheduled'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('status')).eql('scheduled');
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
|
|
// We should not have an email
|
|
let email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.not.exist(email);
|
|
|
|
// Publish now, without passing the newsletter_id or other options again!
|
|
scheduledPost.status = 'published';
|
|
|
|
const publishedRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [scheduledPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const publishedPost = publishedRes.body.posts[0];
|
|
|
|
model = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('status')).eql('sent');
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
|
|
publishedPost.newsletter.id.should.eql(newsletterId);
|
|
should.not.exist(publishedPost.newsletter_id);
|
|
|
|
// Check email is sent to the correct newsletter
|
|
email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('recipient_filter')).eql('all');
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Can\'t change the newsletter once it has been sent', async function () {
|
|
// Note: this test only works if there are members subscribed to the initial newsletter
|
|
// (so it won't get reset when changing the post status to draft again)
|
|
|
|
let model;
|
|
const post = {
|
|
title: 'My post without newsletter_id',
|
|
status: 'draft',
|
|
feature_image_alt: 'Testing newsletter_id',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[0].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[0].slug;
|
|
const newsletterSlug2 = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const updatedPost = {
|
|
status: 'published',
|
|
updated_at: res.body.posts[0].updated_at
|
|
};
|
|
|
|
const res2 = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?email_segment=status:-free&newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
should(res2.body.posts[0].newsletter.id).eql(newsletterId);
|
|
should(res2.body.posts[0].email_segment).eql('status:-free');
|
|
|
|
should.not.exist(res2.body.posts[0].newsletter_id);
|
|
|
|
model = await models.Post.findOne({
|
|
id: id,
|
|
status: 'published'
|
|
}, testUtils.context.internal);
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('status:-free');
|
|
|
|
// Check email is sent to the correct newsletter
|
|
let email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('recipient_filter')).eql('status:-free');
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
|
|
const unpublished = {
|
|
status: 'draft',
|
|
updated_at: res2.body.posts[0].updated_at
|
|
};
|
|
|
|
const res3 = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [unpublished]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
// We should keep it, because we already sent an email
|
|
should(res3.body.posts[0].newsletter.id).eql(newsletterId);
|
|
should(res2.body.posts[0].email_segment).eql('status:-free');
|
|
should.not.exist(res3.body.posts[0].newsletter_id);
|
|
|
|
model = await models.Post.findOne({
|
|
id: id,
|
|
status: 'draft'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
|
|
// Check email
|
|
// Note: we only create an email if we have members susbcribed to the newsletter
|
|
email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.exist(email);
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
|
|
const republished = {
|
|
status: 'published',
|
|
updated_at: res3.body.posts[0].updated_at
|
|
};
|
|
|
|
const res4 = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug2))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [republished]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
// + did update the newsletter id
|
|
should(res4.body.posts[0].newsletter.id).eql(newsletterId);
|
|
should(res4.body.posts[0].email_segment).eql('status:-free');
|
|
should.not.exist(res4.body.posts[0].newsletter_id);
|
|
|
|
model = await models.Post.findOne({
|
|
id: id,
|
|
status: 'published'
|
|
}, testUtils.context.internal);
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
|
|
// Should not change if status remains published
|
|
const res5 = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [republished]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
// + did not update the newsletter id
|
|
should(res5.body.posts[0].newsletter.id).eql(newsletterId);
|
|
should(res5.body.posts[0].email_segment).eql('status:-free');
|
|
should.not.exist(res5.body.posts[0].newsletter_id);
|
|
|
|
model = await models.Post.findOne({
|
|
id: id,
|
|
status: 'published'
|
|
}, testUtils.context.internal);
|
|
|
|
// Test if the newsletter_id option was ignored
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
});
|
|
|
|
it('Cannot get post via pages endpoint', async function () {
|
|
await request.get(localUtils.API.getApiQuery(`pages/${testUtils.DataGenerator.Content.posts[3].id}/`))
|
|
.set('Origin', config.get('url'))
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(404);
|
|
});
|
|
|
|
it('Cannot update post via pages endpoint', async function () {
|
|
const post = {
|
|
title: 'fails',
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
await request.put(localUtils.API.getApiQuery('pages/' + testUtils.DataGenerator.Content.posts[3].id))
|
|
.set('Origin', config.get('url'))
|
|
.send({pages: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(404);
|
|
});
|
|
|
|
describe('As Author', function () {
|
|
before(async function () {
|
|
const user = await testUtils.createUser({
|
|
user: testUtils.DataGenerator.forKnex.createUser({
|
|
email: 'test+author@ghost.org'
|
|
}),
|
|
role: testUtils.DataGenerator.Content.roles[2].name
|
|
});
|
|
|
|
request.user = user;
|
|
await localUtils.doAuth(request);
|
|
});
|
|
|
|
it('Can publish a post and send as email', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'Author newsletter_id post',
|
|
status: 'draft',
|
|
authors: [{id: request.user.id}],
|
|
feature_image_alt: 'Testing newsletter_id',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
// Check newsletter relation is loaded, but null in response.
|
|
should(res.body.posts[0].newsletter).eql(null);
|
|
should.not.exist(res.body.posts[0].newsletter_id);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'published';
|
|
|
|
const finalPost = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
// Check newsletter relation is loaded in response
|
|
should(finalPost.body.posts[0].newsletter.id).eql(newsletterId);
|
|
should(finalPost.body.posts[0].email_segment).eql('all');
|
|
should.not.exist(finalPost.body.posts[0].newsletter_id);
|
|
|
|
const model = await models.Post.findOne({
|
|
id
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
|
|
// Check email
|
|
// Note: we only create an email if we have members susbcribed to the newsletter
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should.exist(email);
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
|
|
it('Can publish an email_only post', async function () {
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const post = {
|
|
title: 'My post',
|
|
status: 'draft',
|
|
authors: [{id: request.user.id}],
|
|
feature_image_alt: 'Testing newsletter in posts',
|
|
feature_image_caption: 'Testing <b>feature image caption</b>',
|
|
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
|
|
created_at: moment().subtract(2, 'days').toDate(),
|
|
updated_at: moment().subtract(2, 'days').toDate(),
|
|
created_by: ObjectId().toHexString(),
|
|
updated_by: ObjectId().toHexString()
|
|
};
|
|
|
|
const res = await request.post(localUtils.API.getApiQuery('posts'))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [post]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(201);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
const updatedPost = res.body.posts[0];
|
|
|
|
updatedPost.status = 'published';
|
|
//updatedPost.published_at = moment().add(2, 'days').toDate();
|
|
updatedPost.email_only = true;
|
|
|
|
const publishedRes = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?newsletter=' + newsletterSlug))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [updatedPost]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(200);
|
|
|
|
const publishedPost = publishedRes.body.posts[0];
|
|
|
|
publishedPost.newsletter.id.should.eql(newsletterId);
|
|
publishedPost.email_segment.should.eql('all');
|
|
publishedPost.status.should.eql('sent');
|
|
should.not.exist(publishedPost.newsletter_id);
|
|
|
|
let model = await models.Post.findOne({
|
|
id,
|
|
status: 'all'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('status')).eql('sent');
|
|
should(model.get('newsletter_id')).eql(newsletterId);
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
|
|
// We should have an email
|
|
const email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email.get('newsletter_id')).eql(newsletterId);
|
|
should(email.get('recipient_filter')).eql('all');
|
|
should(email.get('status')).equalOneOf('pending', 'submitted', 'submitting');
|
|
});
|
|
});
|
|
|
|
describe('Host Settings: emails limits', function () {
|
|
afterEach(function () {
|
|
configUtils.set('hostSettings:limits', undefined);
|
|
});
|
|
|
|
it('Request fails when emails limit is in place', async function () {
|
|
configUtils.set('hostSettings:limits', {
|
|
emails: {
|
|
disabled: true,
|
|
error: 'No email shalt be sent'
|
|
}
|
|
});
|
|
|
|
// NOTE: need to do a full reboot to reinitialize hostSettings
|
|
await localUtils.startGhost();
|
|
request = supertest.agent(config.get('url'));
|
|
await localUtils.doAuth(request, 'users:extra', 'posts', 'emails', 'newsletters');
|
|
|
|
const draftPostResponse = await request
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[3].id}/`))
|
|
.set('Origin', config.get('url'))
|
|
.expect(200);
|
|
|
|
const draftPost = draftPostResponse.body.posts[0];
|
|
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
|
|
|
|
const loggingStub = sinon.stub(logging, 'error');
|
|
|
|
const response = await request
|
|
.put(localUtils.API.getApiQuery(`posts/${draftPost.id}/?newsletter=${newsletterSlug}`))
|
|
.set('Origin', config.get('url'))
|
|
.send({posts: [{
|
|
status: 'published',
|
|
updated_at: draftPost.updated_at
|
|
}]})
|
|
.expect('Content-Type', /json/)
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
.expect(403);
|
|
|
|
response.body.errors[0].type.should.equal('HostLimitError');
|
|
response.body.errors[0].context.should.equal('No email shalt be sent');
|
|
sinon.assert.calledOnce(loggingStub);
|
|
});
|
|
});
|
|
});
|