2020-12-03 23:13:37 +03:00
|
|
|
const _ = require('lodash');
|
2019-08-09 17:25:12 +03:00
|
|
|
const should = require('should');
|
|
|
|
const supertest = require('supertest');
|
|
|
|
const ObjectId = require('bson-objectid');
|
|
|
|
const moment = require('moment-timezone');
|
|
|
|
const testUtils = require('../../../../utils');
|
2020-05-27 20:47:53 +03:00
|
|
|
const config = require('../../../../../core/shared/config');
|
2020-03-30 18:26:47 +03:00
|
|
|
const models = require('../../../../../core/server/models');
|
2019-08-09 17:25:12 +03:00
|
|
|
const localUtils = require('./utils');
|
|
|
|
const ghost = testUtils.startGhost;
|
|
|
|
let request;
|
|
|
|
|
2021-03-05 16:54:01 +03:00
|
|
|
describe('Posts API (canary)', function () {
|
2019-08-09 17:25:12 +03:00
|
|
|
let ghostServer;
|
|
|
|
|
|
|
|
before(function () {
|
|
|
|
return ghost()
|
|
|
|
.then(function (_ghostServer) {
|
|
|
|
ghostServer = _ghostServer;
|
|
|
|
request = supertest.agent(config.get('url'));
|
|
|
|
})
|
|
|
|
.then(function () {
|
2021-08-06 10:50:09 +03:00
|
|
|
return localUtils.doAuth(request, 'users:extra', 'posts', 'emails', 'members');
|
2019-08-09 17:25:12 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('Browse', function () {
|
|
|
|
it('fields & formats combined', function (done) {
|
|
|
|
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html&fields=id,title'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.end(function (err, res) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
null,
|
|
|
|
['mobiledoc', 'id', 'title', 'html']
|
|
|
|
);
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('combined fields, formats, include and non existing', function (done) {
|
2019-11-06 12:30:11 +03:00
|
|
|
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html,plaintext&fields=id,title,primary_tag,doesnotexist&include=authors,tags,email'))
|
2019-08-09 17:25:12 +03:00
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.end(function (err, res) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
null,
|
2019-11-06 12:30:11 +03:00
|
|
|
['mobiledoc', 'plaintext', 'id', 'title', 'html', 'authors', 'tags', 'primary_tag', 'email']
|
2019-08-09 17:25:12 +03:00
|
|
|
);
|
2020-09-24 04:32:40 +03:00
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-11-02 02:53:57 +03:00
|
|
|
it('can filter by fields coming from posts_meta table non null meta_description', function (done) {
|
|
|
|
request.get(localUtils.API.getApiQuery(`posts/?filter=meta_description:-null`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.end(function (err, res) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
jsonResponse.posts.forEach((post) => {
|
|
|
|
should.notEqual(post.meta_description, null);
|
|
|
|
});
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(
|
|
|
|
jsonResponse.posts[0],
|
|
|
|
'post'
|
|
|
|
);
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can filter by fields coming from posts_meta table by value', function (done) {
|
|
|
|
request.get(localUtils.API.getApiQuery(`posts/?filter=meta_description:'meta description for short and sweet'`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.end(function (err, res) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
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(1);
|
|
|
|
jsonResponse.posts[0].id.should.equal(testUtils.DataGenerator.Content.posts[2].id);
|
|
|
|
jsonResponse.posts[0].meta_description.should.equal('meta description for short and sweet');
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(
|
|
|
|
jsonResponse.posts[0],
|
|
|
|
'post'
|
|
|
|
);
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-09-24 04:32:40 +03:00
|
|
|
it('can order by fields coming from posts_meta table', function (done) {
|
|
|
|
request.get(localUtils.API.getApiQuery('posts/?order=meta_description%20ASC'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.end(function (err, res) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
should.equal(jsonResponse.posts[0].meta_description, null);
|
|
|
|
jsonResponse.posts[12].slug.should.equal('short-and-sweet');
|
2020-11-02 02:53:57 +03:00
|
|
|
jsonResponse.posts[12].meta_description.should.equal('meta description for short and sweet');
|
2020-09-24 04:32:40 +03:00
|
|
|
|
|
|
|
localUtils.API.checkResponse(
|
|
|
|
jsonResponse.posts[0],
|
|
|
|
'post'
|
|
|
|
);
|
2019-08-09 17:25:12 +03:00
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
|
|
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2020-12-03 23:13:37 +03:00
|
|
|
|
|
|
|
it('can order by email open rate', async function () {
|
|
|
|
try {
|
|
|
|
await testUtils.createEmailedPost({
|
|
|
|
postOptions: {
|
|
|
|
post: {
|
|
|
|
slug: '80-open-rate'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
emailOptions: {
|
|
|
|
email: {
|
|
|
|
email_count: 100,
|
|
|
|
opened_count: 80,
|
|
|
|
track_opens: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
await testUtils.createEmailedPost({
|
|
|
|
postOptions: {
|
|
|
|
post: {
|
|
|
|
slug: '60-open-rate'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
emailOptions: {
|
|
|
|
email: {
|
|
|
|
email_count: 100,
|
|
|
|
opened_count: 60,
|
|
|
|
track_opens: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
if (_.isArray(err)) {
|
|
|
|
throw err[0];
|
|
|
|
}
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
|
|
|
|
await request.get(localUtils.API.getApiQuery('posts/?order=email.open_rate%20DESC'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
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(15);
|
|
|
|
|
|
|
|
jsonResponse.posts[0].slug.should.equal('80-open-rate', 'DESC 1st');
|
|
|
|
jsonResponse.posts[1].slug.should.equal('60-open-rate', 'DESC 2nd');
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
|
|
|
});
|
|
|
|
|
|
|
|
await request.get(localUtils.API.getApiQuery('posts/?order=email.open_rate%20ASC'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
jsonResponse.posts[0].slug.should.equal('60-open-rate', 'ASC 1st');
|
|
|
|
jsonResponse.posts[1].slug.should.equal('80-open-rate', 'ASC 2nd');
|
|
|
|
});
|
|
|
|
});
|
2019-08-09 17:25:12 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('Read', function () {
|
|
|
|
it('can\'t retrieve non existent post', function (done) {
|
2021-04-21 18:02:02 +03:00
|
|
|
request.get(localUtils.API.getApiQuery(`posts/${ObjectId().toHexString()}/`))
|
2019-08-09 17:25:12 +03:00
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.set('Accept', 'application/json')
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(404)
|
|
|
|
.end(function (err, res) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
2020-04-29 18:44:27 +03:00
|
|
|
const jsonResponse = res.body;
|
2019-08-09 17:25:12 +03:00
|
|
|
should.exist(jsonResponse);
|
|
|
|
should.exist(jsonResponse.errors);
|
|
|
|
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
|
|
|
'message',
|
|
|
|
'context',
|
|
|
|
'type',
|
|
|
|
'details',
|
|
|
|
'property',
|
|
|
|
'help',
|
|
|
|
'code',
|
|
|
|
'id'
|
|
|
|
]);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2021-07-06 10:58:14 +03:00
|
|
|
|
|
|
|
it('throws a 400 when a non-existing field is requested', async function () {
|
|
|
|
await request.get(localUtils.API.getApiQuery(`posts/slug/${testUtils.DataGenerator.Content.posts[0].slug}/?fields=tags`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(400);
|
|
|
|
});
|
2019-08-09 17:25:12 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('Add', function () {
|
|
|
|
it('adds default title when it is missing', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('posts/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
title: ''
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(201)
|
2019-08-19 14:41:09 +03:00
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].title);
|
|
|
|
res.body.posts[0].title.should.equal('(Untitled)');
|
2020-09-14 13:33:37 +03:00
|
|
|
|
|
|
|
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}/`);
|
2019-08-19 14:41:09 +03:00
|
|
|
});
|
2019-08-09 17:25:12 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('Edit', function () {
|
|
|
|
it('published_at = null', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
published_at: null,
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
// @NOTE: if you set published_at to null and the post is published, we set it to NOW in model layer
|
|
|
|
should.exist(res.headers['x-cache-invalidate']);
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].published_at);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-08-06 10:50:09 +03:00
|
|
|
it('publishes a post with email_only and sends email', async function () {
|
|
|
|
const res = await request
|
|
|
|
.post(localUtils.API.getApiQuery('posts/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
title: 'Email me',
|
|
|
|
email_only: true
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(201);
|
|
|
|
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].title);
|
|
|
|
res.body.posts[0].title.should.equal('Email me');
|
|
|
|
res.body.posts[0].email_only.should.be.true();
|
|
|
|
res.body.posts[0].status.should.equal('draft');
|
|
|
|
|
|
|
|
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}/`);
|
|
|
|
|
|
|
|
const publishedRes = await request
|
|
|
|
.put(localUtils.API.getApiQuery(`posts/${res.body.posts[0].id}/?email_recipient_filter=all&send_email_when_published=true`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
status: 'published',
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
|
|
|
|
should.exist(publishedRes.body.posts);
|
|
|
|
res.body.posts[0].email_only.should.be.true();
|
|
|
|
publishedRes.body.posts[0].status.should.equal('draft');
|
|
|
|
|
|
|
|
should.exist(publishedRes.body.posts[0].email);
|
|
|
|
publishedRes.body.posts[0].email.email_count.should.equal(8);
|
|
|
|
});
|
|
|
|
|
2021-05-13 11:14:05 +03:00
|
|
|
it('read-only value do not cause errors when edited', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
frontmatter: 'hey!',
|
|
|
|
plaintext: 'hello!',
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
// NOTE: when ONLY ignored fields are posted they should not change a thing, thus cache stays untouched
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
|
|
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].published_at);
|
|
|
|
should.equal(res.body.posts[0].frontmatter, null);
|
|
|
|
should.equal(res.body.posts[0].plaintext, testUtils.DataGenerator.Content.posts[0].plaintext);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-08-09 17:25:12 +03:00
|
|
|
it('html to plaintext', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/?source=html&formats=html,plaintext'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
html: '<p>HTML Ipsum presents</p>',
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
return models.Post.findOne({
|
|
|
|
id: res.body.posts[0].id
|
|
|
|
}, testUtils.context.internal);
|
|
|
|
})
|
|
|
|
.then((model) => {
|
|
|
|
model.get('plaintext').should.equal('HTML Ipsum presents');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('canonical_url', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
canonical_url: `/canonical/url`,
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].canonical_url);
|
|
|
|
res.body.posts[0].canonical_url.should.equal(`${config.get('url')}/canonical/url`);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('update dates & x_by', function () {
|
|
|
|
const post = {
|
2021-04-21 18:02:02 +03:00
|
|
|
created_by: ObjectId().toHexString(),
|
|
|
|
updated_by: ObjectId().toHexString(),
|
2019-08-09 17:25:12 +03:00
|
|
|
created_at: moment().add(2, 'days').format(),
|
|
|
|
updated_at: moment().add(2, 'days').format()
|
|
|
|
};
|
|
|
|
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({posts: [post]})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
// @NOTE: you cannot modify these fields above manually, that's why the resource won't change.
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
|
|
|
|
|
|
return models.Post.findOne({
|
|
|
|
id: res.body.posts[0].id
|
|
|
|
}, testUtils.context.internal);
|
|
|
|
})
|
|
|
|
.then((model) => {
|
|
|
|
// We expect that the changed properties aren't changed, they are still the same than before.
|
|
|
|
model.get('created_at').toISOString().should.not.eql(post.created_at);
|
|
|
|
model.get('updated_by').should.not.eql(post.updated_by);
|
|
|
|
model.get('created_by').should.not.eql(post.created_by);
|
|
|
|
|
|
|
|
// `updated_at` is automatically set, but it's not the date we send to override.
|
|
|
|
model.get('updated_at').toISOString().should.not.eql(post.updated_at);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Can change scheduled post', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[7].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
res.body.posts[0].status.should.eql('scheduled');
|
|
|
|
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[7].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
title: 'change scheduled post',
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.headers['x-cache-invalidate']);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('trims title', function () {
|
|
|
|
const untrimmedTitle = ' test trimmed update title ';
|
|
|
|
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
title: untrimmedTitle,
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].title);
|
|
|
|
res.body.posts[0].title.should.equal(untrimmedTitle.trim());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('strips invisible unicode from slug', function () {
|
|
|
|
const slug = 'this-is\u0008-invisible';
|
|
|
|
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
slug: slug,
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].slug);
|
|
|
|
res.body.posts[0].slug.should.equal('this-is-invisible');
|
|
|
|
});
|
|
|
|
});
|
2019-09-26 16:38:35 +03:00
|
|
|
|
|
|
|
it('accepts visibility parameter', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
visibility: 'members',
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].visibility);
|
|
|
|
res.body.posts[0].visibility.should.equal('members');
|
|
|
|
});
|
|
|
|
});
|
2020-07-14 14:48:36 +03:00
|
|
|
|
|
|
|
it('changes to post_meta fields triggers a cache invalidation', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
meta_title: 'changed meta title',
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.headers['x-cache-invalidate']);
|
|
|
|
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.equal(res.body.posts[0].meta_title, 'changed meta title');
|
|
|
|
});
|
|
|
|
});
|
2020-07-15 08:41:24 +03:00
|
|
|
|
2021-08-04 14:00:32 +03:00
|
|
|
it('can edit post_meta field that has default value and no previously created posts_meta relation', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
should.equal(res.body.posts[0].email_only, false);
|
|
|
|
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[1].id + '/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
email_only: true,
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.headers['x-cache-invalidate']);
|
|
|
|
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.equal(res.body.posts[0].email_only, true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-07-15 08:41:24 +03:00
|
|
|
it('saving post with no modbiledoc content doesn\t trigger cache invalidation', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('posts/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
title: 'Has a title by no other content',
|
|
|
|
status: 'published'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(201)
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
should.exist(res.body.posts[0].title);
|
|
|
|
res.body.posts[0].title.should.equal('Has a title by no other content');
|
|
|
|
should.equal(res.body.posts[0].html, undefined);
|
|
|
|
should.equal(res.body.posts[0].plaintext, undefined);
|
|
|
|
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery(`posts/${res.body.posts[0].id}/`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
title: res.body.posts[0].title,
|
|
|
|
mobilecdoc: res.body.posts[0].mobilecdoc,
|
|
|
|
updated_at: res.body.posts[0].updated_at
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
|
|
|
|
|
|
should.exist(res.body.posts);
|
|
|
|
res.body.posts[0].title.should.equal('Has a title by no other content');
|
|
|
|
should.equal(res.body.posts[0].html, undefined);
|
|
|
|
should.equal(res.body.posts[0].plaintext, undefined);
|
|
|
|
});
|
|
|
|
});
|
2021-05-07 13:56:41 +03:00
|
|
|
|
|
|
|
it('errors with invalid email recipient filter', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('posts/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
title: 'Ready to be emailed',
|
|
|
|
status: 'draft'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(201)
|
|
|
|
.then((res) => {
|
|
|
|
return request
|
|
|
|
.put(`${localUtils.API.getApiQuery(`posts/${res.body.posts[0].id}/`)}?email_recipient_filter=not a filter`)
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
posts: [{
|
|
|
|
title: res.body.posts[0].title,
|
|
|
|
mobilecdoc: res.body.posts[0].mobilecdoc,
|
|
|
|
updated_at: res.body.posts[0].updated_at,
|
|
|
|
status: 'published'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(400);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
res.text.should.match(/invalid filter/i);
|
|
|
|
});
|
|
|
|
});
|
2019-08-09 17:25:12 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('Destroy', function () {
|
|
|
|
it('non existent post', function () {
|
|
|
|
return request
|
2021-04-21 18:02:02 +03:00
|
|
|
.del(localUtils.API.getApiQuery('posts/' + ObjectId().toHexString() + '/'))
|
2019-08-09 17:25:12 +03:00
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.set('Accept', 'application/json')
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(404)
|
|
|
|
.then((res) => {
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
|
|
should.exist(res.body);
|
|
|
|
should.exist(res.body.errors);
|
|
|
|
testUtils.API.checkResponseValue(res.body.errors[0], [
|
|
|
|
'message',
|
|
|
|
'context',
|
|
|
|
'type',
|
|
|
|
'details',
|
|
|
|
'property',
|
|
|
|
'help',
|
|
|
|
'code',
|
|
|
|
'id'
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|