Reduced & moved acceptance tests for admin API

refs #9178

- consistent naming pattern
- less acceptance tests
This commit is contained in:
kirrg001 2019-02-04 15:16:24 +01:00
parent 8b3336c84d
commit 5d78d0ccfc
27 changed files with 2354 additions and 2462 deletions

View File

@ -6,6 +6,7 @@ const config = require('../../../../server/config');
const ghost = testUtils.startGhost;
let request;
describe('Configuration API', function () {
before(function () {
return ghost()
@ -17,7 +18,6 @@ describe('Configuration API', function () {
});
});
describe('success', function () {
it('can retrieve public configuration and all expected properties', function (done) {
request.get(localUtils.API.getApiQuery('configuration/'))
.set('Origin', config.get('url'))
@ -75,4 +75,3 @@ describe('Configuration API', function () {
});
});
});
});

View File

@ -52,7 +52,7 @@ describe('DB API', () => {
sinon.restore();
});
it('should export data', () => {
it('Can export a JSON database', () => {
return request.get(localUtils.API.getApiQuery(`db/`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -70,20 +70,7 @@ describe('DB API', () => {
});
});
it('include more tables', () => {
return request.get(localUtils.API.getApiQuery('db/?include=clients,client_trusted_domains'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect(200)
.then((res) => {
const jsonResponse = res.body;
should.exist(jsonResponse.db);
jsonResponse.db.should.have.length(1);
Object.keys(jsonResponse.db[0].data).length.should.eql(27);
});
});
it('import should succeed with default content', () => {
it('Can import a JSON database', () => {
return Promise.resolve()
.then(() => {
return request.delete(localUtils.API.getApiQuery('db/'))
@ -120,80 +107,9 @@ describe('DB API', () => {
});
});
it('import should fail without file', () => {
return request.post(localUtils.API.getApiQuery('db/'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(403);
});
it('import should fail with unsupported file', () => {
return request.post(localUtils.API.getApiQuery('db/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('importfile', path.join(__dirname, '/../../../utils/fixtures/csv/single-column-with-header.csv'))
.expect(415);
});
it('export can be triggered by backup client', () => {
const backupQuery = `?client_id=${backupClient.slug}&client_secret=${backupClient.secret}`;
const fsStub = sinon.stub(fs, 'writeFile').resolves();
return request.post(localUtils.API.getApiQuery(`db/backup${backupQuery}`))
.expect('Content-Type', /json/)
.expect(200)
.then((res) => {
(typeof res.body).should.be.Object;
should.exist(res.body.db[0].filename);
fsStub.calledOnce.should.eql(true);
});
});
it('export can be triggered and named by backup client', () => {
const backupQuery = `?client_id=${backupClient.slug}&client_secret=${backupClient.secret}&filename=test`;
const fsStub = sinon.stub(fs, 'writeFile').resolves();
return request.post(localUtils.API.getApiQuery(`db/backup${backupQuery}`))
.expect('Content-Type', /json/)
.expect(200)
.then((res) => {
(typeof res.body).should.be.Object;
res.body.db[0].filename.should.match(/test\.json/);
fsStub.calledOnce.should.eql(true);
});
});
it('export can not be triggered by client other than backup', () => {
const schedulerQuery = `?client_id=${schedulerClient.slug}&client_secret=${schedulerClient.secret}`;
const fsStub = sinon.stub(fs, 'writeFile').resolves();
return request.post(localUtils.API.getApiQuery(`db/backup${schedulerQuery}`))
.expect('Content-Type', /json/)
.expect(403)
.then(res => {
should.exist(res.body.errors);
res.body.errors[0].errorType.should.eql('NoPermissionError');
fsStub.called.should.eql(false);
});
});
it('export can not be triggered by regular authentication', () => {
const fsStub = sinon.stub(fs, 'writeFile').resolves();
return request.post(localUtils.API.getApiQuery(`db/backup`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect(401)
.then(res => {
should.exist(res.body.errors);
res.body.errors[0].errorType.should.eql('UnauthorizedError');
fsStub.called.should.eql(false);
});
});
it('delete all content (owner)', () => {
return request.get(localUtils.API.getApiQuery('posts/'))
it('Can delete all content', () => {
return request
.get(localUtils.API.getApiQuery('posts/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)

View File

@ -21,7 +21,6 @@ describe('Integrations API', function () {
const findBy = (prop, val) => object => object[prop] === val;
describe('POST /integrations/', function () {
it('Can successfully create a single integration with auto generated content and admin api key', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
@ -96,9 +95,7 @@ describe('Integrations API', function () {
done();
});
});
});
describe('GET /integrations/:id', function () {
it('Can successfully get a created integration', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
@ -138,15 +135,6 @@ describe('Integrations API', function () {
});
});
it('Will 404 if the integration does not exist', function (done) {
request.get(localUtils.API.getApiQuery(`integrations/012345678901234567890123/`))
.set('Origin', config.get('url'))
.expect(404)
.end(done);
});
});
describe('GET /integrations/', function () {
it('Can successfully get *all* created integrations with api_keys', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
@ -198,9 +186,7 @@ describe('Integrations API', function () {
});
});
});
});
describe('PUT /integrations/:id', function () {
it('Can successfully edit a created integration', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
@ -331,20 +317,6 @@ describe('Integrations API', function () {
});
});
it('Will 404 if the integration does not exist', function (done) {
request.put(localUtils.API.getApiQuery(`integrations/012345678901234567890123/`))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'This better not work'
}]
})
.expect(404)
.end(done);
});
});
describe('DELETE /integrations/:id', function () {
it('Can succesfully delete a created integration', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
@ -375,21 +347,4 @@ describe('Integrations API', function () {
});
});
});
it('Will 404 if the integration does not exist', function (done) {
request.del(localUtils.API.getApiQuery(`integrations/012345678901234567890123/`))
.set('Origin', config.get('url'))
.expect(404)
.end(done);
});
it('Will delete the associated api_keys and webhooks', function () {
/**
* @TODO
*
* We do not have the /apikeys or /webhooks endpoints yet
* This will be manually tested by egg before merging
*/
});
});
});

View File

@ -9,8 +9,8 @@ const ghost = testUtils.startGhost;
let request;
describe('Invites API V2', function () {
var accesstoken = '', ghostServer;
describe('Invites API', function () {
let ghostServer;
before(function () {
return ghost()
@ -20,9 +20,6 @@ describe('Invites API V2', function () {
})
.then(function () {
return localUtils.doAuth(request, 'invites');
})
.then(function (token) {
accesstoken = token;
});
});
@ -34,8 +31,7 @@ describe('Invites API V2', function () {
sinon.restore();
});
describe('browse', function () {
it('default', function (done) {
it('Can fetch all invites', function (done) {
request.get(localUtils.API.getApiQuery('invites/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -68,10 +64,8 @@ describe('Invites API V2', function () {
done();
});
});
});
describe('read', function () {
it('default', function (done) {
it('Can read an invitation by id', function (done) {
request.get(localUtils.API.getApiQuery(`invites/${testUtils.DataGenerator.forKnex.invites[0].id}/`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -95,10 +89,8 @@ describe('Invites API V2', function () {
done();
});
});
});
describe('add', function () {
it('default', function (done) {
it('Can add a new invite', function (done) {
request
.post(localUtils.API.getApiQuery('invites/'))
.set('Origin', config.get('url'))
@ -128,40 +120,7 @@ describe('Invites API V2', function () {
});
});
it('no email', function () {
return request
.post(localUtils.API.getApiQuery('invites/'))
.set('Origin', config.get('url'))
.send({
invites: [{role_id: testUtils.existingData.roles[1].id}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(422);
});
it('user exists', function (done) {
request.post(localUtils.API.getApiQuery('invites/'))
.set('Origin', config.get('url'))
.send({
invites: [{email: 'ghost-author@example.com', role_id: testUtils.existingData.roles[1].id}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(422)
.end(function (err, res) {
if (err) {
return done(err);
}
mailService.GhostMailer.prototype.send.called.should.be.false();
done();
});
});
});
describe('destroy', function () {
it('default', function (done) {
it('Can destroy an existing invite', function (done) {
request.del(localUtils.API.getApiQuery(`invites/${testUtils.DataGenerator.forKnex.invites[0].id}/`))
.set('Origin', config.get('url'))
.expect('Cache-Control', testUtils.cacheRules.private)
@ -176,4 +135,3 @@ describe('Invites API V2', function () {
});
});
});
});

View File

@ -7,12 +7,12 @@ const config = require('../../../../server/config');
const ghost = testUtils.startGhost;
describe('Admin API V2 key authentication', function () {
describe('Admin API key authentication', function () {
let request;
before(function () {
return ghost()
.then(function (_ghostServer) {
.then(function () {
request = supertest.agent(config.get('url'));
})
.then(function () {
@ -20,7 +20,7 @@ describe('Admin API V2 key authentication', function () {
});
});
it('do not authenticate without token header', function () {
it('Can not access endpoint without a token header', function () {
return request.get(localUtils.API.getApiQuery('posts/'))
.set('Authorization', `Ghost`)
.expect('Content-Type', /json/)
@ -28,7 +28,7 @@ describe('Admin API V2 key authentication', function () {
.expect(401);
});
it('do not authenticate with wrong endpoint token', function () {
it('Can not access endpoint with a wrong endpoint token', function () {
return request.get(localUtils.API.getApiQuery('posts/'))
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('https://wrong.com')}`)
.expect('Content-Type', /json/)
@ -36,15 +36,7 @@ describe('Admin API V2 key authentication', function () {
.expect(401);
});
it('browse with no endpoint token', function () {
return request.get(localUtils.API.getApiQuery('posts/'))
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('')}`)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(401);
});
it('browse with correct GET endpoint token', function () {
it('Can access browse endpoint with correct token', function () {
return request.get(localUtils.API.getApiQuery('posts/'))
.set('Authorization', `Ghost ${localUtils.getValidAdminToken(localUtils.API.getApiQuery('posts/'))}`)
.expect('Content-Type', /json/)
@ -52,7 +44,7 @@ describe('Admin API V2 key authentication', function () {
.expect(200);
});
it('POST to /post endpoint returns not implemented', function () {
it('Can access add endpoint with correct token', function () {
const post = {
authors: [{
id: testUtils.DataGenerator.Content.users[0].id

View File

@ -9,8 +9,8 @@ const ghost = testUtils.startGhost;
let request;
describe('Mail API V2', function () {
var accesstoken = '', ghostServer;
describe('Mail API', function () {
let ghostServer;
before(function () {
return ghost()
@ -20,9 +20,6 @@ describe('Mail API V2', function () {
})
.then(function () {
return localUtils.doAuth(request, 'invites');
})
.then(function (token) {
accesstoken = token;
});
});
@ -34,7 +31,7 @@ describe('Mail API V2', function () {
sinon.restore();
});
it('default', function () {
it('Can send mail', function () {
return request
.post(localUtils.API.getApiQuery('mail/'))
.set('Origin', config.get('url'))
@ -64,19 +61,4 @@ describe('Mail API V2', function () {
mailService.GhostMailer.prototype.send.called.should.be.true();
});
});
it('test mail', function () {
return request
.post(localUtils.API.getApiQuery('mail/test/'))
.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;
jsonResponse.should.eql({message: 'sent'});
mailService.GhostMailer.prototype.send.called.should.be.true();
});
});
});

View File

@ -6,7 +6,7 @@ const config = require('../../../../server/config');
const ghost = testUtils.startGhost;
let request;
describe('Notifications API V2', function () {
describe('Notifications API', function () {
let ghostServer;
before(function () {
@ -20,8 +20,7 @@ describe('Notifications API V2', function () {
});
});
describe('Add', function () {
it('creates a new notification and sets default fields', function (done) {
it('Can add notification', function (done) {
const newNotification = {
type: 'info',
message: 'test notification',
@ -58,103 +57,7 @@ describe('Notifications API V2', function () {
});
});
it('creates duplicate', function (done) {
const newNotification = {
type: 'info',
message: 'add twice',
custom: true,
id: 'customId-2'
};
request.post(localUtils.API.getApiQuery('notifications/'))
.set('Origin', config.get('url'))
.send({notifications: [newNotification]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
should.exist(jsonResponse.notifications);
jsonResponse.notifications.should.be.an.Array().with.lengthOf(1);
jsonResponse.notifications[0].message.should.equal(newNotification.message);
request.post(localUtils.API.getApiQuery('notifications/'))
.set('Origin', config.get('url'))
.send({notifications: [newNotification]})
.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.notifications);
jsonResponse.notifications.should.be.an.Array().with.lengthOf(0);
done();
});
});
});
it('should have correct order', function () {
const firstNotification = {
status: 'alert',
type: 'info',
custom: true,
id: 'firstId',
dismissible: true,
message: '1'
};
const secondNotification = {
status: 'alert',
type: 'info',
custom: true,
id: 'secondId',
dismissible: true,
message: '2'
};
return request.post(localUtils.API.getApiQuery('notifications/'))
.set('Origin', config.get('url'))
.send({notifications: [firstNotification]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.then(() => {
return request.post(localUtils.API.getApiQuery('notifications/'))
.set('Origin', config.get('url'))
.send({notifications: [secondNotification]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201);
})
.then(() => {
return request.get(localUtils.API.getApiQuery('notifications/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then(res => {
const jsonResponse = res.body;
jsonResponse.notifications.should.be.an.Array().with.lengthOf(4);
jsonResponse.notifications[0].id.should.equal(secondNotification.id);
jsonResponse.notifications[1].id.should.equal(firstNotification.id);
jsonResponse.notifications[2].id.should.equal('customId-2');
jsonResponse.notifications[3].id.should.equal('customId');
});
});
});
});
describe('Delete', function () {
it('Can delete notification', function (done) {
var newNotification = {
type: 'info',
message: 'test notification',
@ -162,7 +65,6 @@ describe('Notifications API V2', function () {
custom: true
};
it('deletes a notification', function (done) {
// create the notification that is to be deleted
request.post(localUtils.API.getApiQuery('notifications/'))
.set('Origin', config.get('url'))
@ -200,54 +102,4 @@ describe('Notifications API V2', function () {
});
});
});
it('returns 404 when removing notification with unknown id', function () {
return request.del(localUtils.API.getApiQuery('notifications/unknown'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.then(res => {
res.body.errors[0].message.should.equal('Notification does not exist.');
});
});
});
describe('As Editor', function () {
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
return testUtils.createUser({
user: testUtils.DataGenerator.forKnex.createUser({
email: 'test+1@ghost.org'
}),
role: testUtils.DataGenerator.Content.roles[2].name
});
})
.then((user) => {
request.user = user;
return localUtils.doAuth(request);
});
});
it('Add notification', function () {
const newNotification = {
type: 'info',
message: 'test notification',
custom: true,
id: 'customId'
};
return request.post(localUtils.API.getApiQuery('notifications/'))
.set('Origin', config.get('url'))
.send({notifications: [newNotification]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403);
});
});
});

View File

@ -1,8 +1,8 @@
const nock = require('nock');
const should = require('should');
const supertest = require('supertest');
const testUtils = require('../../../utils');
const config = require('../../../../server/config');
const testUtils = require('../../../utils/index');
const config = require('../../../../server/config/index');
const localUtils = require('./utils');
const ghost = testUtils.startGhost;
@ -21,7 +21,6 @@ describe('Oembed API', function () {
});
});
describe('success', function () {
it('can fetch an embed', function (done) {
let requestMock = nock('https://www.youtube.com')
.get('/oembed')
@ -58,4 +57,3 @@ describe('Oembed API', function () {
});
});
});
});

View File

@ -10,10 +10,8 @@ const models = require('../../../../server/models');
const ghost = testUtils.startGhost;
let request;
describe('Posts API V2', function () {
describe('Posts API', function () {
let ghostServer;
describe('As Owner', function () {
let ownerCookie;
before(function () {
@ -30,8 +28,7 @@ describe('Posts API V2', function () {
});
});
describe('Browse', function () {
it('retrieves all published posts only by default', function (done) {
it('Can retrieve all posts', function (done) {
request.get(localUtils.API.getApiQuery('posts/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -64,7 +61,7 @@ describe('Posts API V2', function () {
});
});
it('can retrieve multiple post formats', function (done) {
it('Can retrieve multiple post formats', function (done) {
request.get(localUtils.API.getApiQuery('posts/?formats=plaintext,mobiledoc&limit=3&order=title%20ASC'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -92,38 +89,7 @@ describe('Posts API V2', 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(11);
localUtils.API.checkResponse(
jsonResponse.posts[0],
'post',
null,
null,
['mobiledoc', 'id', 'title', 'html']
);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
done();
});
});
it('with includes', function (done) {
it('Can includes relations', function (done) {
request.get(localUtils.API.getApiQuery('posts/?include=tags,authors'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -156,37 +122,7 @@ describe('Posts API V2', function () {
});
});
it('fields combined with formats and include', function (done) {
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html&fields=id,title&include=authors'))
.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(11);
localUtils.API.checkResponse(
jsonResponse.posts[0],
'post',
null,
null,
['mobiledoc', 'id', 'title', 'html', 'authors']
);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
done();
});
});
it('can use a filter', function (done) {
it('Can filter posts', function (done) {
request.get(localUtils.API.getApiQuery('posts/?filter=page:[false,true]&status=all'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -208,7 +144,7 @@ describe('Posts API V2', function () {
});
});
it('supports usage of the page param', function (done) {
it('Can paginate posts', function (done) {
request.get(localUtils.API.getApiQuery('posts/?page=2'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -224,10 +160,8 @@ describe('Posts API V2', function () {
done();
});
});
});
describe('read', function () {
it('by id', function (done) {
it('Can request a post by id', function (done) {
request.get(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -254,31 +188,7 @@ describe('Posts API V2', function () {
});
});
it('by id, with formats', function (done) {
request
.get(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/?formats=plaintext,mobiledoc'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.posts);
jsonResponse.posts.should.have.length(1);
jsonResponse.posts[0].id.should.equal(testUtils.DataGenerator.Content.posts[0].id);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', ['mobiledoc', 'plaintext'], ['html']);
done();
});
});
it('can retrieve a post by slug', function (done) {
it('Can retrieve a post by slug', function (done) {
request.get(localUtils.API.getApiQuery('posts/slug/welcome/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -304,7 +214,7 @@ describe('Posts API V2', function () {
});
});
it('with includes', function (done) {
it('Can include relations for a single post', function (done) {
request
.get(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/?include=authors,tags'))
.set('Origin', config.get('url'))
@ -334,30 +244,7 @@ describe('Posts API V2', function () {
});
});
it('can\'t retrieve non existent post', function (done) {
request.get(localUtils.API.getApiQuery(`posts/${ObjectId.generate()}/`))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
});
describe('add', function () {
it('default', function () {
it('Can add a post', function () {
const post = {
title: 'My post',
status: 'draft',
@ -396,95 +283,7 @@ describe('Posts API V2', function () {
});
});
it('published post with response timestamps in UTC format respecting original UTC offset', function () {
const post = {
posts: [{
status: 'published',
published_at: '2016-05-31T07:00:00.000+06:00',
created_at: '2016-05-30T03:00:00.000Z',
updated_at: '2016-05-30T07:00:00.000'
}]
};
return request.post(localUtils.API.getApiQuery('posts'))
.set('Origin', config.get('url'))
.send(post)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.then((res) => {
res.body.posts.length.should.eql(1);
localUtils.API.checkResponse(res.body.posts[0], 'post');
res.body.posts[0].status.should.eql('published');
res.headers['x-cache-invalidate'].should.eql('/*');
res.body.posts[0].published_at.should.eql('2016-05-31T01:00:00.000Z');
res.body.posts[0].created_at.should.eql('2016-05-30T03:00:00.000Z');
res.body.posts[0].updated_at.should.eql('2016-05-30T07:00:00.000Z');
});
});
});
describe('edit', function () {
it('default', function () {
const post = {
title: 'My new Title',
author: testUtils.DataGenerator.Content.extraUsers[0].id,
custom_template: 'custom-about'
};
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) => {
res.headers['x-cache-invalidate'].should.eql('/*');
localUtils.API.checkResponse(res.body.posts[0], 'post');
res.body.posts[0].title.should.eql(post.title);
res.body.posts[0].status.should.eql('published');
res.body.posts[0].custom_template.should.eql('custom-about');
});
});
it('update dates', function () {
const post = {
created_by: ObjectId.generate(),
updated_by: ObjectId.generate(),
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) => {
res.headers['x-cache-invalidate'].should.eql('/*');
localUtils.API.checkResponse(res.body.posts[0], 'post');
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('update draft', function () {
it('Can update draft', function () {
const post = {
title: 'update draft'
};
@ -500,7 +299,7 @@ describe('Posts API V2', function () {
});
});
it('unpublish', function () {
it('Can unpublish a post', function () {
const post = {
status: 'draft'
};
@ -518,27 +317,7 @@ describe('Posts API V2', function () {
});
});
it('published_at = null', function () {
return request
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
.set('Origin', config.get('url'))
.send({
posts: [{published_at: null}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
res.headers['x-cache-invalidate'].should.eql('/*');
should.exist(res.body.posts);
should.exist(res.body.posts[0].published_at);
localUtils.API.checkResponse(res.body.posts[0], 'post');
});
});
});
describe('destroy', function () {
it('default', function () {
it('Can destroy a post', function () {
return request
.del(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
.set('Origin', config.get('url'))
@ -549,22 +328,4 @@ describe('Posts API V2', function () {
res.headers['x-cache-invalidate'].should.eql('/*');
});
});
it('non existent post', function () {
return request
.del(localUtils.API.getApiQuery('posts/' + ObjectId.generate() + '/'))
.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', 'errorType']);
});
});
});
});
});

View File

@ -19,8 +19,7 @@ describe('Roles API', function () {
});
});
describe('browse', function () {
it('default', function (done) {
it('Can request all roles', function (done) {
request.get(localUtils.API.getApiQuery('roles/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -48,7 +47,7 @@ describe('Roles API', function () {
});
});
it('permissions=assign', function (done) {
it('Can request roles which i am able to assign to other users', function (done) {
request.get(localUtils.API.getApiQuery('roles/?permissions=assign'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -77,4 +76,3 @@ describe('Roles API', function () {
});
});
});
});

View File

@ -9,7 +9,7 @@ const localUtils = require('./utils');
const ghost = testUtils.startGhost;
let request;
describe('Settings API V2', function () {
describe('Settings API', function () {
let ghostServer;
before(function () {
@ -27,7 +27,7 @@ describe('Settings API V2', function () {
return ghostServer.stop();
});
it('browse', function (done) {
it('Can request all settings', function (done) {
request.get(localUtils.API.getApiQuery('settings/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -59,7 +59,7 @@ describe('Settings API V2', function () {
});
});
it('read', function (done) {
it('Can read a setting', function (done) {
request.get(localUtils.API.getApiQuery('settings/title/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -83,52 +83,7 @@ describe('Settings API V2', function () {
});
});
it('read core setting', function () {
return request
.get(localUtils.API.getApiQuery('settings/db_hash/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403);
});
it('can\'t read permalinks', function (done) {
request.get(localUtils.API.getApiQuery('settings/permalinks/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.end(function (err, res) {
if (err) {
return done(err);
}
done();
});
});
it('can\'t read non existent setting', function (done) {
request.get(localUtils.API.getApiQuery('settings/testsetting/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
it('can edit settings', function (done) {
it('Can edit a setting', function (done) {
request.get(localUtils.API.getApiQuery('settings/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -170,64 +125,7 @@ describe('Settings API V2', function () {
});
});
it('can\'t edit permalinks', function (done) {
const settingToChange = {
settings: [{key: 'permalinks', value: '/:primary_author/:slug/'}]
};
request.put(localUtils.API.getApiQuery('settings/'))
.set('Origin', config.get('url'))
.send(settingToChange)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.end(function (err, res) {
if (err) {
return done(err);
}
done();
});
});
it('can\'t edit non existent setting', function (done) {
request.get(localUtils.API.getApiQuery('settings/'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.end(function (err, res) {
if (err) {
return done(err);
}
var jsonResponse = res.body,
newValue = 'new value';
should.exist(jsonResponse);
should.exist(jsonResponse.settings);
jsonResponse.settings = [{key: 'testvalue', value: newValue}];
request.put(localUtils.API.getApiQuery('settings/'))
.set('Origin', config.get('url'))
.send(jsonResponse)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.end(function (err, res) {
if (err) {
return done(err);
}
jsonResponse = res.body;
should.not.exist(res.headers['x-cache-invalidate']);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
});
it('can download routes.yaml', ()=> {
it('Can download routes.yaml', ()=> {
return request.get(localUtils.API.getApiQuery('settings/routes/yaml/'))
.set('Origin', config.get('url'))
.set('Accept', 'application/yaml')
@ -239,7 +137,7 @@ describe('Settings API V2', function () {
});
});
it('can upload routes.yaml', ()=> {
it('Can upload routes.yaml', ()=> {
const newRoutesYamlPath = `${os.tmpdir()}/routes.yaml`;
return fs.writeFile(newRoutesYamlPath, 'routes:\ncollections:\ntaxonomies:\n')

View File

@ -1,8 +1,8 @@
var should = require('should'),
supertest = require('supertest'),
testUtils = require('../../../utils'),
localUtils = require('./utils'),
config = require('../../../../server/config'),
testUtils = require('../../../../utils'),
localUtils = require('../../../../acceptance/old/admin/utils'),
config = require('../../../../../server/config'),
ghost = testUtils.startGhost,
request;
@ -20,7 +20,7 @@ describe('Slug API', function () {
});
});
it('should be able to get a post slug', function (done) {
it('Can generate a slug ', function (done) {
request.get(localUtils.API.getApiQuery('slugs/post/a post title/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -42,92 +42,4 @@ describe('Slug API', function () {
done();
});
});
it('should be able to get a tag slug', function (done) {
request.get(localUtils.API.getApiQuery('slugs/post/atag/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.slugs);
jsonResponse.slugs.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.slugs[0], 'slug');
jsonResponse.slugs[0].slug.should.equal('atag');
done();
});
});
it('should be able to get a user slug', function (done) {
request.get(localUtils.API.getApiQuery('slugs/user/user name/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.slugs);
jsonResponse.slugs.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.slugs[0], 'slug');
jsonResponse.slugs[0].slug.should.equal('user-name');
done();
});
});
it('should be able to get an app slug', function (done) {
request.get(localUtils.API.getApiQuery('slugs/app/cool app/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.slugs);
jsonResponse.slugs.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.slugs[0], 'slug');
jsonResponse.slugs[0].slug.should.equal('cool-app');
done();
});
});
it('should not be able to get a slug for an unknown type', function (done) {
request.get(localUtils.API.getApiQuery('slugs/unknown/who knows/'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(422)
.end(function (err, res) {
if (err) {
return done(err);
}
var jsonResponse = res.body;
should.exist(jsonResponse.errors);
done();
});
});
});

View File

@ -5,12 +5,12 @@ const localUtils = require('./utils');
const config = require('../../../../server/config');
const ghost = testUtils.startGhost;
describe('Tag API V2', function () {
describe('Tag API', function () {
let request;
before(function () {
return ghost()
.then(function (_ghostServer) {
.then(function () {
request = supertest.agent(config.get('url'));
})
.then(function () {
@ -18,7 +18,7 @@ describe('Tag API V2', function () {
});
});
it('browse', function () {
it('Can request all tags', function () {
return request
.get(localUtils.API.getApiQuery('tags/?include=count.posts&order=name%20DESC'))
.set('Origin', config.get('url'))
@ -49,7 +49,7 @@ describe('Tag API V2', function () {
});
});
it('browse accepts the page parameter', function () {
it('Can paginate tags', function () {
return request
.get(localUtils.API.getApiQuery('tags/?page=2'))
.set('Origin', config.get('url'))
@ -61,7 +61,7 @@ describe('Tag API V2', function () {
});
});
it('read', function () {
it('Can read a tag', function () {
return request
.get(localUtils.API.getApiQuery(`tags/${testUtils.existingData.tags[0].id}/?include=count.posts`))
.set('Origin', config.get('url'))
@ -81,7 +81,7 @@ describe('Tag API V2', function () {
});
});
it('add', function () {
it('Can add a tag', function () {
const tag = testUtils.DataGenerator.forKnex.createTag();
return request
@ -110,7 +110,7 @@ describe('Tag API V2', function () {
});
});
it('add internal', function () {
it('Can add an internal tag', function () {
const tag = testUtils.DataGenerator.forKnex.createTag({
name: '#test',
slug: null
@ -135,7 +135,7 @@ describe('Tag API V2', function () {
});
});
it('edit', function () {
it('Can edit a tag', function () {
return request
.put(localUtils.API.getApiQuery(`tags/${testUtils.existingData.tags[0].id}`))
.set('Origin', config.get('url'))
@ -156,7 +156,7 @@ describe('Tag API V2', function () {
});
});
it('destroy', function () {
it('Can destroy a tag', function () {
return request
.del(localUtils.API.getApiQuery(`tags/${testUtils.existingData.tags[0].id}`))
.set('Origin', config.get('url'))

View File

@ -8,7 +8,7 @@ const localUtils = require('./utils');
const config = require('../../../../server/config');
const ghost = testUtils.startGhost;
describe('v2 Themes API', function () {
describe('Themes API', function () {
let ghostServer;
let ownerRequest;
@ -35,7 +35,7 @@ describe('v2 Themes API', function () {
return localUtils.doAuth(ownerRequest);
});
it('browse', function () {
it('Can request all available themes', function () {
return ownerRequest
.get(localUtils.API.getApiQuery('themes/'))
.set('Origin', config.get('url'))
@ -73,7 +73,7 @@ describe('v2 Themes API', function () {
});
});
it('download', function () {
it('Can download a theme', function () {
return ownerRequest
.get(localUtils.API.getApiQuery('themes/casper/download/'))
.set('Origin', config.get('url'))
@ -82,7 +82,7 @@ describe('v2 Themes API', function () {
.expect(200);
});
it('upload valid theme', function () {
it('Can upload a valid theme', function () {
return uploadTheme({themePath: path.join(__dirname, '..', '..', '..', 'utils', 'fixtures', 'themes', 'valid.zip')})
.then((res) => {
const jsonResponse = res.body;
@ -159,7 +159,7 @@ describe('v2 Themes API', function () {
});
});
it('delete', function () {
it('Can delete a theme', function () {
return ownerRequest
.del(localUtils.API.getApiQuery('themes/valid'))
.set('Origin', config.get('url'))
@ -215,7 +215,7 @@ describe('v2 Themes API', function () {
});
});
it('upload with warnings', function () {
it('Can upload a theme, which has warnings', function () {
return uploadTheme({themePath: path.join(__dirname, '/../../../utils/fixtures/themes/warnings.zip')})
.then((res) => {
const jsonResponse = res.body;
@ -236,7 +236,7 @@ describe('v2 Themes API', function () {
});
});
it('activate', function () {
it('Can activate a theme', function () {
return ownerRequest
.get(localUtils.API.getApiQuery('themes/'))
.set('Origin', config.get('url'))

View File

@ -28,8 +28,7 @@ describe('Upload API', function () {
});
});
describe('success cases', function () {
it('valid png', function (done) {
it('Can upload a png', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -47,7 +46,7 @@ describe('Upload API', function () {
});
});
it('valid jpg', function (done) {
it('Can upload a jpg', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -65,7 +64,7 @@ describe('Upload API', function () {
});
});
it('valid gif', function (done) {
it('Can upload a gif', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -83,7 +82,7 @@ describe('Upload API', function () {
});
});
it('valid profile image', function (done) {
it('Can upload a square profile image', function (done) {
request.post(localUtils.API.getApiQuery('uploads/profile-image'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -101,67 +100,3 @@ describe('Upload API', function () {
});
});
});
describe('error cases', function () {
it('import should fail without file', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(403)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
it('import should fail with unsupported file', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/csv/single-column-with-header.csv'))
.expect(415)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
it('incorrect extension', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.set('content-type', 'image/png')
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/ghost-logo.pngx'))
.expect(415)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
it('import should fail if profile image is not square', function (done) {
request.post(localUtils.API.getApiQuery('uploads/profile-image'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/favicon_not_square.png'))
.expect(422)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
});

View File

@ -12,10 +12,9 @@ const models = require('../../../../server/models');
const ghost = testUtils.startGhost;
let request;
describe('User API V2', function () {
let editor, author, ghostServer, inactiveUser, admin;
describe('User API', function () {
let ghostServer, inactiveUser, admin;
describe('As Owner', function () {
before(function () {
return ghost()
.then(function (_ghostServer) {
@ -46,8 +45,7 @@ describe('User API V2', function () {
});
});
describe('Browse', function () {
it('returns dates in ISO 8601 format', function (done) {
it('Can request all users ordered by id', function (done) {
// @NOTE: ASC is default
request.get(localUtils.API.getApiQuery('users/?order=id%20DESC'))
.set('Origin', config.get('url'))
@ -93,7 +91,7 @@ describe('User API V2', function () {
});
});
it('can retrieve all users with includes', function (done) {
it('Can include user roles', function (done) {
request.get(localUtils.API.getApiQuery('users/?include=roles'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -115,7 +113,7 @@ describe('User API V2', function () {
});
});
it('supports usage of the page param', function (done) {
it('Can paginate users', function (done) {
request.get(localUtils.API.getApiQuery('users/?page=2'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -131,99 +129,9 @@ describe('User API V2', function () {
done();
});
});
});
describe('Read', function () {
it('can retrieve a user by "me"', function (done) {
request.get(localUtils.API.getApiQuery('users/me/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.users);
should.not.exist(jsonResponse.meta);
jsonResponse.users.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['url']);
done();
});
});
it('can retrieve a user by id', function (done) {
request.get(localUtils.API.getApiQuery('users/' + testUtils.existingData.users[0].id + '/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.users);
should.not.exist(jsonResponse.meta);
jsonResponse.users.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['url']);
done();
});
});
it('can retrieve a user by slug', function (done) {
request.get(localUtils.API.getApiQuery('users/slug/joe-bloggs/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.users);
should.not.exist(jsonResponse.meta);
jsonResponse.users.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['url']);
done();
});
});
it('can retrieve a user by email', function (done) {
request.get(localUtils.API.getApiQuery('users/email/jbloggs%40example.com/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse.users);
should.not.exist(jsonResponse.meta);
jsonResponse.users.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['url']);
done();
});
});
it('can retrieve a user with includes', function (done) {
request.get(localUtils.API.getApiQuery('users/me/?include=roles,roles.permissions,count.posts'))
it('Can retrieve a user by id', function (done) {
request.get(localUtils.API.getApiQuery('users/' + testUtils.existingData.users[0].id + '/?include=roles,roles.permissions,count.posts'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
@ -245,13 +153,12 @@ describe('User API V2', function () {
});
});
it('can\'t retrieve non existent user by id', function (done) {
request.get(localUtils.API.getApiQuery('users/' + ObjectId.generate() + '/'))
it('Can retrieve a user by slug', function (done) {
request.get(localUtils.API.getApiQuery('users/slug/joe-bloggs/'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
@ -259,20 +166,21 @@ describe('User API V2', function () {
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']);
should.exist(jsonResponse.users);
should.not.exist(jsonResponse.meta);
jsonResponse.users.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['url']);
done();
});
});
it('can\'t retrieve non existent user by slug', function (done) {
request.get(localUtils.API.getApiQuery('users/slug/blargh/'))
it('Can retrieve a user by email', function (done) {
request.get(localUtils.API.getApiQuery('users/email/jbloggs%40example.com/'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
@ -280,15 +188,15 @@ describe('User API V2', function () {
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']);
should.exist(jsonResponse.users);
should.not.exist(jsonResponse.meta);
jsonResponse.users.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['url']);
done();
});
});
});
describe('Edit', function () {
it('can edit a user', function (done) {
request.put(localUtils.API.getApiQuery('users/me/'))
.set('Origin', config.get('url'))
@ -329,10 +237,8 @@ describe('User API V2', function () {
});
});
});
});
describe('Destroy', function () {
it('[success] Destroy active user', function () {
it('Can destroy an active user', function () {
const userId = testUtils.existingData.users[1].id;
return request
@ -379,22 +285,7 @@ describe('User API V2', function () {
});
});
it('[failure] Destroy unknown user id', function (done) {
request.delete(localUtils.API.getApiQuery('users/' + ObjectId.generate()))
.set('Origin', config.get('url'))
.expect(404)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
describe('Transfer ownership', function () {
it('Owner can transfer ownership to admin user', function () {
it('Can transfer ownership to admin user', function () {
return request
.put(localUtils.API.getApiQuery('users/owner'))
.set('Origin', config.get('url'))
@ -411,10 +302,8 @@ describe('User API V2', function () {
res.body.users[1].roles[0].name.should.equal(testUtils.DataGenerator.Content.roles[3].name);
});
});
});
describe('Change Password', function () {
it('default', function () {
it('Can change password', function () {
return request
.put(localUtils.API.getApiQuery('users/password'))
.set('Origin', config.get('url'))
@ -435,151 +324,3 @@ describe('User API V2', function () {
});
});
});
});
describe('As Editor', function () {
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
// create editor
return testUtils.createUser({
user: testUtils.DataGenerator.forKnex.createUser({email: 'test+1@ghost.org'}),
role: testUtils.DataGenerator.Content.roles[1].name
});
})
.then(function (_user1) {
editor = _user1;
request.user = editor;
// by default we login with the owner
return localUtils.doAuth(request);
});
});
describe('success cases', function () {
it('can edit himself', function (done) {
request.put(localUtils.API.getApiQuery('users/' + editor.id + '/'))
.set('Origin', config.get('url'))
.send({
users: [{id: editor.id, name: 'test'}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
describe('error cases', function () {
it('can\'t edit the owner', function (done) {
request.put(localUtils.API.getApiQuery('users/' + testUtils.DataGenerator.Content.users[0].id + '/'))
.set('Origin', config.get('url'))
.send({
users: [{
id: testUtils.DataGenerator.Content.users[0].id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
it('Cannot transfer ownership to any other user', function () {
return request
.put(localUtils.API.getApiQuery('users/owner'))
.set('Origin', config.get('url'))
.send({
owner: [{
id: testUtils.existingData.users[1].id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403);
});
});
});
describe('As Author', function () {
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
// create author
return testUtils.createUser({
user: testUtils.DataGenerator.forKnex.createUser({email: 'test+2@ghost.org'}),
role: testUtils.DataGenerator.Content.roles[2].name
});
})
.then(function (_user2) {
author = _user2;
request.user = author;
// by default we login with the owner
return localUtils.doAuth(request);
});
});
describe('success cases', function () {
it('can edit himself', function (done) {
request.put(localUtils.API.getApiQuery('users/' + author.id + '/'))
.set('Origin', config.get('url'))
.send({
users: [{id: author.id, name: 'test'}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
describe('error cases', function () {
it('can\'t edit the owner', function (done) {
request.put(localUtils.API.getApiQuery('users/' + testUtils.DataGenerator.Content.users[0].id + '/'))
.set('Origin', config.get('url'))
.send({
users: [{
id: testUtils.DataGenerator.Content.users[0].id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
});
});

View File

@ -9,9 +9,6 @@ let request;
describe('Webhooks API', function () {
var ghostServer;
describe('As Owner', function () {
var ownerAccessToken = '';
before(function () {
return ghost()
.then(function (_ghostServer) {
@ -23,38 +20,7 @@ describe('Webhooks API', function () {
});
});
describe('Add', function () {
var newWebhook = {
event: 'test.create',
target_url: 'http://example.com/webhooks/test/1'
};
it('creates a new webhook', function (done) {
request.post(localUtils.API.getApiQuery('webhooks/'))
.set('Origin', config.get('url'))
.send({webhooks: [newWebhook]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
var jsonResponse = res.body;
should.exist(jsonResponse.webhooks);
localUtils.API.checkResponse(jsonResponse.webhooks[0], 'webhook');
jsonResponse.webhooks[0].event.should.equal(newWebhook.event);
jsonResponse.webhooks[0].target_url.should.equal(newWebhook.target_url);
done();
});
});
it('creates a new webhook with name, secret and api version', function (done) {
it('Can creates a webhook', function (done) {
let webhookData = {
event: 'test.create',
target_url: 'http://example.com/webhooks/test/extra/1',
@ -62,6 +28,7 @@ describe('Webhooks API', function () {
secret: 'thisissecret',
api_version: 'v2'
};
request.post(localUtils.API.getApiQuery('webhooks/'))
.set('Origin', config.get('url'))
.send({webhooks: [webhookData]})
@ -88,10 +55,8 @@ describe('Webhooks API', function () {
done();
});
});
});
describe('Edit', function () {
it('can succesfully edit a webhook', function (done) {
it('Can edit a webhook', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
@ -150,16 +115,14 @@ describe('Webhooks API', function () {
});
});
});
});
describe('Delete', function () {
it('Can delete a webhook', function (done) {
var newWebhook = {
event: 'test.create',
// a different target_url from above is needed to avoid an "already exists" error
target_url: 'http://example.com/webhooks/test/2'
};
it('deletes a webhook', function (done) {
// create the webhook that is to be deleted
request.post(localUtils.API.getApiQuery('webhooks/'))
.set('Origin', config.get('url'))
@ -196,5 +159,3 @@ describe('Webhooks API', function () {
});
});
});
});
});

View File

@ -0,0 +1,125 @@
const path = require('path');
const _ = require('lodash');
const fs = require('fs-extra');
const should = require('should');
const supertest = require('supertest');
const sinon = require('sinon');
const config = require('../../../../../server/config');
const models = require('../../../../../server/models');
const common = require('../../../../../server/lib/common');
const testUtils = require('../../../../utils');
const localUtils = require('./utils');
let ghost = testUtils.startGhost;
let request;
let eventsTriggered;
describe('DB API', () => {
let backupClient;
let schedulerClient;
before(() => {
return ghost()
.then(() => {
request = supertest.agent(config.get('url'));
})
.then(() => {
return localUtils.doAuth(request);
})
.then(() => {
return models.Client.findAll();
})
.then((result) => {
const clients = result.toJSON();
backupClient = _.find(clients, {slug: 'ghost-backup'});
schedulerClient = _.find(clients, {slug: 'ghost-scheduler'});
});
});
beforeEach(() => {
eventsTriggered = {};
sinon.stub(common.events, 'emit').callsFake((eventName, eventObj) => {
if (!eventsTriggered[eventName]) {
eventsTriggered[eventName] = [];
}
eventsTriggered[eventName].push(eventObj);
});
});
afterEach(() => {
sinon.restore();
});
it('can export the database with more tables', () => {
return request.get(localUtils.API.getApiQuery('db/?include=clients,client_trusted_domains'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect(200)
.then((res) => {
const jsonResponse = res.body;
should.exist(jsonResponse.db);
jsonResponse.db.should.have.length(1);
Object.keys(jsonResponse.db[0].data).length.should.eql(27);
});
});
it('import should fail without file', () => {
return request.post(localUtils.API.getApiQuery('db/'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(403);
});
it('import should fail with unsupported file', () => {
return request.post(localUtils.API.getApiQuery('db/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('importfile', path.join(__dirname, '/../../../../utils/fixtures/csv/single-column-with-header.csv'))
.expect(415);
});
it('export can be triggered by backup client', () => {
const backupQuery = `?client_id=${backupClient.slug}&client_secret=${backupClient.secret}&filename=test`;
const fsStub = sinon.stub(fs, 'writeFile').resolves();
return request.post(localUtils.API.getApiQuery(`db/backup${backupQuery}`))
.expect('Content-Type', /json/)
.expect(200)
.then((res) => {
(typeof res.body).should.be.Object();
res.body.db[0].filename.should.match(/test\.json/);
fsStub.calledOnce.should.eql(true);
});
});
it('export can not be triggered by client other than backup', () => {
const schedulerQuery = `?client_id=${schedulerClient.slug}&client_secret=${schedulerClient.secret}`;
const fsStub = sinon.stub(fs, 'writeFile').resolves();
return request.post(localUtils.API.getApiQuery(`db/backup${schedulerQuery}`))
.expect('Content-Type', /json/)
.expect(403)
.then(res => {
should.exist(res.body.errors);
res.body.errors[0].errorType.should.eql('NoPermissionError');
fsStub.called.should.eql(false);
});
});
it('export can not be triggered by regular authentication', () => {
const fsStub = sinon.stub(fs, 'writeFile').resolves();
return request.post(localUtils.API.getApiQuery(`db/backup`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect(401)
.then(res => {
should.exist(res.body.errors);
res.body.errors[0].errorType.should.eql('UnauthorizedError');
fsStub.called.should.eql(false);
});
});
});

View File

@ -0,0 +1,60 @@
const should = require('should');
const supertest = require('supertest');
const testUtils = require('../../../../utils');
const config = require('../../../../../server/config');
const localUtils = require('./utils');
const ghost = testUtils.startGhost;
let request;
describe('Notifications API', function () {
let ghostServer;
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
return localUtils.doAuth(request);
});
});
describe('As Editor', function () {
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
return testUtils.createUser({
user: testUtils.DataGenerator.forKnex.createUser({
email: 'test+1@ghost.org'
}),
role: testUtils.DataGenerator.Content.roles[2].name
});
})
.then((user) => {
request.user = user;
return localUtils.doAuth(request);
});
});
it('Add notification', function () {
const newNotification = {
type: 'info',
message: 'test notification',
custom: true,
id: 'customId'
};
return request.post(localUtils.API.getApiQuery('notifications/'))
.set('Origin', config.get('url'))
.send({notifications: [newNotification]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403);
});
});
});

View File

@ -0,0 +1,257 @@
const should = require('should');
const supertest = require('supertest');
const _ = require('lodash');
const ObjectId = require('bson-objectid');
const moment = require('moment-timezone');
const testUtils = require('../../../../utils');
const config = require('../../../../../server/config');
const models = require('../../../../../server/models');
const localUtils = require('./utils');
const ghost = testUtils.startGhost;
let request;
describe('Posts API', function () {
let ghostServer;
let ownerCookie;
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
return localUtils.doAuth(request, 'users:extra', 'posts');
})
.then(function (cookie) {
ownerCookie = cookie;
});
});
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(11);
localUtils.API.checkResponse(
jsonResponse.posts[0],
'post',
null,
null,
['mobiledoc', 'id', 'title', 'html']
);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
done();
});
});
it('fields combined with formats and include', function (done) {
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html&fields=id,title&include=authors'))
.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(11);
localUtils.API.checkResponse(
jsonResponse.posts[0],
'post',
null,
null,
['mobiledoc', 'id', 'title', 'html', 'authors']
);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
done();
});
});
it('can use a filter', function (done) {
request.get(localUtils.API.getApiQuery('posts/?filter=page:[false,true]&status=all'))
.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(15);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
done();
});
});
it('supports usage of the page param', function (done) {
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)
.end(function (err, res) {
if (err) {
return done(err);
}
const jsonResponse = res.body;
should.equal(jsonResponse.meta.pagination.page, 2);
done();
});
});
});
describe('read', function () {
it('can\'t retrieve non existent post', function (done) {
request.get(localUtils.API.getApiQuery(`posts/${ObjectId.generate()}/`))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
});
describe('add', function () {
it('published post with response timestamps in UTC format respecting original UTC offset', function () {
const post = {
posts: [{
status: 'published',
published_at: '2016-05-31T07:00:00.000+06:00',
created_at: '2016-05-30T03:00:00.000Z',
updated_at: '2016-05-30T07:00:00.000'
}]
};
return request.post(localUtils.API.getApiQuery('posts'))
.set('Origin', config.get('url'))
.send(post)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.then((res) => {
res.body.posts.length.should.eql(1);
localUtils.API.checkResponse(res.body.posts[0], 'post');
res.body.posts[0].status.should.eql('published');
res.headers['x-cache-invalidate'].should.eql('/*');
res.body.posts[0].published_at.should.eql('2016-05-31T01:00:00.000Z');
res.body.posts[0].created_at.should.eql('2016-05-30T03:00:00.000Z');
res.body.posts[0].updated_at.should.eql('2016-05-30T07:00:00.000Z');
});
});
});
describe('edit', function () {
it('published_at = null', function () {
return request
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
.set('Origin', config.get('url'))
.send({
posts: [{published_at: null}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
res.headers['x-cache-invalidate'].should.eql('/*');
should.exist(res.body.posts);
should.exist(res.body.posts[0].published_at);
localUtils.API.checkResponse(res.body.posts[0], 'post');
});
});
it('update dates', function () {
const post = {
created_by: ObjectId.generate(),
updated_by: ObjectId.generate(),
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) => {
res.headers['x-cache-invalidate'].should.eql('/*');
localUtils.API.checkResponse(res.body.posts[0], 'post');
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);
});
});
});
describe('destroy', function () {
it('non existent post', function () {
return request
.del(localUtils.API.getApiQuery('posts/' + ObjectId.generate() + '/'))
.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', 'errorType']);
});
});
});
});

View File

@ -3,10 +3,10 @@ const supertest = require('supertest');
const fs = require('fs-extra');
const Promise = require('bluebird');
const path = require('path');
const testUtils = require('../../../utils');
const localUtils = require('./utils');
const configUtils = require('../../../utils/configUtils');
const config = require('../../../../server/config');
const testUtils = require('../../../../utils');
const localUtils = require('../../../../acceptance/old/admin/utils');
const configUtils = require('../../../../utils/configUtils');
const config = require('../../../../../server/config');
const ghost = testUtils.startGhost;
let request;

View File

@ -0,0 +1,131 @@
const should = require('should');
const _ = require('lodash');
const supertest = require('supertest');
const os = require('os');
const fs = require('fs-extra');
const config = require('../../../../../server/config');
const testUtils = require('../../../../utils');
const localUtils = require('./utils');
const ghost = testUtils.startGhost;
let request;
describe('Settings API', function () {
let ghostServer;
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
return localUtils.doAuth(request);
});
});
after(function () {
return ghostServer.stop();
});
it('read core setting', function () {
return request
.get(localUtils.API.getApiQuery('settings/db_hash/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403);
});
it('can\'t read permalinks', function (done) {
request.get(localUtils.API.getApiQuery('settings/permalinks/'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.end(function (err, res) {
if (err) {
return done(err);
}
done();
});
});
it('can\'t read non existent setting', function (done) {
request.get(localUtils.API.getApiQuery('settings/testsetting/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
it('can\'t edit permalinks', function (done) {
const settingToChange = {
settings: [{key: 'permalinks', value: '/:primary_author/:slug/'}]
};
request.put(localUtils.API.getApiQuery('settings/'))
.set('Origin', config.get('url'))
.send(settingToChange)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.end(function (err, res) {
if (err) {
return done(err);
}
done();
});
});
it('can\'t edit non existent setting', function (done) {
request.get(localUtils.API.getApiQuery('settings/'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.end(function (err, res) {
if (err) {
return done(err);
}
var jsonResponse = res.body,
newValue = 'new value';
should.exist(jsonResponse);
should.exist(jsonResponse.settings);
jsonResponse.settings = [{key: 'testvalue', value: newValue}];
request.put(localUtils.API.getApiQuery('settings/'))
.set('Origin', config.get('url'))
.send(jsonResponse)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(404)
.end(function (err, res) {
if (err) {
return done(err);
}
jsonResponse = res.body;
should.not.exist(res.headers['x-cache-invalidate']);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
});
});

View File

@ -1,10 +1,10 @@
const should = require('should');
const supertest = require('supertest');
const sinon = require('sinon');
const testUtils = require('../../../utils');
const localUtils = require('./utils');
const config = require('../../../../server/config');
const common = require('../../../../server/lib/common');
const testUtils = require('../../../../utils');
const localUtils = require('../../../../acceptance/old/admin/utils');
const config = require('../../../../../server/config');
const common = require('../../../../../server/lib/common');
const ghost = testUtils.startGhost;
let request;

View File

@ -2,10 +2,10 @@ const path = require('path');
const should = require('should');
const supertest = require('supertest');
const sinon = require('sinon');
const testUtils = require('../../../utils');
const localUtils = require('./utils');
const config = require('../../../../server/config');
const labs = require('../../../../server/services/labs');
const testUtils = require('../../../../utils');
const localUtils = require('../../../../acceptance/old/admin/utils');
const config = require('../../../../../server/config');
const labs = require('../../../../../server/services/labs');
const ghost = testUtils.startGhost;
@ -208,7 +208,7 @@ describe('Subscribers API', function () {
it('importCSV', function () {
return request
.post(localUtils.API.getApiQuery(`subscribers/csv/`))
.attach('subscribersfile', path.join(__dirname, '/../../../utils/fixtures/csv/single-column-with-header.csv'))
.attach('subscribersfile', path.join(__dirname, '/../../../../utils/fixtures/csv/single-column-with-header.csv'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)

View File

@ -0,0 +1,91 @@
const path = require('path');
const fs = require('fs-extra');
const should = require('should');
const supertest = require('supertest');
const localUtils = require('./utils');
const testUtils = require('../../../../utils');
const config = require('../../../../../server/config');
const ghost = testUtils.startGhost;
describe('Upload API', function () {
const images = [];
let request;
before(function () {
return ghost()
.then(function () {
request = supertest.agent(config.get('url'));
})
.then(function () {
return localUtils.doAuth(request);
});
});
after(function () {
images.forEach(function (image) {
fs.removeSync(config.get('paths').appRoot + image);
});
});
it('import should fail without file', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(403)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
it('import should fail with unsupported file', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../../utils/fixtures/csv/single-column-with-header.csv'))
.expect(415)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
it('incorrect extension', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.set('content-type', 'image/png')
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../../utils/fixtures/images/ghost-logo.pngx'))
.expect(415)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
it('import should fail if profile image is not square', function (done) {
request.post(localUtils.API.getApiQuery('uploads/profile-image'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../../utils/fixtures/images/favicon_not_square.png'))
.expect(422)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});

View File

@ -0,0 +1,250 @@
const should = require('should');
const _ = require('lodash');
const supertest = require('supertest');
const ObjectId = require('bson-objectid');
const testUtils = require('../../../../utils');
const config = require('../../../../../server/config');
const localUtils = require('./utils');
const ghost = testUtils.startGhost;
let request;
describe('User API', function () {
let editor, author, ghostServer, inactiveUser, admin;
describe('As Owner', function () {
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
// create inactive user
return testUtils.createUser({
user: testUtils.DataGenerator.forKnex.createUser({email: 'test+3@ghost.org', status: 'inactive'}),
role: testUtils.DataGenerator.Content.roles[2].name
});
})
.then(function (_user) {
inactiveUser = _user;
// create admin user
return testUtils.createUser({
user: testUtils.DataGenerator.forKnex.createUser({email: 'test+admin@ghost.org', slug: 'admin'}),
role: testUtils.DataGenerator.Content.roles[0].name
});
})
.then(function (_user) {
admin = _user;
// by default we login with the owner
return localUtils.doAuth(request);
});
});
describe('Read', function () {
it('can\'t retrieve non existent user by id', function (done) {
request.get(localUtils.API.getApiQuery('users/' + ObjectId.generate() + '/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
it('can\'t retrieve non existent user by slug', function (done) {
request.get(localUtils.API.getApiQuery('users/slug/blargh/'))
.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']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.errors);
testUtils.API.checkResponseValue(jsonResponse.errors[0], ['message', 'errorType']);
done();
});
});
});
describe('Destroy', function () {
it('[failure] Destroy unknown user id', function (done) {
request.delete(localUtils.API.getApiQuery('users/' + ObjectId.generate()))
.set('Origin', config.get('url'))
.expect(404)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
});
describe('As Editor', function () {
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
// create editor
return testUtils.createUser({
user: testUtils.DataGenerator.forKnex.createUser({email: 'test+1@ghost.org'}),
role: testUtils.DataGenerator.Content.roles[1].name
});
})
.then(function (_user1) {
editor = _user1;
request.user = editor;
// by default we login with the owner
return localUtils.doAuth(request);
});
});
describe('success cases', function () {
it('can edit himself', function (done) {
request.put(localUtils.API.getApiQuery('users/' + editor.id + '/'))
.set('Origin', config.get('url'))
.send({
users: [{id: editor.id, name: 'test'}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
describe('error cases', function () {
it('can\'t edit the owner', function (done) {
request.put(localUtils.API.getApiQuery('users/' + testUtils.DataGenerator.Content.users[0].id + '/'))
.set('Origin', config.get('url'))
.send({
users: [{
id: testUtils.DataGenerator.Content.users[0].id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
it('Cannot transfer ownership to any other user', function () {
return request
.put(localUtils.API.getApiQuery('users/owner'))
.set('Origin', config.get('url'))
.send({
owner: [{
id: testUtils.existingData.users[1].id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403);
});
});
});
describe('As Author', function () {
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
// create author
return testUtils.createUser({
user: testUtils.DataGenerator.forKnex.createUser({email: 'test+2@ghost.org'}),
role: testUtils.DataGenerator.Content.roles[2].name
});
})
.then(function (_user2) {
author = _user2;
request.user = author;
// by default we login with the owner
return localUtils.doAuth(request);
});
});
describe('success cases', function () {
it('can edit himself', function (done) {
request.put(localUtils.API.getApiQuery('users/' + author.id + '/'))
.set('Origin', config.get('url'))
.send({
users: [{id: author.id, name: 'test'}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
describe('error cases', function () {
it('can\'t edit the owner', function (done) {
request.put(localUtils.API.getApiQuery('users/' + testUtils.DataGenerator.Content.users[0].id + '/'))
.set('Origin', config.get('url'))
.send({
users: [{
id: testUtils.DataGenerator.Content.users[0].id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(403)
.end(function (err) {
if (err) {
return done(err);
}
done();
});
});
});
});
});

View File

@ -0,0 +1,120 @@
const url = require('url');
const _ = require('lodash');
const testUtils = require('../../../../utils');
const schema = require('../../../../../server/data/schema').tables;
const API_URL = '/ghost/api/v2/admin/';
const expectedProperties = {
// API top level
posts: ['posts', 'meta'],
tags: ['tags', 'meta'],
users: ['users', 'meta'],
settings: ['settings', 'meta'],
subscribers: ['subscribers', 'meta'],
roles: ['roles'],
pagination: ['page', 'limit', 'pages', 'total', 'next', 'prev'],
slugs: ['slugs'],
slug: ['slug'],
invites: ['invites', 'meta'],
themes: ['themes'],
post: _(schema.posts)
.keys()
// by default we only return html
.without('mobiledoc', 'plaintext')
// always returns computed properties: url, comment_id, primary_tag, primary_author
.without('author_id').concat('url', 'primary_tag', 'primary_author')
,
user: _(schema.users)
.keys()
.without('password')
.without('ghost_auth_access_token')
,
tag: _(schema.tags)
.keys()
// Tag API swaps parent_id to parent
.without('parent_id').concat('parent')
,
setting: _(schema.settings)
.keys()
,
subscriber: _(schema.subscribers)
.keys()
,
accesstoken: _(schema.accesstokens)
.keys()
,
role: _(schema.roles)
.keys()
,
permission: _(schema.permissions)
.keys()
,
notification: ['type', 'message', 'status', 'id', 'dismissible', 'location', 'custom'],
theme: ['name', 'package', 'active'],
invite: _(schema.invites)
.keys()
.without('token')
,
webhook: _(schema.webhooks)
.keys()
.without(
'name',
'last_triggered_at',
'last_triggered_error',
'last_triggered_status',
'secret',
'integration_id'
)
};
_.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);
}
},
doAuth(...args) {
return testUtils.API.doAuth(`${API_URL}session/`, ...args);
},
getValidAdminToken(endpoint) {
const jwt = require('jsonwebtoken');
const JWT_OPTIONS = {
algorithm: 'HS256',
expiresIn: '5m',
audience: endpoint
};
return jwt.sign(
{
kid: testUtils.DataGenerator.Content.api_keys[0].id
},
Buffer.from(testUtils.DataGenerator.Content.api_keys[0].secret, 'hex'),
JWT_OPTIONS
);
}
};