mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-18 16:01:40 +03:00
13b0f51b13
refs: https://github.com/TryGhost/Toolbox/issues/389 This removes many error logs when the end-to-end test suite is run with the log-level set to error. Many errors are intentional, so the resolution is typically to stub the error log function and assert that it would have been called.
2018 lines
81 KiB
JavaScript
2018 lines
81 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.mockLabsDisabled('emailStability');
|
|
});
|
|
|
|
afterEach(function () {
|
|
mockManager.restore();
|
|
sinon.restore();
|
|
nock.cleanAll();
|
|
});
|
|
|
|
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']
|
|
);
|
|
|
|
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'))
|
|
.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 () {
|
|
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;
|
|
|
|
const res2 = 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;
|
|
|
|
const res2 = 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')).eql('pending');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
|
|
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 newsletterId2 = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
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')).eql('pending');
|
|
|
|
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('Can change the newsletter if it has not been sent', async function () {
|
|
// Note: this test only works if there are NO members subscribed to the initial newsletter
|
|
// (so it will get reset when changing the post status to draft again)
|
|
|
|
let model;
|
|
const post = {
|
|
title: 'My post that will get a changed newsletter',
|
|
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);
|
|
|
|
const id = res.body.posts[0].id;
|
|
|
|
// Check default values
|
|
should(res.body.posts[0].newsletter).eql(null);
|
|
should(res.body.posts[0].email_segment).eql('all');
|
|
|
|
const newsletterId = testUtils.DataGenerator.Content.newsletters[0].id;
|
|
const newsletterSlug = testUtils.DataGenerator.Content.newsletters[0].slug;
|
|
const newsletterId2 = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
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=id:0&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('id:0');
|
|
|
|
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('id:0');
|
|
|
|
// Check email is sent to the correct newsletter
|
|
let email = await models.Email.findOne({
|
|
post_id: id
|
|
}, testUtils.context.internal);
|
|
|
|
should(email).eql(null);
|
|
|
|
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 is reset
|
|
should(res3.body.posts[0].newsletter).eql(null);
|
|
should.not.exist(res3.body.posts[0].newsletter_id);
|
|
should(res3.body.posts[0].email_segment).eql('all');
|
|
|
|
model = await models.Post.findOne({
|
|
id: id,
|
|
status: 'draft'
|
|
}, testUtils.context.internal);
|
|
|
|
should(model.get('newsletter_id')).eql(null);
|
|
should(model.get('email_recipient_filter')).eql('all');
|
|
|
|
const republished = {
|
|
status: 'published',
|
|
updated_at: res3.body.posts[0].updated_at
|
|
};
|
|
|
|
const res4 = await request
|
|
.put(localUtils.API.getApiQuery('posts/' + id + '/?email_segment=status:-free&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(newsletterId2);
|
|
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(newsletterId2);
|
|
should(model.get('email_recipient_filter')).eql('status:-free');
|
|
|
|
// 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(newsletterId2);
|
|
should(email.get('recipient_filter')).eql('status:-free');
|
|
should(email.get('status')).eql('pending');
|
|
|
|
// 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(newsletterId2);
|
|
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(newsletterId2);
|
|
should(model.get('email_recipient_filter')).eql('status:-free');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
|
|
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')).eql('pending');
|
|
});
|
|
});
|
|
|
|
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 newsletterId = testUtils.DataGenerator.Content.newsletters[1].id;
|
|
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);
|
|
});
|
|
});
|
|
});
|