0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-10 23:36:14 -05:00

Reduced & moved acceptance tests for content API

refs #9178

- goal: only run main use cases regurlay
- the rest should run once per day
- reduced tests also
This commit is contained in:
kirrg001 2019-02-04 15:49:59 +01:00
parent 5d78d0ccfc
commit 9d8a450ede
11 changed files with 347 additions and 310 deletions

View file

@ -1,8 +1,8 @@
var should = require('should'),
supertest = require('supertest'),
testUtils = require('../../../../utils'),
localUtils = require('../../../../acceptance/old/admin/utils'),
config = require('../../../../../server/config'),
testUtils = require('../../../utils'),
localUtils = require('../../../acceptance/old/admin/utils'),
config = require('../../../../server/config'),
ghost = testUtils.startGhost,
request;

View file

@ -10,7 +10,7 @@ const localUtils = require('./utils');
const ghost = testUtils.startGhost;
let request;
describe('Authors Content API V2', function () {
describe('Authors Content API', function () {
let ghostServer;
before(function () {
@ -30,7 +30,7 @@ describe('Authors Content API V2', function () {
const validKey = localUtils.getValidKey();
it('browse authors', function (done) {
it('Can request authors', function (done) {
request.get(localUtils.API.getApiQuery(`authors/?key=${validKey}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
@ -67,69 +67,7 @@ describe('Authors Content API V2', function () {
});
});
it('browse authors: does not give back roles if trying to fetch roles', function (done) {
request.get(localUtils.API.getApiQuery(`authors/?key=${validKey}&include=roles`))
.set('Origin', testUtils.API.getURL())
.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.body.authors[0].roles);
done();
});
});
it('browse user by slug: count.posts', function (done) {
request.get(localUtils.API.getApiQuery(`authors/slug/ghost/?key=${validKey}&include=count.posts`))
.set('Origin', testUtils.API.getURL())
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.authors);
jsonResponse.authors.should.have.length(1);
// We don't expose the email address.
localUtils.API.checkResponse(jsonResponse.authors[0], 'author', ['count', 'url'], null, null);
done();
});
});
it('browse user by id: count.posts', function (done) {
request.get(localUtils.API.getApiQuery(`authors/1/?key=${validKey}&include=count.posts`))
.set('Origin', testUtils.API.getURL())
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.authors);
jsonResponse.authors.should.have.length(1);
// We don't expose the email address.
localUtils.API.checkResponse(jsonResponse.authors[0], 'author', ['count', 'url'], null, null);
done();
});
});
it('browse user with count.posts', function (done) {
it('Can request authors including post count', function (done) {
request.get(localUtils.API.getApiQuery(`authors/?key=${validKey}&include=count.posts&order=count.posts ASC`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
@ -166,8 +104,8 @@ describe('Authors Content API V2', function () {
});
});
it('browse authors: post count', function (done) {
request.get(localUtils.API.getApiQuery(`authors/?key=${validKey}&include=count.posts`))
it('Can request single author', function (done) {
request.get(localUtils.API.getApiQuery(`authors/slug/ghost/?key=${validKey}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
@ -179,9 +117,32 @@ describe('Authors Content API V2', function () {
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse.authors);
localUtils.API.checkResponse(jsonResponse, 'authors');
jsonResponse.authors.should.have.length(3);
jsonResponse.authors.should.have.length(1);
// We don't expose the email address.
localUtils.API.checkResponse(jsonResponse.authors[0], 'author', ['url'], null, null);
done();
});
});
it('Can request author by id including post count', function (done) {
request.get(localUtils.API.getApiQuery(`authors/1/?key=${validKey}&include=count.posts`))
.set('Origin', testUtils.API.getURL())
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.authors);
jsonResponse.authors.should.have.length(1);
// We don't expose the email address.
localUtils.API.checkResponse(jsonResponse.authors[0], 'author', ['count', 'url'], null, null);

View file

@ -7,12 +7,12 @@ const config = require('../../../../server/config');
const ghost = testUtils.startGhost;
describe('Content API V2 key authentication', function () {
describe('Content API key authentication', function () {
let request;
before(function () {
return ghost()
.then(function (_ghostServer) {
.then(function () {
request = supertest.agent(config.get('url'));
})
.then(function () {
@ -20,14 +20,14 @@ describe('Content API V2 key authentication', function () {
});
});
it('forbid access without key', function () {
it('Can not access without key', function () {
return request.get(localUtils.API.getApiQuery('posts/'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403);
});
it('browse with valid key', function () {
it('Can access with with valid key', function () {
const key = localUtils.getValidKey();
return request.get(localUtils.API.getApiQuery(`posts/?key=${key}`))

View file

@ -9,7 +9,7 @@ const config = require('../../../../server/config');
const ghost = testUtils.startGhost;
let request;
describe('Pages', function () {
describe('Pages Content API', function () {
before(function () {
return ghost()
.then(function () {
@ -24,7 +24,7 @@ describe('Pages', function () {
configUtils.restore();
});
it('browse pages', function () {
it('Can request pages', function () {
const key = localUtils.getValidKey();
return request.get(localUtils.API.getApiQuery(`pages/?key=${key}`))
.set('Origin', testUtils.API.getURL())
@ -49,27 +49,7 @@ describe('Pages', function () {
});
});
it('browse pages with page:false', function () {
const key = localUtils.getValidKey();
return request.get(localUtils.API.getApiQuery(`pages/?key=${key}&filter=page:false`))
.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.pages);
should.exist(jsonResponse.meta);
jsonResponse.pages.should.have.length(0);
});
});
it('read page', function () {
it('Can request page', function () {
const key = localUtils.getValidKey();
return request.get(localUtils.API.getApiQuery(`pages/${testUtils.DataGenerator.Content.posts[5].id}/?key=${key}`))
.set('Origin', testUtils.API.getURL())
@ -92,15 +72,4 @@ describe('Pages', function () {
should.exist(urlParts.host);
});
});
it('can\'t read post', function () {
const key = localUtils.getValidKey();
return request
.get(localUtils.API.getApiQuery(`pages/${testUtils.DataGenerator.Content.posts[0].id}/?key=${key}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404);
});
});

View file

@ -12,7 +12,7 @@ const config = require('../../../../server/config');
const ghost = testUtils.startGhost;
let request;
describe('Posts', function () {
describe('Posts Content API', function () {
before(function () {
return ghost()
.then(function () {
@ -29,7 +29,7 @@ describe('Posts', function () {
const validKey = localUtils.getValidKey();
it('browse posts', function (done) {
it('Can request posts', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
@ -91,7 +91,7 @@ describe('Posts', function () {
});
});
it('browse posts with basic filters', function (done) {
it('Can filter posts by tag', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=tag:kitchen-sink,featured:true&include=tags`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
@ -140,50 +140,7 @@ describe('Posts', function () {
});
});
it('browse posts with basic page filter should not return pages', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=page:true`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
should.not.exist(res.headers['x-cache-invalidate']);
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
jsonResponse.posts.should.have.length(0);
done();
});
});
it('browse posts with basic page filter should not return pages', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=page:true,featured:true`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
should.not.exist(res.headers['x-cache-invalidate']);
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
jsonResponse.posts.should.have.length(2);
jsonResponse.posts.filter(p => (p.page === true)).should.have.length(0);
done();
});
});
it('browse posts with author filter', function (done) {
it('Can filter posts by authors', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=authors:[joe-bloggs,pat,ghost,slimer-mcectoplasm]&include=authors`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
@ -220,50 +177,7 @@ describe('Posts', function () {
});
});
it('browse posts with published and draft status, should not return drafts', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=status:published,status:draft`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
jsonResponse.posts.should.be.an.Array().with.lengthOf(11);
done();
});
});
it('[deprecated] browse posts with page non matching filter', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=tag:no-posts`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
jsonResponse.posts.should.be.an.Array().with.lengthOf(0);
jsonResponse.meta.should.have.property('pagination');
jsonResponse.meta.pagination.should.be.an.Object().with.properties(['page', 'limit', 'pages', 'total', 'next', 'prev']);
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(0);
should.equal(jsonResponse.meta.pagination.next, null);
should.equal(jsonResponse.meta.pagination.prev, null);
done();
});
});
it('browse posts: request only url fields', function (done) {
it('Can request fields of posts', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&fields=url`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
@ -283,28 +197,7 @@ describe('Posts', function () {
});
});
it('browse posts: request only url fields with include', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&fields=url&include=tags`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', false, false, ['url','tags']);
jsonResponse.posts[0].url.should.eql('http://127.0.0.1:2369/welcome/');
jsonResponse.posts[0].tags[0].url.should.eql('http://127.0.0.1:2369/tag/getting-started/');
done();
});
});
it('browse posts: request to include tags and authors should always contain absolute urls', function (done) {
it('Can include relations', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&include=tags,authors`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
@ -344,7 +237,7 @@ describe('Posts', function () {
});
});
it('browse posts from different origin', function (done) {
it('Can request posts from different origin', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}`))
.set('Origin', 'https://example.com')
.expect('Content-Type', /json/)
@ -370,73 +263,7 @@ describe('Posts', function () {
});
});
it('ensure origin header on redirect is not getting lost', function (done) {
// NOTE: force a redirect to the admin url
configUtils.set('admin:url', 'http://localhost:9999');
request.get(localUtils.API.getApiQuery(`posts?key=${validKey}`))
.set('Origin', 'https://example.com')
// 301 Redirects _should_ be cached
.expect('Cache-Control', testUtils.cacheRules.year)
.expect(301)
.end(function (err, res) {
if (err) {
return done(err);
}
res.headers.vary.should.eql('Accept, Accept-Encoding');
res.headers.location.should.eql(`http://localhost:9999/ghost/api/v2/content/posts/?key=${validKey}`);
should.exist(res.headers['access-control-allow-origin']);
should.not.exist(res.headers['x-cache-invalidate']);
done();
});
});
it('browse posts, ignores staticPages', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&staticPages=true`))
.set('Origin', testUtils.API.getURL())
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts');
jsonResponse.posts.should.have.length(11);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
done();
});
});
it('denies access with invalid key', function (done) {
request.get(localUtils.API.getApiQuery('posts/?key=invalid-key'))
.set('Origin', testUtils.API.getURL())
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(401)
.end(function (err, res) {
if (err) {
return done(err);
}
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
it('fetch the most recent post, then the prev, then the next should match the first', function (done) {
it('Can filter by published date', function (done) {
function createFilter(publishedAt, op) {
// This line deliberately uses double quotes because GQL cannot handle either double quotes
// or escaped singles, see TryGhost/GQL#34
@ -488,7 +315,7 @@ describe('Posts', function () {
.catch(done);
});
it('read posts', function () {
it('Can request a single post', function () {
return request
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/?key=${validKey}`))
.set('Origin', testUtils.API.getURL())
@ -504,13 +331,4 @@ describe('Posts', function () {
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
});
});
it('can\'t read page', function () {
return request
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[5].id}/?key=${validKey}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404);
});
});

View file

@ -12,7 +12,7 @@ const defaultSettings = require('../../../../server/data/schema').defaultSetting
const ghost = testUtils.startGhost;
let request;
describe('Settings', function () {
describe('Settings Content API', function () {
before(function () {
return ghost()
.then(function () {
@ -22,7 +22,7 @@ describe('Settings', function () {
});
});
it('browse settings', function () {
it('Can request settings', function () {
const key = localUtils.getValidKey();
return request.get(localUtils.API.getApiQuery(`settings/?key=${key}`))
.set('Origin', testUtils.API.getURL())

View file

@ -8,7 +8,7 @@ const testUtils = require('../../../utils');
const localUtils = require('./utils');
const ghost = testUtils.startGhost;
describe('Tags Content API V2', function () {
describe('Tags Content API', function () {
let request;
before(function () {
@ -27,7 +27,7 @@ describe('Tags Content API V2', function () {
const validKey = localUtils.getValidKey();
it('browse tags without limit defaults to 15', function (done) {
it('Can request tags', function (done) {
request.get(localUtils.API.getApiQuery(`tags/?key=${validKey}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
@ -65,7 +65,7 @@ describe('Tags Content API V2', function () {
});
});
it('browse tags - limit=all should fetch all tags', function (done) {
it('Can request tags with limit=all', function (done) {
request.get(localUtils.API.getApiQuery(`tags/?limit=all&key=${validKey}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
@ -86,7 +86,7 @@ describe('Tags Content API V2', function () {
});
});
it('browse tags without limit=4 fetches 4 tags', function (done) {
it('Can limit tags to receive', function (done) {
request.get(localUtils.API.getApiQuery(`tags/?limit=3&key=${validKey}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
@ -108,8 +108,8 @@ describe('Tags Content API V2', function () {
});
});
it('browse tags - limit=all should fetch all tags and include count.posts', function (done) {
request.get(localUtils.API.getApiQuery(`tags/?limit=all&key=${validKey}&include=count.posts`))
it('Can include post count', function (done) {
request.get(localUtils.API.getApiQuery(`tags/?key=${validKey}&include=count.posts`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)

View file

@ -89,7 +89,7 @@ describe('DB API', () => {
.expect('Content-Type', /json/)
.expect(200)
.then((res) => {
(typeof res.body).should.be.Object();
res.body.should.be.Object();
res.body.db[0].filename.should.match(/test\.json/);
fsStub.calledOnce.should.eql(true);
});

View file

@ -0,0 +1,57 @@
const url = require('url');
const should = require('should');
const supertest = require('supertest');
const testUtils = require('../../../../utils');
const localUtils = require('./utils');
const configUtils = require('../../../../utils/configUtils');
const config = require('../../../../../server/config');
const ghost = testUtils.startGhost;
let request;
describe('Pages', function () {
before(function () {
return ghost()
.then(function () {
request = supertest.agent(config.get('url'));
})
.then(function () {
return testUtils.initFixtures('users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys');
});
});
afterEach(function () {
configUtils.restore();
});
it('browse pages with page:false', function () {
const key = localUtils.getValidKey();
return request.get(localUtils.API.getApiQuery(`pages/?key=${key}&filter=page:false`))
.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.pages);
should.exist(jsonResponse.meta);
jsonResponse.pages.should.have.length(0);
});
});
it('can\'t read post', function () {
const key = localUtils.getValidKey();
return request
.get(localUtils.API.getApiQuery(`pages/${testUtils.DataGenerator.Content.posts[0].id}/?key=${key}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404);
});
});

View file

@ -0,0 +1,145 @@
const should = require('should');
const supertest = require('supertest');
const _ = require('lodash');
const url = require('url');
const cheerio = require('cheerio');
const moment = require('moment');
const testUtils = require('../../../../utils');
const localUtils = require('./utils');
const configUtils = require('../../../../utils/configUtils');
const config = require('../../../../../server/config');
const ghost = testUtils.startGhost;
let request;
describe('Posts', function () {
before(function () {
return ghost()
.then(function () {
request = supertest.agent(config.get('url'));
})
.then(function () {
return testUtils.initFixtures('users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys');
});
});
afterEach(function () {
configUtils.restore();
});
const validKey = localUtils.getValidKey();
it('browse posts with basic page filter should not return pages', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=page:true`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
should.not.exist(res.headers['x-cache-invalidate']);
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
jsonResponse.posts.should.have.length(0);
done();
});
});
it('browse posts with basic page filter should not return pages', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=page:true,featured:true`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
should.not.exist(res.headers['x-cache-invalidate']);
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
jsonResponse.posts.should.have.length(2);
jsonResponse.posts.filter(p => (p.page === true)).should.have.length(0);
done();
});
});
it('browse posts with published and draft status, should not return drafts', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=status:published,status:draft`))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
jsonResponse.posts.should.be.an.Array().with.lengthOf(11);
done();
});
});
it('ensure origin header on redirect is not getting lost', function (done) {
// NOTE: force a redirect to the admin url
configUtils.set('admin:url', 'http://localhost:9999');
request.get(localUtils.API.getApiQuery(`posts?key=${validKey}`))
.set('Origin', 'https://example.com')
// 301 Redirects _should_ be cached
.expect('Cache-Control', testUtils.cacheRules.year)
.expect(301)
.end(function (err, res) {
if (err) {
return done(err);
}
res.headers.vary.should.eql('Accept, Accept-Encoding');
res.headers.location.should.eql(`http://localhost:9999/ghost/api/v2/content/posts/?key=${validKey}`);
should.exist(res.headers['access-control-allow-origin']);
should.not.exist(res.headers['x-cache-invalidate']);
done();
});
});
it('browse posts, ignores staticPages', function (done) {
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&staticPages=true`))
.set('Origin', testUtils.API.getURL())
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts');
jsonResponse.posts.should.have.length(11);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
done();
});
});
it('can\'t read page', function () {
return request
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[5].id}/?key=${validKey}`))
.set('Origin', testUtils.API.getURL())
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404);
});
});

View file

@ -0,0 +1,87 @@
const url = require('url');
const _ = require('lodash');
const testUtils = require('../../../../utils');
const schema = require('../../../../../server/data/schema').tables;
const API_URL = '/ghost/api/v2/content/';
const expectedProperties = {
// API top level
posts: ['posts', 'meta'],
tags: ['tags', 'meta'],
authors: ['authors', 'meta'],
pagination: ['page', 'limit', 'pages', 'total', 'next', 'prev'],
post: _(schema.posts)
.keys()
// by default we only return html
.without('mobiledoc', 'plaintext')
// v2 doesn't return author_id OR author
.without('author_id', 'author')
// and always returns computed properties: url, primary_tag, primary_author
.concat('url', 'primary_tag', 'primary_author')
// v2 API doesn't return unused fields
.without('locale', 'visibility')
// These fields aren't useful as they always have known values
.without('status')
// @TODO: https://github.com/TryGhost/Ghost/issues/10335
// .without('page')
// v2 returns a calculated excerpt field
.concat('excerpt')
,
author: _(schema.users)
.keys()
.without(
'password',
'email',
'ghost_auth_access_token',
'ghost_auth_id',
'created_at',
'created_by',
'updated_at',
'updated_by',
'last_seen',
'status'
)
// v2 API doesn't return unused fields
.without('accessibility', 'locale', 'tour', 'visibility')
,
tag: _(schema.tags)
.keys()
// v2 Tag API doesn't return parent_id or parent
.without('parent_id', 'parent')
// v2 Tag API doesn't return date fields
.without('created_at', 'updated_at')
};
_.each(expectedProperties, (value, key) => {
if (!value.__wrapped__) {
return;
}
/**
* @deprecated: x_by
*/
expectedProperties[key] = value
.without(
'created_by',
'updated_by',
'published_by'
)
.value();
});
module.exports = {
API: {
getApiQuery(route) {
return url.resolve(API_URL, route);
},
checkResponse(...args) {
this.expectedProperties = expectedProperties;
return testUtils.API.checkResponse.call(this, ...args);
}
},
getValidKey() {
return testUtils.DataGenerator.Content.api_keys[1].secret;
}
};