mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
Added regression tests for content gating
no issue - There was a lack of any kind of tests checking if content gating behaves as it should. These changes create a base to expand upon when more changes are introduced into content gating mechanism - One thing that would be great to add in the future is imitation of member authentication to test the content is visible for authenticated paying/non-paying members - Added 'members only' tests - Added 'paid' post test case - Added plaintext gating test case
This commit is contained in:
parent
4361a0b936
commit
6fa20066f5
3 changed files with 378 additions and 0 deletions
|
@ -1,6 +1,9 @@
|
||||||
const should = require('should');
|
const should = require('should');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
const moment = require('moment');
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const labs = require('../../../../../server/services/labs');
|
||||||
const testUtils = require('../../../../utils');
|
const testUtils = require('../../../../utils');
|
||||||
const localUtils = require('./utils');
|
const localUtils = require('./utils');
|
||||||
const configUtils = require('../../../../utils/configUtils');
|
const configUtils = require('../../../../utils/configUtils');
|
||||||
|
@ -219,4 +222,127 @@ describe('api/canary/content/posts', function () {
|
||||||
localUtils.API.checkResponse(res.body.posts[0], 'post', null, null, ['id', 'title', 'slug']);
|
localUtils.API.checkResponse(res.body.posts[0], 'post', null, null, ['id', 'title', 'slug']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('content gating', function () {
|
||||||
|
let membersPost;
|
||||||
|
let paidPost;
|
||||||
|
|
||||||
|
before(function () {
|
||||||
|
// NOTE: ideally this would be set through Admin API request not a stub
|
||||||
|
sinon.stub(labs, 'isSet').withArgs('members').returns(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
before (function () {
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
return testUtils.fixtures.insertPosts([
|
||||||
|
membersPost,
|
||||||
|
paidPost
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read members only post content', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null);
|
||||||
|
post.slug.should.eql('thou-shalt-not-be-seen');
|
||||||
|
post.html.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read paid only post content', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${paidPost.id}/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null);
|
||||||
|
post.slug.should.eql('thou-shalt-be-paid-for');
|
||||||
|
post.html.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read members only post plaintext', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/?key=${validKey}&formats=html,plaintext&fields=html,plaintext`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null, ['id', 'html', 'plaintext']);
|
||||||
|
post.html.should.eql('');
|
||||||
|
post.plaintext.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot browse members only posts content', function () {
|
||||||
|
return request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
res.headers.vary.should.eql('Accept-Encoding');
|
||||||
|
should.exist(res.headers['access-control-allow-origin']);
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Default order 'published_at desc' check
|
||||||
|
jsonResponse.posts[0].slug.should.eql('thou-shalt-not-be-seen');
|
||||||
|
jsonResponse.posts[1].slug.should.eql('thou-shalt-be-paid-for');
|
||||||
|
jsonResponse.posts[6].slug.should.eql('organising-content');
|
||||||
|
|
||||||
|
jsonResponse.posts[0].html.should.eql('');
|
||||||
|
jsonResponse.posts[1].html.should.eql('');
|
||||||
|
jsonResponse.posts[6].html.should.not.eql('');
|
||||||
|
|
||||||
|
// check meta response for this test
|
||||||
|
jsonResponse.meta.pagination.page.should.eql(1);
|
||||||
|
jsonResponse.meta.pagination.limit.should.eql(15);
|
||||||
|
jsonResponse.meta.pagination.pages.should.eql(1);
|
||||||
|
jsonResponse.meta.pagination.total.should.eql(13);
|
||||||
|
jsonResponse.meta.pagination.hasOwnProperty('next').should.be.true();
|
||||||
|
jsonResponse.meta.pagination.hasOwnProperty('prev').should.be.true();
|
||||||
|
should.not.exist(jsonResponse.meta.pagination.next);
|
||||||
|
should.not.exist(jsonResponse.meta.pagination.prev);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
const should = require('should');
|
const should = require('should');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
const moment = require('moment');
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const cheerio = require('cheerio');
|
const cheerio = require('cheerio');
|
||||||
|
const labs = require('../../../../../server/services/labs');
|
||||||
const testUtils = require('../../../../utils');
|
const testUtils = require('../../../../utils');
|
||||||
const localUtils = require('./utils');
|
const localUtils = require('./utils');
|
||||||
const configUtils = require('../../../../utils/configUtils');
|
const configUtils = require('../../../../utils/configUtils');
|
||||||
|
@ -199,4 +202,127 @@ describe('api/v2/content/posts', function () {
|
||||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('content gating', function () {
|
||||||
|
let membersPost;
|
||||||
|
let paidPost;
|
||||||
|
|
||||||
|
before(function () {
|
||||||
|
// NOTE: ideally this would be set through Admin API request not a stub
|
||||||
|
sinon.stub(labs, 'isSet').withArgs('members').returns(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
before (function () {
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
return testUtils.fixtures.insertPosts([
|
||||||
|
membersPost,
|
||||||
|
paidPost
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read members only post content', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null);
|
||||||
|
post.slug.should.eql('thou-shalt-not-be-seen');
|
||||||
|
post.html.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read paid only post content', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${paidPost.id}/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null);
|
||||||
|
post.slug.should.eql('thou-shalt-be-paid-for');
|
||||||
|
post.html.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read members only post plaintext', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/?key=${validKey}&formats=html,plaintext&fields=html,plaintext`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null, ['id', 'html', 'plaintext']);
|
||||||
|
post.html.should.eql('');
|
||||||
|
post.plaintext.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot browse members only posts content', function () {
|
||||||
|
return request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
res.headers.vary.should.eql('Accept-Encoding');
|
||||||
|
should.exist(res.headers['access-control-allow-origin']);
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Default order 'published_at desc' check
|
||||||
|
jsonResponse.posts[0].slug.should.eql('thou-shalt-not-be-seen');
|
||||||
|
jsonResponse.posts[1].slug.should.eql('thou-shalt-be-paid-for');
|
||||||
|
jsonResponse.posts[6].slug.should.eql('organising-content');
|
||||||
|
|
||||||
|
jsonResponse.posts[0].html.should.eql('');
|
||||||
|
jsonResponse.posts[1].html.should.eql('');
|
||||||
|
jsonResponse.posts[6].html.should.not.eql('');
|
||||||
|
|
||||||
|
// check meta response for this test
|
||||||
|
jsonResponse.meta.pagination.page.should.eql(1);
|
||||||
|
jsonResponse.meta.pagination.limit.should.eql(15);
|
||||||
|
jsonResponse.meta.pagination.pages.should.eql(1);
|
||||||
|
jsonResponse.meta.pagination.total.should.eql(13);
|
||||||
|
jsonResponse.meta.pagination.hasOwnProperty('next').should.be.true();
|
||||||
|
jsonResponse.meta.pagination.hasOwnProperty('prev').should.be.true();
|
||||||
|
should.not.exist(jsonResponse.meta.pagination.next);
|
||||||
|
should.not.exist(jsonResponse.meta.pagination.prev);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
const should = require('should');
|
const should = require('should');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
const moment = require('moment');
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const labs = require('../../../../../server/services/labs');
|
||||||
const testUtils = require('../../../../utils');
|
const testUtils = require('../../../../utils');
|
||||||
const localUtils = require('./utils');
|
const localUtils = require('./utils');
|
||||||
const configUtils = require('../../../../utils/configUtils');
|
const configUtils = require('../../../../utils/configUtils');
|
||||||
|
@ -219,4 +222,127 @@ describe('api/v3/content/posts', function () {
|
||||||
localUtils.API.checkResponse(res.body.posts[0], 'post', null, null, ['id', 'title', 'slug']);
|
localUtils.API.checkResponse(res.body.posts[0], 'post', null, null, ['id', 'title', 'slug']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('content gating', function () {
|
||||||
|
let membersPost;
|
||||||
|
let paidPost;
|
||||||
|
|
||||||
|
before(function () {
|
||||||
|
// NOTE: ideally this would be set through Admin API request not a stub
|
||||||
|
sinon.stub(labs, 'isSet').withArgs('members').returns(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
before (function () {
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
return testUtils.fixtures.insertPosts([
|
||||||
|
membersPost,
|
||||||
|
paidPost
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read members only post content', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null);
|
||||||
|
post.slug.should.eql('thou-shalt-not-be-seen');
|
||||||
|
post.html.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read paid only post content', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${paidPost.id}/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null);
|
||||||
|
post.slug.should.eql('thou-shalt-be-paid-for');
|
||||||
|
post.html.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot read members only post plaintext', function () {
|
||||||
|
return request
|
||||||
|
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/?key=${validKey}&formats=html,plaintext&fields=html,plaintext`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
const jsonResponse = res.body;
|
||||||
|
should.exist(jsonResponse.posts);
|
||||||
|
const post = jsonResponse.posts[0];
|
||||||
|
|
||||||
|
localUtils.API.checkResponse(post, 'post', null, null, ['id', 'html', 'plaintext']);
|
||||||
|
post.html.should.eql('');
|
||||||
|
post.plaintext.should.eql('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot browse members only posts content', function () {
|
||||||
|
return request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}`))
|
||||||
|
.set('Origin', testUtils.API.getURL())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
.expect(200)
|
||||||
|
.then((res) => {
|
||||||
|
res.headers.vary.should.eql('Accept-Encoding');
|
||||||
|
should.exist(res.headers['access-control-allow-origin']);
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Default order 'published_at desc' check
|
||||||
|
jsonResponse.posts[0].slug.should.eql('thou-shalt-not-be-seen');
|
||||||
|
jsonResponse.posts[1].slug.should.eql('thou-shalt-be-paid-for');
|
||||||
|
jsonResponse.posts[6].slug.should.eql('organising-content');
|
||||||
|
|
||||||
|
jsonResponse.posts[0].html.should.eql('');
|
||||||
|
jsonResponse.posts[1].html.should.eql('');
|
||||||
|
jsonResponse.posts[6].html.should.not.eql('');
|
||||||
|
|
||||||
|
// check meta response for this test
|
||||||
|
jsonResponse.meta.pagination.page.should.eql(1);
|
||||||
|
jsonResponse.meta.pagination.limit.should.eql(15);
|
||||||
|
jsonResponse.meta.pagination.pages.should.eql(1);
|
||||||
|
jsonResponse.meta.pagination.total.should.eql(13);
|
||||||
|
jsonResponse.meta.pagination.hasOwnProperty('next').should.be.true();
|
||||||
|
jsonResponse.meta.pagination.hasOwnProperty('prev').should.be.true();
|
||||||
|
should.not.exist(jsonResponse.meta.pagination.next);
|
||||||
|
should.not.exist(jsonResponse.meta.pagination.prev);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue