2
1
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2023-12-13 21:00:40 +01:00

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,62 +18,60 @@ 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'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
it('can retrieve public configuration and all expected properties', function (done) {
request.get(localUtils.API.getApiQuery('configuration/'))
.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.exist(res.body.configuration);
should.exist(res.body.configuration);
res.body.configuration.should.be.an.Array().with.lengthOf(1);
const props = res.body.configuration[0];
res.body.configuration.should.be.an.Array().with.lengthOf(1);
const props = res.body.configuration[0];
props.blogUrl.should.eql('http://127.0.0.1:2369/');
props.blogUrl.should.eql('http://127.0.0.1:2369/');
props.useGravatar.should.eql(false);
props.clientId.should.eql('ghost-admin');
props.clientSecret.should.eql('not_available');
props.useGravatar.should.eql(false);
props.clientId.should.eql('ghost-admin');
props.clientSecret.should.eql('not_available');
// value not available, because settings API was not called yet
props.hasOwnProperty('blogTitle').should.eql(true);
done();
});
});
// value not available, because settings API was not called yet
props.hasOwnProperty('blogTitle').should.eql(true);
done();
});
});
it('can read about config and get all expected properties', function (done) {
request.get(localUtils.API.getApiQuery('configuration/about/'))
.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);
}
it('can read about config and get all expected properties', function (done) {
request.get(localUtils.API.getApiQuery('configuration/about/'))
.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.exist(res.body.configuration);
should.exist(res.body.configuration);
res.body.configuration.should.be.an.Array().with.lengthOf(1);
const props = res.body.configuration[0];
res.body.configuration.should.be.an.Array().with.lengthOf(1);
const props = res.body.configuration[0];
// Check the structure
props.should.have.property('version').which.is.a.String();
props.should.have.property('environment').which.is.a.String();
props.should.have.property('database').which.is.a.String();
props.should.have.property('mail').which.is.a.String();
// Check the structure
props.should.have.property('version').which.is.a.String();
props.should.have.property('environment').which.is.a.String();
props.should.have.property('database').which.is.a.String();
props.should.have.property('mail').which.is.a.String();
// Check a few values
props.environment.should.match(/^testing/);
props.version.should.eql(require('../../../../../package.json').version);
done();
});
});
// Check a few values
props.environment.should.match(/^testing/);
props.version.should.eql(require('../../../../../package.json').version);
done();
});
});
});

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,375 +21,330 @@ 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'))
.send({
integrations: [{
name: 'Dis-Integrate!!'
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'))
.send({
integrations: [{
name: 'Dis-Integrate!!'
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
should.equal(body.integrations.length, 1);
const [integration] = body.integrations;
should.equal(integration.name, 'Dis-Integrate!!');
should.equal(integration.api_keys.length, 2);
const contentApiKey = integration.api_keys.find(findBy('type', 'content'));
should.equal(contentApiKey.integration_id, integration.id);
const adminApiKey = integration.api_keys.find(findBy('type', 'admin'));
should.equal(adminApiKey.integration_id, integration.id);
should.exist(adminApiKey.secret);
// check Admin API key secret format
const [id, secret] = adminApiKey.secret.split(':');
should.exist(id);
should.equal(id, adminApiKey.id);
should.exist(secret);
secret.length.should.equal(64);
done();
});
});
it('Can successfully create a single integration with a webhook', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Integratatron4000',
webhooks: [{
event: 'something',
target_url: 'http://example.com',
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
should.equal(body.integrations.length, 1);
should.equal(body.integrations.length, 1);
const [integration] = body.integrations;
should.equal(integration.name, 'Dis-Integrate!!');
const [integration] = body.integrations;
should.equal(integration.name, 'Integratatron4000');
should.equal(integration.api_keys.length, 2);
should.equal(integration.webhooks.length, 1);
const contentApiKey = integration.api_keys.find(findBy('type', 'content'));
should.equal(contentApiKey.integration_id, integration.id);
const webhook = integration.webhooks[0];
should.equal(webhook.integration_id, integration.id);
const adminApiKey = integration.api_keys.find(findBy('type', 'admin'));
should.equal(adminApiKey.integration_id, integration.id);
should.exist(adminApiKey.secret);
done();
});
});
// check Admin API key secret format
const [id, secret] = adminApiKey.secret.split(':');
should.exist(id);
should.equal(id, adminApiKey.id);
should.exist(secret);
secret.length.should.equal(64);
it('Can successfully get a created integration', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Interrogation Integration'
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
done();
});
});
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
it('Can successfully create a single integration with a webhook', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Integratatron4000',
webhooks: [{
event: 'something',
target_url: 'http://example.com',
should.equal(body.integrations.length, 1);
const [integration] = body.integrations;
should.equal(integration.id, createdIntegration.id);
should.equal(integration.name, createdIntegration.name);
should.equal(integration.slug, createdIntegration.slug);
should.equal(integration.description, createdIntegration.description);
should.equal(integration.icon_image, createdIntegration.icon_image);
done();
});
});
});
it('Can successfully get *all* created integrations with api_keys', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Integrate with this!'
}]
})
.expect(201)
.end(function (err) {
if (err) {
return done(err);
}
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Winter-(is)-great'
}]
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
})
.expect(201)
.end(function (err) {
if (err) {
return done(err);
}
should.equal(body.integrations.length, 1);
request.get(localUtils.API.getApiQuery(`integrations/?include=api_keys&limit=all`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [integration] = body.integrations;
should.equal(integration.name, 'Integratatron4000');
// This is the only page
should.equal(body.meta.pagination.page, 1);
should.equal(body.meta.pagination.pages, 1);
should.equal(body.meta.pagination.next, null);
should.equal(body.meta.pagination.prev, null);
should.equal(integration.webhooks.length, 1);
body.integrations.forEach(integration => {
should.exist(integration.api_keys);
});
const webhook = integration.webhooks[0];
should.equal(webhook.integration_id, integration.id);
done();
});
});
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'))
.send({
integrations: [{
name: 'Interrogation Integration'
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
it('Can successfully edit a created integration', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Rubbish Integration Name'
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
request.put(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Awesome Integration Name',
description: 'Finally got round to writing this...'
}]
})
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
should.equal(body.integrations.length, 1);
const [updatedIntegration] = body.integrations;
const [integration] = body.integrations;
should.equal(integration.id, createdIntegration.id);
should.equal(integration.name, createdIntegration.name);
should.equal(integration.slug, createdIntegration.slug);
should.equal(integration.description, createdIntegration.description);
should.equal(integration.icon_image, createdIntegration.icon_image);
done();
});
});
});
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);
});
should.equal(updatedIntegration.id, createdIntegration.id);
should.equal(updatedIntegration.name, 'Awesome Integration Name');
should.equal(updatedIntegration.description, 'Finally got round to writing this...');
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'))
.send({
integrations: [{
name: 'Integrate with this!'
}]
})
.expect(201)
.end(function (err) {
if (err) {
return done(err);
}
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Winter-(is)-great'
it('Can successfully add and delete a created integrations webhooks', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Webhook-less Integration',
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
request.put(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.send({
integrations: [{
webhooks: [{
event: 'somestuff',
target_url: 'http://example.com'
}]
})
.expect(201)
.end(function (err) {
if (err) {
return done(err);
}
}]
})
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
request.get(localUtils.API.getApiQuery(`integrations/?include=api_keys&limit=all`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/?include=webhooks`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
// This is the only page
should.equal(body.meta.pagination.page, 1);
should.equal(body.meta.pagination.pages, 1);
should.equal(body.meta.pagination.next, null);
should.equal(body.meta.pagination.prev, null);
const [updatedIntegration] = body.integrations;
body.integrations.forEach(integration => {
should.exist(integration.api_keys);
should.equal(updatedIntegration.webhooks.length, 1);
const webhook = updatedIntegration.webhooks[0];
should.equal(webhook.integration_id, updatedIntegration.id);
request.put(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.send({
integrations: [{
webhooks: []
}]
})
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/?include=webhooks`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [updatedIntegration] = body.integrations;
should.equal(updatedIntegration.webhooks.length, 0);
done();
});
});
done();
});
});
});
});
});
});
});
});
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'))
.send({
integrations: [{
name: 'Rubbish Integration Name'
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
request.put(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Awesome Integration Name',
description: 'Finally got round to writing this...'
}]
})
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
it('Can succesfully delete a created integration', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Short Lived Integration'
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
request.del(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.expect(204)
.end(function (err) {
if (err) {
return done(err);
}
const [updatedIntegration] = body.integrations;
should.equal(updatedIntegration.id, createdIntegration.id);
should.equal(updatedIntegration.name, 'Awesome Integration Name');
should.equal(updatedIntegration.description, 'Finally got round to writing this...');
done();
});
});
});
});
it('Can successfully add and delete a created integrations webhooks', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Webhook-less Integration',
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
request.put(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.send({
integrations: [{
webhooks: [{
event: 'somestuff',
target_url: 'http://example.com'
}]
}]
})
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/?include=webhooks`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [updatedIntegration] = body.integrations;
should.equal(updatedIntegration.webhooks.length, 1);
const webhook = updatedIntegration.webhooks[0];
should.equal(webhook.integration_id, updatedIntegration.id);
request.put(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.send({
integrations: [{
webhooks: []
}]
})
.expect(200)
.end(function (err) {
if (err) {
return done(err);
}
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/?include=webhooks`))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [updatedIntegration] = body.integrations;
should.equal(updatedIntegration.webhooks.length, 0);
done();
});
});
});
});
});
});
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'))
.send({
integrations: [{
name: 'Short Lived Integration'
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
request.del(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.expect(204)
.end(function (err) {
if (err) {
return done(err);
}
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.expect(404)
.end(done);
});
});
});
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
*/
});
request.get(localUtils.API.getApiQuery(`integrations/${createdIntegration.id}/`))
.set('Origin', config.get('url'))
.expect(404)
.end(done);
});
});
});
});

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,146 +31,107 @@ describe('Invites API V2', function () {
sinon.restore();
});
describe('browse', function () {
it('default', function (done) {
request.get(localUtils.API.getApiQuery('invites/'))
.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);
}
it('Can fetch all invites', function (done) {
request.get(localUtils.API.getApiQuery('invites/'))
.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);
should.exist(jsonResponse.invites);
jsonResponse.invites.should.have.length(2);
should.not.exist(res.headers['x-cache-invalidate']);
const jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.invites);
jsonResponse.invites.should.have.length(2);
localUtils.API.checkResponse(jsonResponse, 'invites');
localUtils.API.checkResponse(jsonResponse.invites[0], 'invite');
localUtils.API.checkResponse(jsonResponse, 'invites');
localUtils.API.checkResponse(jsonResponse.invites[0], 'invite');
jsonResponse.invites[0].status.should.eql('sent');
jsonResponse.invites[0].email.should.eql('test1@ghost.org');
jsonResponse.invites[0].role_id.should.eql(testUtils.roles.ids.admin);
jsonResponse.invites[0].status.should.eql('sent');
jsonResponse.invites[0].email.should.eql('test1@ghost.org');
jsonResponse.invites[0].role_id.should.eql(testUtils.roles.ids.admin);
jsonResponse.invites[1].status.should.eql('sent');
jsonResponse.invites[1].email.should.eql('test2@ghost.org');
jsonResponse.invites[1].role_id.should.eql(testUtils.roles.ids.author);
jsonResponse.invites[1].status.should.eql('sent');
jsonResponse.invites[1].email.should.eql('test2@ghost.org');
jsonResponse.invites[1].role_id.should.eql(testUtils.roles.ids.author);
mailService.GhostMailer.prototype.send.called.should.be.false();
mailService.GhostMailer.prototype.send.called.should.be.false();
done();
});
});
done();
});
});
describe('read', function () {
it('default', function (done) {
request.get(localUtils.API.getApiQuery(`invites/${testUtils.DataGenerator.forKnex.invites[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);
}
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/)
.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);
should.exist(jsonResponse.invites);
jsonResponse.invites.should.have.length(1);
should.not.exist(res.headers['x-cache-invalidate']);
const jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.invites);
jsonResponse.invites.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.invites[0], 'invite');
localUtils.API.checkResponse(jsonResponse.invites[0], 'invite');
mailService.GhostMailer.prototype.send.called.should.be.false();
mailService.GhostMailer.prototype.send.called.should.be.false();
done();
});
});
done();
});
});
describe('add', function () {
it('default', function (done) {
request
.post(localUtils.API.getApiQuery('invites/'))
.set('Origin', config.get('url'))
.send({
invites: [{email: 'test@example.com', role_id: testUtils.existingData.roles[1].id}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
it('Can add a new invite', function (done) {
request
.post(localUtils.API.getApiQuery('invites/'))
.set('Origin', config.get('url'))
.send({
invites: [{email: 'test@example.com', role_id: testUtils.existingData.roles[1].id}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
should.not.exist(res.headers['x-cache-invalidate']);
const jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.invites);
jsonResponse.invites.should.have.length(1);
should.not.exist(res.headers['x-cache-invalidate']);
const jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.invites);
jsonResponse.invites.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.invites[0], 'invite');
jsonResponse.invites[0].role_id.should.eql(testUtils.existingData.roles[1].id);
localUtils.API.checkResponse(jsonResponse.invites[0], 'invite');
jsonResponse.invites[0].role_id.should.eql(testUtils.existingData.roles[1].id);
mailService.GhostMailer.prototype.send.called.should.be.true();
mailService.GhostMailer.prototype.send.called.should.be.true();
done();
});
});
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();
});
});
done();
});
});
describe('destroy', function () {
it('default', 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)
.expect(204)
.end(function (err) {
if (err) {
return done(err);
}
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)
.expect(204)
.end(function (err) {
if (err) {
return done(err);
}
mailService.GhostMailer.prototype.send.called.should.be.false();
done();
});
});
mailService.GhostMailer.prototype.send.called.should.be.false();
done();
});
});
});

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,141 +20,44 @@ describe('Notifications API V2', function () {
});
});
describe('Add', function () {
it('creates a new notification and sets default fields', function (done) {
const newNotification = {
type: 'info',
message: 'test notification',
custom: true,
id: 'customId'
};
it('Can add notification', function (done) {
const newNotification = {
type: 'info',
message: 'test notification',
custom: true,
id: 'customId'
};
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);
}
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);
}
var jsonResponse = res.body;
var jsonResponse = res.body;
should.exist(jsonResponse.notifications);
should.exist(jsonResponse.notifications);
localUtils.API.checkResponse(jsonResponse.notifications[0], 'notification');
localUtils.API.checkResponse(jsonResponse.notifications[0], 'notification');
jsonResponse.notifications[0].type.should.equal(newNotification.type);
jsonResponse.notifications[0].message.should.equal(newNotification.message);
jsonResponse.notifications[0].status.should.equal('alert');
jsonResponse.notifications[0].dismissible.should.be.true();
should.exist(jsonResponse.notifications[0].location);
jsonResponse.notifications[0].location.should.equal('bottom');
jsonResponse.notifications[0].id.should.be.a.String();
jsonResponse.notifications[0].type.should.equal(newNotification.type);
jsonResponse.notifications[0].message.should.equal(newNotification.message);
jsonResponse.notifications[0].status.should.equal('alert');
jsonResponse.notifications[0].dismissible.should.be.true();
should.exist(jsonResponse.notifications[0].location);
jsonResponse.notifications[0].location.should.equal('bottom');
jsonResponse.notifications[0].id.should.be.a.String();
done();
});
});
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');
});
});
});
done();
});
});
describe('Delete', function () {
it('Can delete notification', function (done) {
var newNotification = {
type: 'info',
message: 'test notification',
@ -162,92 +65,41 @@ 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'))
.send({notifications: [newNotification]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
// create the notification that is to be deleted
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;
const jsonResponse = res.body;
should.exist(jsonResponse.notifications);
localUtils.API.checkResponse(jsonResponse.notifications[0], 'notification');
jsonResponse.notifications.length.should.eql(1);
should.exist(jsonResponse.notifications);
localUtils.API.checkResponse(jsonResponse.notifications[0], 'notification');
jsonResponse.notifications.length.should.eql(1);
jsonResponse.notifications[0].type.should.equal(newNotification.type);
jsonResponse.notifications[0].message.should.equal(newNotification.message);
jsonResponse.notifications[0].status.should.equal(newNotification.status);
jsonResponse.notifications[0].type.should.equal(newNotification.type);
jsonResponse.notifications[0].message.should.equal(newNotification.message);
jsonResponse.notifications[0].status.should.equal(newNotification.status);
// begin delete test
request.del(localUtils.API.getApiQuery(`notifications/${jsonResponse.notifications[0].id}/`))
.set('Origin', config.get('url'))
.expect(204)
.end(function (err, res) {
if (err) {
return done(err);
}
// begin delete test
request.del(localUtils.API.getApiQuery(`notifications/${jsonResponse.notifications[0].id}/`))
.set('Origin', config.get('url'))
.expect(204)
.end(function (err, res) {
if (err) {
return done(err);
}
res.body.should.be.empty();
res.body.should.be.empty();
done();
});
});
});
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
done();
});
})
.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,41 +21,39 @@ describe('Oembed API', function () {
});
});
describe('success', function () {
it('can fetch an embed', function (done) {
let requestMock = nock('https://www.youtube.com')
.get('/oembed')
.query(true)
.reply(200, {
html: '<iframe width="480" height="270" src="https://www.youtube.com/embed/E5yFcdPAGv0?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>',
thumbnail_width: 480,
width: 480,
author_url: 'https://www.youtube.com/user/gorillaz',
height: 270,
thumbnail_height: 360,
provider_name: 'YouTube',
title: 'Gorillaz - Humility (Official Video)',
provider_url: 'https://www.youtube.com/',
author_name: 'Gorillaz',
version: '1.0',
thumbnail_url: 'https://i.ytimg.com/vi/E5yFcdPAGv0/hqdefault.jpg',
type: 'video'
});
it('can fetch an embed', function (done) {
let requestMock = nock('https://www.youtube.com')
.get('/oembed')
.query(true)
.reply(200, {
html: '<iframe width="480" height="270" src="https://www.youtube.com/embed/E5yFcdPAGv0?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>',
thumbnail_width: 480,
width: 480,
author_url: 'https://www.youtube.com/user/gorillaz',
height: 270,
thumbnail_height: 360,
provider_name: 'YouTube',
title: 'Gorillaz - Humility (Official Video)',
provider_url: 'https://www.youtube.com/',
author_name: 'Gorillaz',
version: '1.0',
thumbnail_url: 'https://i.ytimg.com/vi/E5yFcdPAGv0/hqdefault.jpg',
type: 'video'
});
request.get(localUtils.API.getApiQuery('oembed/?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DE5yFcdPAGv0'))
.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);
}
request.get(localUtils.API.getApiQuery('oembed/?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DE5yFcdPAGv0'))
.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);
}
requestMock.isDone().should.be.true();
should.exist(res.body.html);
done();
});
});
requestMock.isDone().should.be.true();
should.exist(res.body.html);
done();
});
});
});

View file

@ -10,561 +10,322 @@ const models = require('../../../../server/models');
const ghost = testUtils.startGhost;
let request;
describe('Posts API V2', function () {
describe('Posts API', function () {
let ghostServer;
let ownerCookie;
describe('As Owner', function () {
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('retrieves all published posts only by default', function (done) {
request.get(localUtils.API.getApiQuery('posts/'))
.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');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
// Ensure default order
jsonResponse.posts[0].slug.should.eql('welcome');
jsonResponse.posts[10].slug.should.eql('html-ipsum');
// Absolute urls by default
jsonResponse.posts[0].url.should.eql(`${config.get('url')}/welcome/`);
jsonResponse.posts[9].feature_image.should.eql(`${config.get('url')}/content/images/2018/hey.jpg`);
done();
});
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;
});
});
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/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
it('Can retrieve all posts', function (done) {
request.get(localUtils.API.getApiQuery('posts/'))
.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(3);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', ['mobiledoc', 'plaintext'], ['html']);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
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');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
// ensure order works
jsonResponse.posts[0].slug.should.eql('apps-integrations');
// Ensure default order
jsonResponse.posts[0].slug.should.eql('welcome');
jsonResponse.posts[10].slug.should.eql('html-ipsum');
done();
});
// Absolute urls by default
jsonResponse.posts[0].url.should.eql(`${config.get('url')}/welcome/`);
jsonResponse.posts[9].feature_image.should.eql(`${config.get('url')}/content/images/2018/hey.jpg`);
done();
});
});
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);
}
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/)
.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);
should.not.exist(res.headers['x-cache-invalidate']);
const jsonResponse = res.body;
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse, 'posts');
jsonResponse.posts.should.have.length(3);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', ['mobiledoc', 'plaintext'], ['html']);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
localUtils.API.checkResponse(
jsonResponse.posts[0],
'post',
null,
null,
['mobiledoc', 'id', 'title', 'html']
);
// ensure order works
jsonResponse.posts[0].slug.should.eql('apps-integrations');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
done();
});
done();
});
});
it('with includes', function (done) {
request.get(localUtils.API.getApiQuery('posts/?include=tags,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);
}
it('Can includes relations', function (done) {
request.get(localUtils.API.getApiQuery('posts/?include=tags,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',
['tags', 'authors']
);
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',
['tags', 'authors']
);
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
jsonResponse.posts[0].tags.length.should.eql(1);
jsonResponse.posts[0].authors.length.should.eql(1);
jsonResponse.posts[0].tags[0].url.should.eql(`${config.get('url')}/tag/getting-started/`);
jsonResponse.posts[0].authors[0].url.should.eql(`${config.get('url')}/author/ghost/`);
jsonResponse.posts[0].tags.length.should.eql(1);
jsonResponse.posts[0].authors.length.should.eql(1);
jsonResponse.posts[0].tags[0].url.should.eql(`${config.get('url')}/tag/getting-started/`);
jsonResponse.posts[0].authors[0].url.should.eql(`${config.get('url')}/author/ghost/`);
done();
});
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);
}
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/)
.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();
});
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('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);
}
it('Can paginate posts', 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);
}
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();
});
const jsonResponse = res.body;
should.equal(jsonResponse.meta.pagination.page, 2);
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);
}
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/)
.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();
});
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
jsonResponse.posts[0].id.should.equal(testUtils.DataGenerator.Content.posts[0].id);
jsonResponse.posts[0].page.should.not.be.ok();
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
testUtils.API.isISO8601(jsonResponse.posts[0].created_at).should.be.true();
// Tags aren't included by default
should.not.exist(jsonResponse.posts[0].tags);
done();
});
});
});
describe('read', function () {
it('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/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
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/)
.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.posts);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
jsonResponse.posts[0].id.should.equal(testUtils.DataGenerator.Content.posts[0].id);
jsonResponse.posts[0].page.should.not.be.ok();
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
testUtils.API.isISO8601(jsonResponse.posts[0].created_at).should.be.true();
// Tags aren't included by default
should.not.exist(jsonResponse.posts[0].tags);
done();
});
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
jsonResponse.posts[0].slug.should.equal('welcome');
jsonResponse.posts[0].page.should.not.be.ok();
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
// Tags aren't included by default
should.not.exist(jsonResponse.posts[0].tags);
done();
});
});
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);
}
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'))
.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);
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', ['mobiledoc', 'plaintext'], ['html']);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', ['tags', 'authors']);
done();
});
jsonResponse.posts[0].page.should.not.be.ok();
jsonResponse.posts[0].authors[0].should.be.an.Object();
localUtils.API.checkResponse(jsonResponse.posts[0].authors[0], 'user', ['url']);
jsonResponse.posts[0].tags[0].should.be.an.Object();
localUtils.API.checkResponse(jsonResponse.posts[0].tags[0], 'tag', ['url']);
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/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
it('Can add a post', function () {
const post = {
title: 'My post',
status: 'draft',
published_at: '2016-05-30T07:00:00.000Z',
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
created_at: moment().subtract(2, 'days').toDate(),
updated_at: moment().subtract(2, 'days').toDate(),
created_by: ObjectId.generate(),
updated_by: ObjectId.generate()
};
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.posts);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
jsonResponse.posts[0].slug.should.equal('welcome');
jsonResponse.posts[0].page.should.not.be.ok();
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
_.isBoolean(jsonResponse.posts[0].page).should.eql(true);
// Tags aren't included by default
should.not.exist(jsonResponse.posts[0].tags);
done();
});
});
return request.post(localUtils.API.getApiQuery('posts'))
.set('Origin', config.get('url'))
.send({posts: [post]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.then((res) => {
res.body.posts.length.should.eql(1);
localUtils.API.checkResponse(res.body.posts[0], 'post');
should.not.exist(res.headers['x-cache-invalidate']);
it('with includes', function (done) {
request
.get(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/?include=authors,tags'))
.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.posts);
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', ['tags', 'authors']);
jsonResponse.posts[0].page.should.not.be.ok();
jsonResponse.posts[0].authors[0].should.be.an.Object();
localUtils.API.checkResponse(jsonResponse.posts[0].authors[0], 'user', ['url']);
jsonResponse.posts[0].tags[0].should.be.an.Object();
localUtils.API.checkResponse(jsonResponse.posts[0].tags[0], 'tag', ['url']);
done();
});
});
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 () {
const post = {
title: 'My post',
status: 'draft',
published_at: '2016-05-30T07:00:00.000Z',
mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('my post'),
created_at: moment().subtract(2, 'days').toDate(),
updated_at: moment().subtract(2, 'days').toDate(),
created_by: ObjectId.generate(),
updated_by: ObjectId.generate()
};
return request.post(localUtils.API.getApiQuery('posts'))
.set('Origin', config.get('url'))
.send({posts: [post]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.then((res) => {
res.body.posts.length.should.eql(1);
localUtils.API.checkResponse(res.body.posts[0], 'post');
should.not.exist(res.headers['x-cache-invalidate']);
return models.Post.findOne({
id: res.body.posts[0].id,
status: 'draft'
}, testUtils.context.internal);
})
.then((model) => {
model.get('title').should.eql(post.title);
model.get('status').should.eql(post.status);
model.get('published_at').toISOString().should.eql('2016-05-30T07:00:00.000Z');
model.get('created_at').toISOString().should.not.eql(post.created_at.toISOString());
model.get('updated_at').toISOString().should.not.eql(post.updated_at.toISOString());
model.get('updated_by').should.not.eql(post.updated_by);
model.get('created_by').should.not.eql(post.created_by);
});
});
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 () {
const post = {
title: 'update draft'
};
return request.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[3].id))
.set('Origin', config.get('url'))
.send({posts: [post]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
res.headers['x-cache-invalidate'].should.eql('/p/' + res.body.posts[0].uuid + '/');
});
});
it('unpublish', function () {
const post = {
return models.Post.findOne({
id: res.body.posts[0].id,
status: 'draft'
};
return request
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[1].id + '/'))
.set('Origin', config.get('url'))
.send({posts: [post]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
res.headers['x-cache-invalidate'].should.eql('/*');
res.body.posts[0].status.should.eql('draft');
});
}, testUtils.context.internal);
})
.then((model) => {
model.get('title').should.eql(post.title);
model.get('status').should.eql(post.status);
model.get('published_at').toISOString().should.eql('2016-05-30T07:00:00.000Z');
model.get('created_at').toISOString().should.not.eql(post.created_at.toISOString());
model.get('updated_at').toISOString().should.not.eql(post.updated_at.toISOString());
model.get('updated_by').should.not.eql(post.updated_by);
model.get('created_by').should.not.eql(post.created_by);
});
});
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('Can update draft', function () {
const post = {
title: 'update draft'
};
describe('destroy', function () {
it('default', function () {
return request
.del(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
.set('Origin', config.get('url'))
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(204)
.then((res) => {
res.body.should.be.empty();
res.headers['x-cache-invalidate'].should.eql('/*');
});
return request.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[3].id))
.set('Origin', config.get('url'))
.send({posts: [post]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
res.headers['x-cache-invalidate'].should.eql('/p/' + res.body.posts[0].uuid + '/');
});
});
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']);
});
it('Can unpublish a post', function () {
const post = {
status: 'draft'
};
return request
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[1].id + '/'))
.set('Origin', config.get('url'))
.send({posts: [post]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
res.headers['x-cache-invalidate'].should.eql('/*');
res.body.posts[0].status.should.eql('draft');
});
});
it('Can destroy a post', function () {
return request
.del(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
.set('Origin', config.get('url'))
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(204)
.then((res) => {
res.body.should.be.empty();
res.headers['x-cache-invalidate'].should.eql('/*');
});
});
});
});

View file

@ -19,62 +19,60 @@ describe('Roles API', function () {
});
});
describe('browse', function () {
it('default', function (done) {
request.get(localUtils.API.getApiQuery('roles/'))
.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);
}
it('Can request all roles', function (done) {
request.get(localUtils.API.getApiQuery('roles/'))
.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 response = res.body;
should.exist(response);
should.exist(response.roles);
localUtils.API.checkResponse(response, 'roles');
response.roles.should.have.length(6);
localUtils.API.checkResponse(response.roles[0], 'role');
localUtils.API.checkResponse(response.roles[1], 'role');
localUtils.API.checkResponse(response.roles[2], 'role');
localUtils.API.checkResponse(response.roles[3], 'role');
localUtils.API.checkResponse(response.roles[4], 'role');
localUtils.API.checkResponse(response.roles[5], 'role');
should.not.exist(res.headers['x-cache-invalidate']);
const response = res.body;
should.exist(response);
should.exist(response.roles);
localUtils.API.checkResponse(response, 'roles');
response.roles.should.have.length(6);
localUtils.API.checkResponse(response.roles[0], 'role');
localUtils.API.checkResponse(response.roles[1], 'role');
localUtils.API.checkResponse(response.roles[2], 'role');
localUtils.API.checkResponse(response.roles[3], 'role');
localUtils.API.checkResponse(response.roles[4], 'role');
localUtils.API.checkResponse(response.roles[5], 'role');
done();
});
});
done();
});
});
it('permissions=assign', function (done) {
request.get(localUtils.API.getApiQuery('roles/?permissions=assign'))
.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);
}
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/)
.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 response = res.body;
should.exist(response.roles);
localUtils.API.checkResponse(response, 'roles');
response.roles.should.have.length(4);
localUtils.API.checkResponse(response.roles[0], 'role');
localUtils.API.checkResponse(response.roles[1], 'role');
localUtils.API.checkResponse(response.roles[2], 'role');
localUtils.API.checkResponse(response.roles[3], 'role');
response.roles[0].name.should.equal('Administrator');
response.roles[1].name.should.equal('Editor');
response.roles[2].name.should.equal('Author');
response.roles[3].name.should.equal('Contributor');
should.not.exist(res.headers['x-cache-invalidate']);
const response = res.body;
should.exist(response.roles);
localUtils.API.checkResponse(response, 'roles');
response.roles.should.have.length(4);
localUtils.API.checkResponse(response.roles[0], 'role');
localUtils.API.checkResponse(response.roles[1], 'role');
localUtils.API.checkResponse(response.roles[2], 'role');
localUtils.API.checkResponse(response.roles[3], 'role');
response.roles[0].name.should.equal('Administrator');
response.roles[1].name.should.equal('Editor');
response.roles[2].name.should.equal('Author');
response.roles[3].name.should.equal('Contributor');
done();
});
});
done();
});
});
});

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,140 +28,75 @@ describe('Upload API', function () {
});
});
describe('success cases', function () {
it('valid png', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/ghost-logo.png'))
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
it('Can upload a png', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/ghost-logo.png'))
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
res.body.should.match(new RegExp(`${config.get('url')}/content/images/\\d+/\\d+/ghost-logo.png`));
res.body.should.match(new RegExp(`${config.get('url')}/content/images/\\d+/\\d+/ghost-logo.png`));
images.push(res.body.replace(config.get('url'), ''));
done();
});
});
it('valid jpg', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/ghosticon.jpg'))
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
res.body.should.match(new RegExp(`${config.get('url')}/content/images/\\d+/\\d+/ghosticon.jpg`));
images.push(res.body.replace(config.get('url'), ''));
done();
});
});
it('valid gif', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/loadingcat.gif'))
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
res.body.should.match(new RegExp(`${config.get('url')}/content/images/\\d+/\\d+/loadingcat.gif`));
images.push(res.body.replace(config.get('url'), ''));
done();
});
});
it('valid profile image', 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/loadingcat_square.gif'))
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
res.body.should.match(new RegExp(`${config.get('url')}/content/images/\\d+/\\d+/loadingcat_square.gif`));
images.push(res.body.replace(config.get('url'), ''));
done();
});
});
images.push(res.body.replace(config.get('url'), ''));
done();
});
});
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);
}
it('Can upload a jpg', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/ghosticon.jpg'))
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
done();
});
});
res.body.should.match(new RegExp(`${config.get('url')}/content/images/\\d+/\\d+/ghosticon.jpg`));
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);
}
images.push(res.body.replace(config.get('url'), ''));
done();
});
});
done();
});
});
it('Can upload a gif', function (done) {
request.post(localUtils.API.getApiQuery('uploads'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/loadingcat.gif'))
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
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);
}
res.body.should.match(new RegExp(`${config.get('url')}/content/images/\\d+/\\d+/loadingcat.gif`));
done();
});
});
images.push(res.body.replace(config.get('url'), ''));
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);
}
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/)
.attach('uploadimage', path.join(__dirname, '/../../../utils/fixtures/images/loadingcat_square.gif'))
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
done();
});
});
res.body.should.match(new RegExp(`${config.get('url')}/content/images/\\d+/\\d+/loadingcat_square.gif`));
images.push(res.body.replace(config.get('url'), ''));
done();
});
});
});

View file

@ -12,574 +12,315 @@ 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) {
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);
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;
describe('Browse', function () {
it('returns dates in ISO 8601 format', function (done) {
// @NOTE: ASC is default
request.get(localUtils.API.getApiQuery('users/?order=id%20DESC'))
.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);
}
// 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;
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse.users);
localUtils.API.checkResponse(jsonResponse, 'users');
// owner use + ghost-author user when Ghost starts
// and two extra users, see createUser in before
jsonResponse.users.should.have.length(4);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['url']);
jsonResponse.users[0].email.should.eql(admin.email);
jsonResponse.users[0].status.should.eql(admin.status);
jsonResponse.users[1].email.should.eql(inactiveUser.email);
jsonResponse.users[1].status.should.eql(inactiveUser.status);
jsonResponse.users[2].email.should.eql('ghost-author@example.com');
jsonResponse.users[3].email.should.eql(testUtils.DataGenerator.Content.users[0].email);
testUtils.API.isISO8601(jsonResponse.users[3].last_seen).should.be.true();
testUtils.API.isISO8601(jsonResponse.users[3].created_at).should.be.true();
testUtils.API.isISO8601(jsonResponse.users[3].updated_at).should.be.true();
jsonResponse.users[0].url.should.eql(`${config.get('url')}/author/admin-user/`);
jsonResponse.users[1].url.should.eql(`${config.get('url')}/404/`);
jsonResponse.users[2].url.should.eql(`${config.get('url')}/author/ghost/`);
jsonResponse.users[3].url.should.eql(`${config.get('url')}/author/joe-bloggs/`);
done();
});
// by default we login with the owner
return localUtils.doAuth(request);
});
});
it('can retrieve all users with includes', function (done) {
request.get(localUtils.API.getApiQuery('users/?include=roles'))
.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);
}
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'))
.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);
localUtils.API.checkResponse(jsonResponse, 'users');
should.not.exist(res.headers['x-cache-invalidate']);
jsonResponse.users.should.have.length(4);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles', 'url']);
done();
});
var jsonResponse = res.body;
should.exist(jsonResponse.users);
localUtils.API.checkResponse(jsonResponse, 'users');
// owner use + ghost-author user when Ghost starts
// and two extra users, see createUser in before
jsonResponse.users.should.have.length(4);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['url']);
jsonResponse.users[0].email.should.eql(admin.email);
jsonResponse.users[0].status.should.eql(admin.status);
jsonResponse.users[1].email.should.eql(inactiveUser.email);
jsonResponse.users[1].status.should.eql(inactiveUser.status);
jsonResponse.users[2].email.should.eql('ghost-author@example.com');
jsonResponse.users[3].email.should.eql(testUtils.DataGenerator.Content.users[0].email);
testUtils.API.isISO8601(jsonResponse.users[3].last_seen).should.be.true();
testUtils.API.isISO8601(jsonResponse.users[3].created_at).should.be.true();
testUtils.API.isISO8601(jsonResponse.users[3].updated_at).should.be.true();
jsonResponse.users[0].url.should.eql(`${config.get('url')}/author/admin-user/`);
jsonResponse.users[1].url.should.eql(`${config.get('url')}/404/`);
jsonResponse.users[2].url.should.eql(`${config.get('url')}/author/ghost/`);
jsonResponse.users[3].url.should.eql(`${config.get('url')}/author/joe-bloggs/`);
done();
});
});
it('supports usage of the page param', function (done) {
request.get(localUtils.API.getApiQuery('users/?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);
}
it('Can include user roles', function (done) {
request.get(localUtils.API.getApiQuery('users/?include=roles'))
.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();
});
should.not.exist(res.headers['x-cache-invalidate']);
var jsonResponse = res.body;
should.exist(jsonResponse.users);
localUtils.API.checkResponse(jsonResponse, 'users');
jsonResponse.users.should.have.length(4);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles', 'url']);
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);
}
it('Can paginate users', function (done) {
request.get(localUtils.API.getApiQuery('users/?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);
}
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();
});
const jsonResponse = res.body;
should.equal(jsonResponse.meta.pagination.page, 2);
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);
}
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)
.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);
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();
});
jsonResponse.users.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles', 'count', 'url']);
localUtils.API.checkResponse(jsonResponse.users[0].roles[0], 'role', ['permissions']);
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);
}
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);
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();
});
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);
}
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);
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();
});
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'))
.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);
}
it('can edit a user', function (done) {
request.put(localUtils.API.getApiQuery('users/me/'))
.set('Origin', config.get('url'))
.send({
users: [{
website: 'http://joe-bloggs.ghost.org',
password: 'mynewfancypasswordwhichisnotallowed'
}]
})
.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);
var putBody = res.body;
res.headers['x-cache-invalidate'].should.eql('/*');
should.exist(putBody.users[0]);
putBody.users[0].website.should.eql('http://joe-bloggs.ghost.org');
putBody.users[0].email.should.eql('jbloggs@example.com');
localUtils.API.checkResponse(putBody.users[0], 'user', ['url']);
jsonResponse.users.should.have.length(1);
localUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles', 'count', 'url']);
localUtils.API.checkResponse(jsonResponse.users[0].roles[0], 'role', ['permissions']);
done();
});
});
should.not.exist(putBody.users[0].password);
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('Edit', function () {
it('can edit a user', function (done) {
request.put(localUtils.API.getApiQuery('users/me/'))
.set('Origin', config.get('url'))
.send({
users: [{
website: 'http://joe-bloggs.ghost.org',
password: 'mynewfancypasswordwhichisnotallowed'
}]
models.User.findOne({id: putBody.users[0].id})
.then((user) => {
return models.User.isPasswordCorrect({
plainPassword: 'mynewfancypasswordwhichisnotallowed',
hashedPassword: user.get('password')
});
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
var putBody = res.body;
res.headers['x-cache-invalidate'].should.eql('/*');
should.exist(putBody.users[0]);
putBody.users[0].website.should.eql('http://joe-bloggs.ghost.org');
putBody.users[0].email.should.eql('jbloggs@example.com');
localUtils.API.checkResponse(putBody.users[0], 'user', ['url']);
should.not.exist(putBody.users[0].password);
models.User.findOne({id: putBody.users[0].id})
.then((user) => {
return models.User.isPasswordCorrect({
plainPassword: 'mynewfancypasswordwhichisnotallowed',
hashedPassword: user.get('password')
});
})
.then(Promise.reject)
.catch((err) => {
err.code.should.eql('PASSWORD_INCORRECT');
done();
});
.then(Promise.reject)
.catch((err) => {
err.code.should.eql('PASSWORD_INCORRECT');
done();
});
});
});
});
describe('Destroy', function () {
it('[success] Destroy active user', function () {
const userId = testUtils.existingData.users[1].id;
it('Can destroy an active user', function () {
const userId = testUtils.existingData.users[1].id;
return request
.get(localUtils.API.getApiQuery(`posts/?filter=author_id:${userId}`))
.set('Origin', config.get('url'))
.expect(200)
.then((res) => {
res.body.posts.length.should.eql(7);
return request
.delete(localUtils.API.getApiQuery(`users/${userId}`))
.set('Origin', config.get('url'))
.expect(204);
})
.then(() => {
return request
.get(localUtils.API.getApiQuery(`users/${userId}/`))
.set('Origin', config.get('url'))
.expect(404);
})
.then(() => {
return request
.get(localUtils.API.getApiQuery(`posts/?filter=author_id:${userId}`))
.set('Origin', config.get('url'))
.expect(200)
.then((res) => {
res.body.posts.length.should.eql(7);
.expect(200);
})
.then((res) => {
res.body.posts.length.should.eql(0);
return request
.delete(localUtils.API.getApiQuery(`users/${userId}`))
.set('Origin', config.get('url'))
.expect(204);
return db.knex('roles_users')
.where({
user_id: userId
})
.then(() => {
return request
.get(localUtils.API.getApiQuery(`users/${userId}/`))
.set('Origin', config.get('url'))
.expect(404);
})
.then(() => {
return request
.get(localUtils.API.getApiQuery(`posts/?filter=author_id:${userId}`))
.set('Origin', config.get('url'))
.expect(200);
})
.then((res) => {
res.body.posts.length.should.eql(0);
.select();
})
.then((models) => {
models.length.should.eql(0);
return db.knex('roles_users')
.where({
user_id: userId
})
.select();
})
.then((models) => {
models.length.should.eql(0);
return db.knex('roles_users')
.select();
})
.then((models) => {
models.length.should.greaterThan(0);
});
return db.knex('roles_users')
.select();
})
.then((models) => {
models.length.should.greaterThan(0);
});
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 () {
return request
.put(localUtils.API.getApiQuery('users/owner'))
.set('Origin', config.get('url'))
.send({
owner: [{
id: admin.id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
res.body.users[0].roles[0].name.should.equal(testUtils.DataGenerator.Content.roles[0].name);
res.body.users[1].roles[0].name.should.equal(testUtils.DataGenerator.Content.roles[3].name);
});
});
});
describe('Change Password', function () {
it('default', function () {
return request
.put(localUtils.API.getApiQuery('users/password'))
.set('Origin', config.get('url'))
.send({
password: [{
newPassword: '1234abcde!!',
ne2Password: '1234abcde!!',
oldPassword: 'Sl1m3rson99',
user_id: testUtils.existingData.users[0].id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
should.exist(res.body.password);
should.exist(res.body.password[0].message);
});
});
});
});
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();
});
it('Can transfer ownership to admin user', function () {
return request
.put(localUtils.API.getApiQuery('users/owner'))
.set('Origin', config.get('url'))
.send({
owner: [{
id: admin.id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
res.body.users[0].roles[0].name.should.equal(testUtils.DataGenerator.Content.roles[0].name);
res.body.users[1].roles[0].name.should.equal(testUtils.DataGenerator.Content.roles[3].name);
});
});
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();
});
it('Can change password', function () {
return request
.put(localUtils.API.getApiQuery('users/password'))
.set('Origin', config.get('url'))
.send({
password: [{
newPassword: '1234abcde!!',
ne2Password: '1234abcde!!',
oldPassword: 'Sl1m3rson99',
user_id: testUtils.existingData.users[0].id
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
should.exist(res.body.password);
should.exist(res.body.password[0].message);
});
});
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,94 +9,77 @@ let request;
describe('Webhooks API', function () {
var ghostServer;
describe('As Owner', function () {
var ownerAccessToken = '';
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
return localUtils.doAuth(request);
});
});
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();
});
before(function () {
return ghost()
.then(function (_ghostServer) {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(function () {
return localUtils.doAuth(request);
});
});
it('creates a new webhook with name, secret and api version', function (done) {
let webhookData = {
event: 'test.create',
target_url: 'http://example.com/webhooks/test/extra/1',
name: 'test',
secret: 'thisissecret',
api_version: 'v2'
};
request.post(localUtils.API.getApiQuery('webhooks/'))
.set('Origin', config.get('url'))
.send({webhooks: [webhookData]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
it('Can creates a webhook', function (done) {
let webhookData = {
event: 'test.create',
target_url: 'http://example.com/webhooks/test/extra/1',
name: 'test',
secret: 'thisissecret',
api_version: 'v2'
};
var jsonResponse = res.body;
request.post(localUtils.API.getApiQuery('webhooks/'))
.set('Origin', config.get('url'))
.send({webhooks: [webhookData]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.end(function (err, res) {
if (err) {
return done(err);
}
should.exist(jsonResponse.webhooks);
var jsonResponse = res.body;
localUtils.API.checkResponse(jsonResponse.webhooks[0], 'webhook', ['name', 'secret']);
should.exist(jsonResponse.webhooks);
jsonResponse.webhooks[0].event.should.equal(webhookData.event);
jsonResponse.webhooks[0].target_url.should.equal(webhookData.target_url);
jsonResponse.webhooks[0].secret.should.equal(webhookData.secret);
jsonResponse.webhooks[0].name.should.equal(webhookData.name);
jsonResponse.webhooks[0].api_version.should.equal(webhookData.api_version);
localUtils.API.checkResponse(jsonResponse.webhooks[0], 'webhook', ['name', 'secret']);
done();
});
jsonResponse.webhooks[0].event.should.equal(webhookData.event);
jsonResponse.webhooks[0].target_url.should.equal(webhookData.target_url);
jsonResponse.webhooks[0].secret.should.equal(webhookData.secret);
jsonResponse.webhooks[0].name.should.equal(webhookData.name);
jsonResponse.webhooks[0].api_version.should.equal(webhookData.api_version);
done();
});
});
});
describe('Edit', function () {
it('can succesfully edit a webhook', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
it('Can edit a webhook', function (done) {
request.post(localUtils.API.getApiQuery('integrations/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Rubbish Integration Name'
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
const [createdIntegration] = body.integrations;
request.post(localUtils.API.getApiQuery('webhooks/'))
.set('Origin', config.get('url'))
.send({
integrations: [{
name: 'Rubbish Integration Name'
webhooks: [{
name: 'Testing',
event: 'site.changed',
target_url: 'https://example.com/rebuild',
integration_id: createdIntegration.id
}]
})
.expect(201)
@ -105,96 +88,74 @@ describe('Webhooks API', function () {
return done(err);
}
const [createdIntegration] = body.integrations;
const [createdWebhook] = body.webhooks;
request.post(localUtils.API.getApiQuery('webhooks/'))
request.put(localUtils.API.getApiQuery(`webhooks/${createdWebhook.id}/`))
.set('Origin', config.get('url'))
.send({
webhooks: [{
name: 'Testing',
event: 'site.changed',
target_url: 'https://example.com/rebuild',
integration_id: createdIntegration.id
name: 'Edit Test',
event: 'subscriber.added',
target_url: 'https://example.com/new-subscriber'
}]
})
.expect(201)
.end(function (err, {body}) {
if (err) {
return done(err);
}
.expect(200)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.then(({body}) => {
const [updatedWebhook] = body.webhooks;
const [createdWebhook] = body.webhooks;
request.put(localUtils.API.getApiQuery(`webhooks/${createdWebhook.id}/`))
.set('Origin', config.get('url'))
.send({
webhooks: [{
name: 'Edit Test',
event: 'subscriber.added',
target_url: 'https://example.com/new-subscriber'
}]
})
.expect(200)
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.then(({body}) => {
const [updatedWebhook] = body.webhooks;
should.equal(updatedWebhook.id, createdWebhook.id);
should.equal(updatedWebhook.name, 'Edit Test');
should.equal(updatedWebhook.event, 'subscriber.added');
should.equal(updatedWebhook.target_url, 'https://example.com/new-subscriber');
should.equal(updatedWebhook.integration_id, createdIntegration.id);
done();
});
should.equal(updatedWebhook.id, createdWebhook.id);
should.equal(updatedWebhook.name, 'Edit Test');
should.equal(updatedWebhook.event, 'subscriber.added');
should.equal(updatedWebhook.target_url, 'https://example.com/new-subscriber');
should.equal(updatedWebhook.integration_id, createdIntegration.id);
done();
});
});
});
});
});
describe('Delete', function () {
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('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/'))
// create the webhook that is to be deleted
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 location = res.headers.location;
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);
// begin delete test
request.del(localUtils.API.getApiQuery('webhooks/' + jsonResponse.webhooks[0].id + '/'))
.set('Origin', config.get('url'))
.send({webhooks: [newWebhook]})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.expect(204)
.end(function (err, res) {
if (err) {
return done(err);
}
var location = res.headers.location;
var jsonResponse = res.body;
res.body.should.be.empty();
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);
// begin delete test
request.del(localUtils.API.getApiQuery('webhooks/' + jsonResponse.webhooks[0].id + '/'))
.set('Origin', config.get('url'))
.expect(204)
.end(function (err, res) {
if (err) {
return done(err);
}
res.body.should.be.empty();
done();
});
done();
});
});
});
});
});

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
);
}
};