mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Deleted v3 regression tests
- at the time of writing, the v3 API === canary API - we have both v3 + canary regression tests, which are nearly the same but there are slight deviations that we keep missing when adding new tests - the canary tests are actually describing functionality of the v3 API - therefore, we should be ok to delete the v3 regression tests for now - when v3 is stable, we can copy the canary tests back to v3
This commit is contained in:
parent
2d621c9680
commit
4ef019d88d
17 changed files with 0 additions and 3678 deletions
|
@ -1,317 +0,0 @@
|
|||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const supertest = require('supertest');
|
||||
const localUtils = require('./utils');
|
||||
const testUtils = require('../../../../utils/index');
|
||||
const models = require('../../../../../core/server/models/index');
|
||||
const security = require('@tryghost/security');
|
||||
const settingsCache = require('../../../../../core/server/services/settings/cache');
|
||||
const config = require('../../../../../core/shared/config/index');
|
||||
const mailService = require('../../../../../core/server/services/mail/index');
|
||||
|
||||
let ghost = testUtils.startGhost;
|
||||
let request;
|
||||
|
||||
describe('Authentication API v3', function () {
|
||||
let ghostServer;
|
||||
|
||||
describe('Blog setup', function () {
|
||||
before(function () {
|
||||
return ghost({forceStart: true})
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
request = supertest.agent(config.get('url'));
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
sinon.stub(mailService.GhostMailer.prototype, 'send').resolves('Mail is disabled');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('is setup? no', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery('authentication/setup'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.body.setup[0].status.should.be.false();
|
||||
});
|
||||
});
|
||||
|
||||
it('complete setup', function () {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('authentication/setup'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
setup: [{
|
||||
name: 'test user',
|
||||
email: 'test@example.com',
|
||||
password: 'thisissupersafe',
|
||||
blogTitle: 'a test blog'
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(201)
|
||||
.then((res) => {
|
||||
const 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');
|
||||
|
||||
const newUser = jsonResponse.users[0];
|
||||
newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
|
||||
newUser.name.should.equal('test user');
|
||||
newUser.email.should.equal('test@example.com');
|
||||
|
||||
mailService.GhostMailer.prototype.send.called.should.be.true();
|
||||
mailService.GhostMailer.prototype.send.args[0][0].to.should.equal('test@example.com');
|
||||
});
|
||||
});
|
||||
|
||||
it('is setup? yes', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery('authentication/setup'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.body.setup[0].status.should.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
it('complete setup again', function () {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('authentication/setup'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
setup: [{
|
||||
name: 'test user',
|
||||
email: 'test-leo@example.com',
|
||||
password: 'thisissupersafe',
|
||||
blogTitle: 'a test blog'
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it('update setup', function () {
|
||||
return localUtils.doAuth(request)
|
||||
.then(() => {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('authentication/setup'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
setup: [{
|
||||
name: 'test user edit',
|
||||
email: 'test-edit@example.com',
|
||||
password: 'thisissupersafe',
|
||||
blogTitle: 'a test blog'
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
const 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');
|
||||
|
||||
const newUser = jsonResponse.users[0];
|
||||
newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
|
||||
newUser.name.should.equal('test user edit');
|
||||
newUser.email.should.equal('test-edit@example.com');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Invitation', function () {
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
request = supertest.agent(config.get('url'));
|
||||
|
||||
// simulates blog setup (initialises the owner)
|
||||
return localUtils.doAuth(request, 'invites');
|
||||
});
|
||||
});
|
||||
|
||||
it('check invite with invalid email', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery('authentication/invitation?email=invalidemail'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it('check valid invite', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`authentication/invitation?email=${testUtils.DataGenerator.forKnex.invites[0].email}`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.body.invitation[0].valid.should.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('check invalid invite', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`authentication/invitation?email=notinvited@example.org`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.body.invitation[0].valid.should.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('try to accept without invite', function () {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('authentication/invitation'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
invitation: [{
|
||||
token: 'lul11111',
|
||||
password: 'lel123456',
|
||||
email: 'not-invited@example.org',
|
||||
name: 'not invited'
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('try to accept with invite', function () {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('authentication/invitation'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
invitation: [{
|
||||
token: testUtils.DataGenerator.forKnex.invites[0].token,
|
||||
password: '12345678910',
|
||||
email: testUtils.DataGenerator.forKnex.invites[0].email,
|
||||
name: 'invited'
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.body.invitation[0].message.should.equal('Invitation accepted.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Password reset', function () {
|
||||
const user = testUtils.DataGenerator.forModel.users[0];
|
||||
|
||||
before(function () {
|
||||
return ghost({forceStart: true})
|
||||
.then(() => {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(() => {
|
||||
return localUtils.doAuth(request);
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
sinon.stub(mailService.GhostMailer.prototype, 'send').resolves('Mail is disabled');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('reset password', function (done) {
|
||||
models.User.getOwnerUser(testUtils.context.internal)
|
||||
.then(function (ownerUser) {
|
||||
const token = security.tokens.resetToken.generateHash({
|
||||
expires: Date.now() + (1000 * 60),
|
||||
email: user.email,
|
||||
dbHash: settingsCache.get('db_hash'),
|
||||
password: ownerUser.get('password')
|
||||
});
|
||||
|
||||
request.put(localUtils.API.getApiQuery('authentication/passwordreset'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.send({
|
||||
passwordreset: [{
|
||||
token: token,
|
||||
newPassword: 'thisissupersafe',
|
||||
ne2Password: 'thisissupersafe'
|
||||
}]
|
||||
})
|
||||
.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.passwordreset[0].message);
|
||||
jsonResponse.passwordreset[0].message.should.equal('Password changed successfully.');
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
it('reset password: invalid token', function () {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('authentication/passwordreset'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.send({
|
||||
passwordreset: [{
|
||||
token: 'invalid',
|
||||
newPassword: 'thisissupersafe',
|
||||
ne2Password: 'thisissupersafe'
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(401)
|
||||
.then((res) => {
|
||||
should.exist(res.body.errors);
|
||||
res.body.errors[0].type.should.eql('UnauthorizedError');
|
||||
res.body.errors[0].message.should.eql('Cannot reset password.');
|
||||
});
|
||||
});
|
||||
|
||||
it('reset password: generate reset token', function () {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('authentication/passwordreset'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.send({
|
||||
passwordreset: [{
|
||||
email: user.email
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.passwordreset[0].message);
|
||||
jsonResponse.passwordreset[0].message.should.equal('Check your email for further instructions.');
|
||||
mailService.GhostMailer.prototype.send.args[0][0].to.should.equal(user.email);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,172 +0,0 @@
|
|||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const os = require('os');
|
||||
const fs = require('fs-extra');
|
||||
const uuid = require('uuid');
|
||||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const sinon = require('sinon');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
const {events} = require('../../../../../core/server/lib/common');
|
||||
const testUtils = require('../../../../utils');
|
||||
const localUtils = require('./utils');
|
||||
|
||||
let ghost = testUtils.startGhost;
|
||||
let request;
|
||||
let eventsTriggered;
|
||||
|
||||
describe('DB API', function () {
|
||||
let backupKey;
|
||||
let schedulerKey;
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(() => {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(() => {
|
||||
return localUtils.doAuth(request);
|
||||
})
|
||||
.then(() => {
|
||||
backupKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
schedulerKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
eventsTriggered = {};
|
||||
|
||||
sinon.stub(events, 'emit').callsFake((eventName, eventObj) => {
|
||||
if (!eventsTriggered[eventName]) {
|
||||
eventsTriggered[eventName] = [];
|
||||
}
|
||||
|
||||
eventsTriggered[eventName].push(eventObj);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
// SKIPPED: we no longer have the "extra" clients and client_trusted_domains tables
|
||||
it.skip('can export the database with more tables', function () {
|
||||
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(28);
|
||||
});
|
||||
});
|
||||
|
||||
it('can export & import', function () {
|
||||
const exportFolder = path.join(os.tmpdir(), uuid.v4());
|
||||
const exportPath = path.join(exportFolder, 'export.json');
|
||||
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
settings: [
|
||||
{
|
||||
key: 'is_private',
|
||||
value: true
|
||||
}
|
||||
]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then(() => {
|
||||
return request.get(localUtils.API.getApiQuery('db/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.db);
|
||||
|
||||
fs.ensureDirSync(exportFolder);
|
||||
fs.writeJSONSync(exportPath, jsonResponse);
|
||||
|
||||
return request.post(localUtils.API.getApiQuery('db/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.attach('importfile', exportPath)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
res.body.problems.length.should.eql(3);
|
||||
fs.removeSync(exportFolder);
|
||||
});
|
||||
});
|
||||
|
||||
it('fails when triggering an export from unknown filename ', function () {
|
||||
return request.get(localUtils.API.getApiQuery('db/?filename=this_file_is_not_here.json'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('import should fail without file', function () {
|
||||
return request.post(localUtils.API.getApiQuery('db/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(422);
|
||||
});
|
||||
|
||||
it('import should fail with unsupported file', function () {
|
||||
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('backup can be triggered by backup integration', function () {
|
||||
const backupQuery = `?filename=test`;
|
||||
const fsStub = sinon.stub(fs, 'writeFile').resolves();
|
||||
|
||||
return request.post(localUtils.API.getApiQuery(`db/backup${backupQuery}`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', backupKey)}`)
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.body.should.be.Object();
|
||||
res.body.db[0].filename.should.match(/test\.json/);
|
||||
fsStub.calledOnce.should.eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('backup can not be triggered by integration other than backup', function () {
|
||||
const fsStub = sinon.stub(fs, 'writeFile').resolves();
|
||||
|
||||
return request.post(localUtils.API.getApiQuery(`db/backup`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', schedulerKey)}`)
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(403)
|
||||
.then((res) => {
|
||||
should.exist(res.body.errors);
|
||||
res.body.errors[0].type.should.eql('NoPermissionError');
|
||||
fsStub.called.should.eql(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('backup can be triggered by Admin authentication', function () {
|
||||
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(200);
|
||||
});
|
||||
});
|
|
@ -1,86 +0,0 @@
|
|||
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('../../../../../core/shared/config');
|
||||
|
||||
const ghost = testUtils.startGhost;
|
||||
|
||||
describe('Images 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('Can\'t import fail without file', function () {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('images/upload'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(422);
|
||||
});
|
||||
|
||||
it('Can\'t import with unsupported file', function (done) {
|
||||
request.post(localUtils.API.getApiQuery('images/upload'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.attach('file', path.join(__dirname, '/../../../../utils/fixtures/csv/single-column-with-header.csv'))
|
||||
.expect(415)
|
||||
.end(function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can\'t upload incorrect extension', function (done) {
|
||||
request.post(localUtils.API.getApiQuery('images/upload'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('content-type', 'image/png')
|
||||
.expect('Content-Type', /json/)
|
||||
.attach('file', path.join(__dirname, '/../../../../utils/fixtures/images/ghost-logo.pngx'))
|
||||
.expect(415)
|
||||
.end(function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can\'t import if profile image is not square', function (done) {
|
||||
request.post(localUtils.API.getApiQuery('images/upload'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.field('purpose', 'profile_image')
|
||||
.attach('file', path.join(__dirname, '/../../../../utils/fixtures/images/favicon_not_square.png'))
|
||||
.expect(422)
|
||||
.end(function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,198 +0,0 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const testUtils = require('../../../../utils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
const localUtils = require('./utils');
|
||||
const ghost = testUtils.startGhost;
|
||||
|
||||
describe('Notifications API', function () {
|
||||
describe('As Editor', function () {
|
||||
let request;
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function (_ghostServer) {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.createUser({
|
||||
user: testUtils.DataGenerator.forKnex.createUser({
|
||||
email: 'test+editor@ghost.org'
|
||||
}),
|
||||
role: testUtils.DataGenerator.Content.roles[1].name
|
||||
});
|
||||
})
|
||||
.then((user) => {
|
||||
request.user = user;
|
||||
return localUtils.doAuth(request);
|
||||
});
|
||||
});
|
||||
|
||||
it('Add notification', function () {
|
||||
const newNotification = {
|
||||
type: 'info',
|
||||
message: 'test notification',
|
||||
custom: true
|
||||
};
|
||||
|
||||
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(201)
|
||||
.then((res) => {
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.notifications);
|
||||
should.equal(jsonResponse.notifications.length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('Read notifications', function () {
|
||||
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;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.notifications);
|
||||
should.equal(jsonResponse.notifications.length, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Author', function () {
|
||||
let request;
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function (_ghostServer) {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.createUser({
|
||||
user: testUtils.DataGenerator.forKnex.createUser({
|
||||
email: 'test+author@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
|
||||
};
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
it('Read notifications', function () {
|
||||
return request.get(localUtils.API.getApiQuery('notifications/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(403);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Can view by multiple users', function () {
|
||||
let requestEditor1;
|
||||
let requestEditor2;
|
||||
let notification;
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function (_ghostServer) {
|
||||
requestEditor1 = supertest.agent(config.get('url'));
|
||||
requestEditor2 = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.createUser({
|
||||
user: testUtils.DataGenerator.forKnex.createUser({
|
||||
email: 'test+editor1@ghost.org'
|
||||
}),
|
||||
role: testUtils.DataGenerator.Content.roles[1].name
|
||||
});
|
||||
})
|
||||
.then((user) => {
|
||||
requestEditor1.user = user;
|
||||
return localUtils.doAuth(requestEditor1);
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.createUser({
|
||||
user: testUtils.DataGenerator.forKnex.createUser({
|
||||
email: 'test+editor2@ghost.org'
|
||||
}),
|
||||
role: testUtils.DataGenerator.Content.roles[1].name
|
||||
});
|
||||
})
|
||||
.then((user) => {
|
||||
requestEditor2.user = user;
|
||||
return localUtils.doAuth(requestEditor2);
|
||||
})
|
||||
.then(() => {
|
||||
const newNotification = {
|
||||
type: 'info',
|
||||
message: 'multiple views',
|
||||
custom: true
|
||||
};
|
||||
|
||||
return requestEditor1.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)
|
||||
.then((res) => {
|
||||
notification = res.body.notifications[0];
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('notification is visible and dismissible by other user', function () {
|
||||
return requestEditor1.del(localUtils.API.getApiQuery(`notifications/${notification.id}`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(204)
|
||||
.then(() => {
|
||||
return requestEditor2.get(localUtils.API.getApiQuery(`notifications/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then(function (res) {
|
||||
const deleted = res.body.notifications.filter(n => n.id === notification.id);
|
||||
deleted.should.not.be.empty();
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
return requestEditor2.del(localUtils.API.getApiQuery(`notifications/${notification.id}`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(204);
|
||||
})
|
||||
.then(() => {
|
||||
return requestEditor2.get(localUtils.API.getApiQuery(`notifications/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then(function (res) {
|
||||
const deleted = res.body.notifications.filter(n => n.id === notification.id);
|
||||
deleted.should.be.empty();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,444 +0,0 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const ObjectId = require('bson-objectid');
|
||||
const moment = require('moment-timezone');
|
||||
const testUtils = require('../../../../utils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
const models = require('../../../../../core/server/models');
|
||||
const localUtils = require('./utils');
|
||||
const ghost = testUtils.startGhost;
|
||||
let request;
|
||||
|
||||
describe('Posts API (v3)', 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(13);
|
||||
|
||||
localUtils.API.checkResponse(
|
||||
jsonResponse.posts[0],
|
||||
'post',
|
||||
null,
|
||||
null,
|
||||
['mobiledoc', 'id', 'title', 'html']
|
||||
);
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('combined fields, formats, include and non existing', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html,plaintext&fields=id,title,primary_tag,doesnotexist&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']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
localUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(13);
|
||||
|
||||
localUtils.API.checkResponse(
|
||||
jsonResponse.posts[0],
|
||||
'post',
|
||||
null,
|
||||
null,
|
||||
['mobiledoc', 'plaintext', 'id', 'title', 'html', 'authors', 'tags', 'primary_tag']
|
||||
);
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
|
||||
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']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
'context',
|
||||
'type',
|
||||
'details',
|
||||
'property',
|
||||
'help',
|
||||
'code',
|
||||
'id'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Add', function () {
|
||||
it('adds default title when it is missing', function () {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('posts/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
title: ''
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(201)
|
||||
.then((res) => {
|
||||
should.exist(res.body.posts);
|
||||
should.exist(res.body.posts[0].title);
|
||||
res.body.posts[0].title.should.equal('(Untitled)');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edit', function () {
|
||||
it('published_at = null', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
published_at: null,
|
||||
updated_at: res.body.posts[0].updated_at
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
// @NOTE: if you set published_at to null and the post is published, we set it to NOW in model layer
|
||||
should.exist(res.headers['x-cache-invalidate']);
|
||||
should.exist(res.body.posts);
|
||||
should.exist(res.body.posts[0].published_at);
|
||||
});
|
||||
});
|
||||
|
||||
it('html to plaintext', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/?source=html&formats=html,plaintext'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
html: '<p>HTML Ipsum presents</p>',
|
||||
updated_at: res.body.posts[0].updated_at
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
return models.Post.findOne({
|
||||
id: res.body.posts[0].id
|
||||
}, testUtils.context.internal);
|
||||
})
|
||||
.then((model) => {
|
||||
model.get('plaintext').should.equal('HTML Ipsum presents');
|
||||
});
|
||||
});
|
||||
|
||||
it('canonical_url', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
canonical_url: `/canonical/url`,
|
||||
updated_at: res.body.posts[0].updated_at
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
should.exist(res.body.posts);
|
||||
should.exist(res.body.posts[0].canonical_url);
|
||||
res.body.posts[0].canonical_url.should.equal(`${config.get('url')}/canonical/url`);
|
||||
});
|
||||
});
|
||||
|
||||
it('update dates & x_by', function () {
|
||||
const post = {
|
||||
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) => {
|
||||
// @NOTE: you cannot modify these fields above manually, that's why the resource won't change.
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
return models.Post.findOne({
|
||||
id: res.body.posts[0].id
|
||||
}, testUtils.context.internal);
|
||||
})
|
||||
.then((model) => {
|
||||
// We expect that the changed properties aren't changed, they are still the same than before.
|
||||
model.get('created_at').toISOString().should.not.eql(post.created_at);
|
||||
model.get('updated_by').should.not.eql(post.updated_by);
|
||||
model.get('created_by').should.not.eql(post.created_by);
|
||||
|
||||
// `updated_at` is automatically set, but it's not the date we send to override.
|
||||
model.get('updated_at').toISOString().should.not.eql(post.updated_at);
|
||||
});
|
||||
});
|
||||
|
||||
it('Can change scheduled post', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[7].id}/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.body.posts[0].status.should.eql('scheduled');
|
||||
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[7].id + '/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
title: 'change scheduled post',
|
||||
updated_at: res.body.posts[0].updated_at
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
should.exist(res.headers['x-cache-invalidate']);
|
||||
});
|
||||
});
|
||||
|
||||
it('trims title', function () {
|
||||
const untrimmedTitle = ' test trimmed update title ';
|
||||
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
title: untrimmedTitle,
|
||||
updated_at: res.body.posts[0].updated_at
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
should.exist(res.body.posts);
|
||||
should.exist(res.body.posts[0].title);
|
||||
res.body.posts[0].title.should.equal(untrimmedTitle.trim());
|
||||
});
|
||||
});
|
||||
|
||||
it('strips invisible unicode from slug', function () {
|
||||
const slug = 'this-is\u0008-invisible';
|
||||
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
slug: slug,
|
||||
updated_at: res.body.posts[0].updated_at
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
should.exist(res.body.posts);
|
||||
should.exist(res.body.posts[0].slug);
|
||||
res.body.posts[0].slug.should.equal('this-is-invisible');
|
||||
});
|
||||
});
|
||||
|
||||
it('changes to post_meta fields triggers a cache invalidation', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
meta_title: 'changed meta title',
|
||||
updated_at: res.body.posts[0].updated_at
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
should.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
should.exist(res.body.posts);
|
||||
should.equal(res.body.posts[0].meta_title, 'changed meta title');
|
||||
});
|
||||
});
|
||||
|
||||
it('saving post with no modbiledoc content doesn\t trigger cache invalidation', function () {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('posts/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
title: 'Has a title by no other content',
|
||||
status: 'published'
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(201)
|
||||
.then((res) => {
|
||||
should.exist(res.body.posts);
|
||||
should.exist(res.body.posts[0].title);
|
||||
res.body.posts[0].title.should.equal('Has a title by no other content');
|
||||
should.equal(res.body.posts[0].html, undefined);
|
||||
should.equal(res.body.posts[0].plaintext, undefined);
|
||||
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery(`posts/${res.body.posts[0].id}/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
posts: [{
|
||||
title: res.body.posts[0].title,
|
||||
mobilecdoc: res.body.posts[0].mobilecdoc,
|
||||
updated_at: res.body.posts[0].updated_at
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
should.exist(res.body.posts);
|
||||
res.body.posts[0].title.should.equal('Has a title by no other content');
|
||||
should.equal(res.body.posts[0].html, undefined);
|
||||
should.equal(res.body.posts[0].plaintext, undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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',
|
||||
'context',
|
||||
'type',
|
||||
'details',
|
||||
'property',
|
||||
'help',
|
||||
'code',
|
||||
'id'
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,383 +0,0 @@
|
|||
const should = require('should');
|
||||
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('../../../../../core/shared/config');
|
||||
|
||||
const ghost = testUtils.startGhost;
|
||||
let request;
|
||||
|
||||
describe('Redirects API', function () {
|
||||
let originalContentPath;
|
||||
|
||||
before(function () {
|
||||
return ghost({redirectsFile: true})
|
||||
.then(() => {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(() => {
|
||||
return localUtils.doAuth(request);
|
||||
})
|
||||
.then(() => {
|
||||
originalContentPath = configUtils.config.get('paths:contentPath');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Download', function () {
|
||||
afterEach(function () {
|
||||
configUtils.config.set('paths:contentPath', originalContentPath);
|
||||
});
|
||||
|
||||
it('file does not exist', function () {
|
||||
// Just set any content folder, which does not contain a redirects file.
|
||||
configUtils.set('paths:contentPath', path.join(__dirname, '../../../utils/fixtures/data'));
|
||||
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.headers['content-disposition'].should.eql('Attachment; filename="redirects.json"');
|
||||
res.headers['content-type'].should.eql('application/json; charset=utf-8');
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
should.deepEqual(res.body, []);
|
||||
});
|
||||
});
|
||||
|
||||
it('file exists', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect('Content-Disposition', 'Attachment; filename="redirects.json"')
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.headers['content-disposition'].should.eql('Attachment; filename="redirects.json"');
|
||||
res.headers['content-type'].should.eql('application/json; charset=utf-8');
|
||||
|
||||
should.deepEqual(res.body, require('../../../../utils/fixtures/data/redirects.json'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Download yaml', function () {
|
||||
beforeEach(function () {
|
||||
testUtils.setupRedirectsFile(config.get('paths:contentPath'), '.yaml');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
testUtils.setupRedirectsFile(config.get('paths:contentPath'), '.json');
|
||||
});
|
||||
|
||||
// 'file does not exist' doesn't have to be tested because it always returns .json file.
|
||||
|
||||
it('file exists', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /text\/html/)
|
||||
.expect('Content-Disposition', 'Attachment; filename="redirects.yaml"')
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.headers['content-disposition'].should.eql('Attachment; filename="redirects.yaml"');
|
||||
res.headers['content-type'].should.eql('text/html; charset=utf-8');
|
||||
|
||||
should.deepEqual(res.text, fs.readFileSync(path.join(__dirname, '../../../../utils/fixtures/data/redirects.yaml')).toString());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Upload', function () {
|
||||
describe('Error cases', function () {
|
||||
it('syntax error', function () {
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects.json'), 'something');
|
||||
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects.json'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it('wrong format: no array', function () {
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects.json'), JSON.stringify({
|
||||
from: 'c',
|
||||
to: 'd'
|
||||
}));
|
||||
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects.json'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(422);
|
||||
});
|
||||
|
||||
it('wrong format: no from/to', function () {
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects.json'), JSON.stringify([{to: 'd'}]));
|
||||
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects.json'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(422);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Ensure re-registering redirects works', function () {
|
||||
const startGhost = (options) => {
|
||||
return ghost(options)
|
||||
.then(() => {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(() => {
|
||||
return localUtils.doAuth(request);
|
||||
});
|
||||
};
|
||||
|
||||
it('no redirects file exists', function () {
|
||||
return startGhost({redirectsFile: false, forceStart: true})
|
||||
.then(() => {
|
||||
return request
|
||||
.get('/my-old-blog-post/')
|
||||
.expect(404);
|
||||
})
|
||||
.then(() => {
|
||||
// Provide a redirects file in the root directory of the content test folder
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects-init.json'), JSON.stringify([{
|
||||
from: 'k',
|
||||
to: 'l'
|
||||
}]));
|
||||
})
|
||||
.then(() => {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects-init.json'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
res.headers['x-cache-invalidate'].should.eql('/*');
|
||||
|
||||
return request
|
||||
.get('/k/')
|
||||
.expect(302);
|
||||
})
|
||||
.then((response) => {
|
||||
response.headers.location.should.eql('/l');
|
||||
|
||||
const dataFiles = fs.readdirSync(config.getContentPath('data'));
|
||||
dataFiles.join(',').match(/(redirects)/g).length.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('override', function () {
|
||||
return startGhost({forceStart: true})
|
||||
.then(() => {
|
||||
return request
|
||||
.get('/my-old-blog-post/')
|
||||
.expect(301);
|
||||
})
|
||||
.then((response) => {
|
||||
response.headers.location.should.eql('/revamped-url/');
|
||||
})
|
||||
.then(() => {
|
||||
// Provide a second redirects file in the root directory of the content test folder
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects.json'), JSON.stringify([{
|
||||
from: 'c',
|
||||
to: 'd'
|
||||
}]));
|
||||
})
|
||||
.then(() => {
|
||||
// Override redirects file
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects.json'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
res.headers['x-cache-invalidate'].should.eql('/*');
|
||||
|
||||
return request
|
||||
.get('/my-old-blog-post/')
|
||||
.expect(404);
|
||||
})
|
||||
.then(() => {
|
||||
return request
|
||||
.get('/c/')
|
||||
.expect(302);
|
||||
})
|
||||
.then((response) => {
|
||||
response.headers.location.should.eql('/d');
|
||||
|
||||
// check backup of redirects files
|
||||
const dataFiles = fs.readdirSync(config.getContentPath('data'));
|
||||
dataFiles.join(',').match(/(redirects)/g).length.should.eql(2);
|
||||
|
||||
// Provide another redirects file in the root directory of the content test folder
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects-something.json'), JSON.stringify([{
|
||||
from: 'e',
|
||||
to: 'b'
|
||||
}]));
|
||||
})
|
||||
.then(() => {
|
||||
// the backup is in the format HH:mm:ss, we have to wait minimum a second
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, 1100);
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
// Override redirects file again and ensure the backup file works twice
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects-something.json'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(200);
|
||||
})
|
||||
.then(() => {
|
||||
const dataFiles = fs.readdirSync(config.getContentPath('data'));
|
||||
dataFiles.join(',').match(/(redirects)/g).length.should.eql(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Upload yaml', function () {
|
||||
// No error cases here because there are no easy syntax pitfalls in the yaml format.
|
||||
|
||||
describe('Ensure re-registering redirects works', function () {
|
||||
const startGhost = (options) => {
|
||||
return ghost(options)
|
||||
.then(() => {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(() => {
|
||||
return localUtils.doAuth(request);
|
||||
});
|
||||
};
|
||||
|
||||
it('no redirects file exists', function () {
|
||||
return startGhost({redirectsFile: false, forceStart: true})
|
||||
.then(() => {
|
||||
return request
|
||||
.get('/my-old-blog-post/')
|
||||
.expect(404);
|
||||
})
|
||||
.then(() => {
|
||||
// Provide a redirects file in the root directory of the content test folder
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects-init.yaml'), '302:\n k: l');
|
||||
})
|
||||
.then(() => {
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects-init.yaml'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
res.headers['x-cache-invalidate'].should.eql('/*');
|
||||
|
||||
return request
|
||||
.get('/k/')
|
||||
.expect(302);
|
||||
})
|
||||
.then((response) => {
|
||||
response.headers.location.should.eql('/l');
|
||||
|
||||
const dataFiles = fs.readdirSync(config.getContentPath('data'));
|
||||
dataFiles.join(',').match(/(redirects)/g).length.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('override', function () {
|
||||
// We want to test if we can override old redirects.json with new redirects.yaml
|
||||
// That's why we start with .json.
|
||||
return startGhost({forceStart: true, redirectsFileExt: '.json'})
|
||||
.then(() => {
|
||||
return request
|
||||
.get('/my-old-blog-post/')
|
||||
.expect(301);
|
||||
})
|
||||
.then((response) => {
|
||||
response.headers.location.should.eql('/revamped-url/');
|
||||
})
|
||||
.then(() => {
|
||||
// Provide a second redirects file in the root directory of the content test folder
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects.yaml'), '302:\n c: d');
|
||||
})
|
||||
.then(() => {
|
||||
// Override redirects file
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects.yaml'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(200);
|
||||
})
|
||||
.then((res) => {
|
||||
res.headers['x-cache-invalidate'].should.eql('/*');
|
||||
|
||||
return request
|
||||
.get('/my-old-blog-post/')
|
||||
.expect(404);
|
||||
})
|
||||
.then(() => {
|
||||
return request
|
||||
.get('/c/')
|
||||
.expect(302);
|
||||
})
|
||||
.then((response) => {
|
||||
response.headers.location.should.eql('/d');
|
||||
|
||||
// check backup of redirects files
|
||||
const dataFiles = fs.readdirSync(config.getContentPath('data'));
|
||||
dataFiles.join(',').match(/(redirects)/g).length.should.eql(2);
|
||||
|
||||
// Provide another redirects file in the root directory of the content test folder
|
||||
fs.writeFileSync(path.join(config.get('paths:contentPath'), 'redirects-something.json'), JSON.stringify([{
|
||||
from: 'e',
|
||||
to: 'b'
|
||||
}]));
|
||||
})
|
||||
.then(() => {
|
||||
// the backup is in the format HH:mm:ss, we have to wait minimum a second
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, 1100);
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
// Override redirects file again and ensure the backup file works twice
|
||||
return request
|
||||
.post(localUtils.API.getApiQuery('redirects/json/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.attach('redirects', path.join(config.get('paths:contentPath'), 'redirects-something.json'))
|
||||
.expect('Content-Type', /application\/json/)
|
||||
.expect(200);
|
||||
})
|
||||
.then(() => {
|
||||
return request
|
||||
.get('/e/')
|
||||
.expect(302);
|
||||
})
|
||||
.then((response) => {
|
||||
response.headers.location.should.eql('/b');
|
||||
|
||||
const dataFiles = fs.readdirSync(config.getContentPath('data'));
|
||||
dataFiles.join(',').match(/(redirects)/g).length.should.eql(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,184 +0,0 @@
|
|||
const _ = require('lodash');
|
||||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const Promise = require('bluebird');
|
||||
const sinon = require('sinon');
|
||||
const moment = require('moment-timezone');
|
||||
const SchedulingDefault = require('../../../../../core/server/adapters/scheduling/SchedulingDefault');
|
||||
const models = require('../../../../../core/server/models/index');
|
||||
const config = require('../../../../../core/shared/config/index');
|
||||
const testUtils = require('../../../../utils/index');
|
||||
const localUtils = require('./utils');
|
||||
|
||||
const ghost = testUtils.startGhost;
|
||||
|
||||
// TODO: Fix with token in URL
|
||||
describe.skip('v3 Schedules API', function () {
|
||||
const resources = [];
|
||||
let request;
|
||||
|
||||
before(function () {
|
||||
models.init();
|
||||
|
||||
// @NOTE: mock the post scheduler, otherwise it will auto publish the post
|
||||
sinon.stub(SchedulingDefault.prototype, '_pingUrl').resolves();
|
||||
});
|
||||
|
||||
after(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(() => {
|
||||
request = supertest.agent(config.get('url'));
|
||||
});
|
||||
});
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function () {
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
published_at: moment().add(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'first'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
published_at: moment().subtract(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'second'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
published_at: moment().add(10, 'minute').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'third'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
published_at: moment().subtract(10, 'minute').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'fourth'
|
||||
}));
|
||||
|
||||
resources.push(testUtils.DataGenerator.forKnex.createPost({
|
||||
created_by: testUtils.existingData.users[0].id,
|
||||
author_id: testUtils.existingData.users[0].id,
|
||||
published_by: testUtils.existingData.users[0].id,
|
||||
published_at: moment().add(30, 'seconds').toDate(),
|
||||
status: 'scheduled',
|
||||
slug: 'fifth',
|
||||
type: 'page'
|
||||
}));
|
||||
|
||||
return Promise.mapSeries(resources, function (post) {
|
||||
return models.Post.add(post, {context: {internal: true}});
|
||||
}).then(function (result) {
|
||||
result.length.should.eql(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('publish', function () {
|
||||
let schedulerKey;
|
||||
|
||||
before(function () {
|
||||
schedulerKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-scheduler'}});
|
||||
});
|
||||
|
||||
it('publishes posts', function () {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery(`schedules/posts/${resources[0].id}/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', schedulerKey)}`)
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
should.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
jsonResponse.posts[0].id.should.eql(resources[0].id);
|
||||
jsonResponse.posts[0].status.should.eql('published');
|
||||
});
|
||||
});
|
||||
|
||||
it('publishes page', function () {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery(`schedules/pages/${resources[4].id}/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', schedulerKey)}`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
should.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
jsonResponse.pages[0].id.should.eql(resources[4].id);
|
||||
jsonResponse.pages[0].status.should.eql('published');
|
||||
});
|
||||
});
|
||||
|
||||
it('no access', function () {
|
||||
const zapierKey = _.find(testUtils.existingData.apiKeys, {integration: {slug: 'ghost-backup'}});
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery(`schedules/posts/${resources[0].id}/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', zapierKey)}`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it('should fail with invalid resource type', function () {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery(`schedules/this_is_invalid/${resources[0].id}/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', schedulerKey)}`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(422);
|
||||
});
|
||||
|
||||
it('published_at is x seconds in past, but still in tolerance', function () {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery(`schedules/posts/${resources[1].id}/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', schedulerKey)}`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('not found', function () {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery(`schedules/posts/${resources[2].id}/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', schedulerKey)}`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('force publish', function () {
|
||||
return request
|
||||
.put(localUtils.API.getApiQuery(`schedules/posts/${resources[3].id}/`))
|
||||
.send({
|
||||
force: true
|
||||
})
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', schedulerKey)}`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,636 +0,0 @@
|
|||
const _ = require('lodash');
|
||||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
const testUtils = require('../../../../utils');
|
||||
const localUtils = require('./utils');
|
||||
const ghost = testUtils.startGhost;
|
||||
|
||||
// NOTE: in future iterations these fields should be fetched from a central module.
|
||||
// Have put a list as is here for the lack of better place for it.
|
||||
const defaultSettingsKeys = [
|
||||
'title',
|
||||
'description',
|
||||
'logo',
|
||||
'cover_image',
|
||||
'icon',
|
||||
'lang',
|
||||
'timezone',
|
||||
'codeinjection_head',
|
||||
'codeinjection_foot',
|
||||
'facebook',
|
||||
'twitter',
|
||||
'navigation',
|
||||
'secondary_navigation',
|
||||
'meta_title',
|
||||
'meta_description',
|
||||
'og_image',
|
||||
'og_title',
|
||||
'og_description',
|
||||
'twitter_image',
|
||||
'twitter_title',
|
||||
'twitter_description',
|
||||
'active_theme',
|
||||
'is_private',
|
||||
'password',
|
||||
'public_hash',
|
||||
'default_content_visibility',
|
||||
'members_allow_free_signup',
|
||||
'members_from_address',
|
||||
'members_support_address',
|
||||
'members_reply_address',
|
||||
'members_free_signup_redirect',
|
||||
'members_paid_signup_redirect',
|
||||
'stripe_product_name',
|
||||
'stripe_plans',
|
||||
'stripe_secret_key',
|
||||
'stripe_publishable_key',
|
||||
'stripe_connect_secret_key',
|
||||
'stripe_connect_publishable_key',
|
||||
'stripe_connect_account_id',
|
||||
'stripe_connect_display_name',
|
||||
'stripe_connect_livemode',
|
||||
'portal_name',
|
||||
'portal_button',
|
||||
'portal_plans',
|
||||
'portal_button_style',
|
||||
'portal_button_icon',
|
||||
'portal_button_signup_text',
|
||||
'mailgun_api_key',
|
||||
'mailgun_domain',
|
||||
'mailgun_base_url',
|
||||
'email_track_opens',
|
||||
'amp',
|
||||
'amp_gtag_id',
|
||||
'labs',
|
||||
'slack',
|
||||
'unsplash',
|
||||
'shared_views',
|
||||
'active_timezone',
|
||||
'default_locale',
|
||||
'accent_color',
|
||||
'newsletter_show_badge',
|
||||
'newsletter_show_header',
|
||||
'newsletter_body_font_category',
|
||||
'newsletter_footer_content'
|
||||
];
|
||||
|
||||
describe('Settings API (v3)', function () {
|
||||
let ghostServer;
|
||||
let request;
|
||||
|
||||
describe('As Owner', function () {
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return localUtils.doAuth(request);
|
||||
});
|
||||
});
|
||||
|
||||
it('Can request all settings', function () {
|
||||
return request.get(localUtils.API.getApiQuery(`settings/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.settings);
|
||||
should.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.settings.should.be.an.Object();
|
||||
const settings = jsonResponse.settings;
|
||||
|
||||
settings.map(s => s.key).sort().should.deepEqual(defaultSettingsKeys.sort());
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse, 'settings');
|
||||
});
|
||||
});
|
||||
|
||||
it('Can request settings by type', function () {
|
||||
return request.get(localUtils.API.getApiQuery(`settings/?type=theme`))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.settings);
|
||||
should.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.settings.should.be.an.Object();
|
||||
const settings = jsonResponse.settings;
|
||||
|
||||
Object.keys(settings).length.should.equal(1);
|
||||
settings[0].key.should.equal('active_theme');
|
||||
settings[0].value.should.equal('casper');
|
||||
settings[0].type.should.equal('theme');
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse, 'settings');
|
||||
});
|
||||
});
|
||||
|
||||
it('Can\'t 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 read deprecated default_locale', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/default_locale/'))
|
||||
.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.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
jsonResponse.settings[0].key.should.eql('default_locale');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can edit deprecated default_locale setting', function () {
|
||||
return request.get(localUtils.API.getApiQuery('settings/default_locale/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.then(function (res) {
|
||||
let jsonResponse = res.body;
|
||||
const newValue = 'new value';
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
jsonResponse.settings = [{key: 'default_locale', value: 'ua'}];
|
||||
|
||||
return jsonResponse;
|
||||
})
|
||||
.then((editedSetting) => {
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(editedSetting)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then(function (res) {
|
||||
should.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
jsonResponse.settings[0].key.should.eql('default_locale');
|
||||
jsonResponse.settings[0].value.should.eql('ua');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read timezone', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/timezone/'))
|
||||
.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.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
jsonResponse.settings[0].key.should.eql('timezone');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read active_timezone', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/active_timezone/'))
|
||||
.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.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
jsonResponse.settings[0].key.should.eql('active_timezone');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read deprecated active_timezone', function (done) {
|
||||
request.get(localUtils.API.getApiQuery('settings/active_timezone/'))
|
||||
.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.settings);
|
||||
|
||||
jsonResponse.settings.length.should.eql(1);
|
||||
|
||||
testUtils.API.checkResponseValue(jsonResponse.settings[0], ['id', 'group', 'key', 'value', 'type', 'flags', 'created_at', 'updated_at']);
|
||||
jsonResponse.settings[0].key.should.eql('active_timezone');
|
||||
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']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
'context',
|
||||
'type',
|
||||
'details',
|
||||
'property',
|
||||
'help',
|
||||
'code',
|
||||
'id'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can toggle member setting', function () {
|
||||
return request.get(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.then(function (res) {
|
||||
const jsonResponse = res.body;
|
||||
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'labs',
|
||||
value: '{"subscribers":false,"members":false}'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then(function ({body, headers}) {
|
||||
const putBody = body;
|
||||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings[0].key.should.eql('labs');
|
||||
putBody.settings[0].value.should.eql(JSON.stringify({subscribers: false, members: false}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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 () {
|
||||
return 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)
|
||||
.then(function (res) {
|
||||
let jsonResponse = res.body;
|
||||
const newValue = 'new value';
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
jsonResponse.settings = [{key: 'testvalue', value: newValue}];
|
||||
|
||||
return 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)
|
||||
.then(function ({body, headers}) {
|
||||
jsonResponse = body;
|
||||
should.not.exist(headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
'context',
|
||||
'type',
|
||||
'details',
|
||||
'property',
|
||||
'help',
|
||||
'code',
|
||||
'id'
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Will transform "1"', function () {
|
||||
return request.get(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.then(function (res) {
|
||||
const jsonResponse = res.body;
|
||||
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'is_private',
|
||||
value: '1'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then(function ({body, headers}) {
|
||||
const putBody = body;
|
||||
headers['x-cache-invalidate'].should.eql('/*');
|
||||
should.exist(putBody);
|
||||
|
||||
putBody.settings[0].key.should.eql('is_private');
|
||||
putBody.settings[0].value.should.eql(true);
|
||||
|
||||
localUtils.API.checkResponse(putBody, 'settings');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Admin', function () {
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
// create admin
|
||||
return testUtils.createUser({
|
||||
user: testUtils.DataGenerator.forKnex.createUser({email: 'admin+1@ghost.org'}),
|
||||
role: testUtils.DataGenerator.Content.roles[0].name
|
||||
});
|
||||
})
|
||||
.then(function (admin) {
|
||||
request.user = admin;
|
||||
|
||||
// by default we login with the owner
|
||||
return localUtils.doAuth(request);
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot toggle member setting', function (done) {
|
||||
const settingToChange = {
|
||||
settings: [
|
||||
{
|
||||
key: 'labs',
|
||||
value: '{"subscribers":false,"members":true}'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(settingToChange)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(403)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Editor', function () {
|
||||
let editor;
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be able to edit settings', function () {
|
||||
return 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)
|
||||
.then(function (res) {
|
||||
let jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
jsonResponse.settings = [{key: 'visibility', value: 'public'}];
|
||||
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(jsonResponse)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(403)
|
||||
.then(function ({body, headers}) {
|
||||
jsonResponse = body;
|
||||
should.not.exist(headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
'context',
|
||||
'type',
|
||||
'details',
|
||||
'property',
|
||||
'help',
|
||||
'code',
|
||||
'id'
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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 (author) {
|
||||
request.user = author;
|
||||
|
||||
// by default we login with the owner
|
||||
return localUtils.doAuth(request);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be able to edit settings', function () {
|
||||
return 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)
|
||||
.then(function (res) {
|
||||
let jsonResponse = res.body;
|
||||
const newValue = 'new value';
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.settings);
|
||||
jsonResponse.settings = [{key: 'visibility', value: 'public'}];
|
||||
|
||||
return request.put(localUtils.API.getApiQuery('settings/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send(jsonResponse)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(403)
|
||||
.then(function ({body, headers}) {
|
||||
jsonResponse = body;
|
||||
should.not.exist(headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
'context',
|
||||
'type',
|
||||
'details',
|
||||
'property',
|
||||
'help',
|
||||
'code',
|
||||
'id'
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,48 +0,0 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const sinon = require('sinon');
|
||||
const testUtils = require('../../../../utils');
|
||||
const localUtils = require('./utils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
const {events} = require('../../../../../core/server/lib/common');
|
||||
const ghost = testUtils.startGhost;
|
||||
|
||||
let request;
|
||||
|
||||
describe('Slack 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 () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('Can post slack test', function (done) {
|
||||
const eventSpy = sinon.spy(events, 'emit');
|
||||
request.post(localUtils.API.getApiQuery('slack/test/'))
|
||||
.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);
|
||||
eventSpy.calledWith('slack.test').should.be.true();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,295 +0,0 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const ObjectId = require('bson-objectid');
|
||||
const testUtils = require('../../../../utils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
const localUtils = require('./utils');
|
||||
const ghost = testUtils.startGhost;
|
||||
let request;
|
||||
|
||||
describe('User API', function () {
|
||||
let editor;
|
||||
let author;
|
||||
let ghostServer;
|
||||
let otherAuthor;
|
||||
let 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'}),
|
||||
role: testUtils.DataGenerator.Content.roles[2].name
|
||||
});
|
||||
})
|
||||
.then(function (_user) {
|
||||
otherAuthor = _user;
|
||||
|
||||
// create admin user
|
||||
return testUtils.createUser({
|
||||
user: testUtils.DataGenerator.forKnex.createUser({email: 'test+admin@ghost.org', slug: 'owner'}),
|
||||
role: testUtils.DataGenerator.Content.roles[3].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']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
'context',
|
||||
'type',
|
||||
'details',
|
||||
'property',
|
||||
'help',
|
||||
'code',
|
||||
'id'
|
||||
]);
|
||||
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']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.errors);
|
||||
testUtils.API.checkResponseValue(jsonResponse.errors[0], [
|
||||
'message',
|
||||
'context',
|
||||
'type',
|
||||
'details',
|
||||
'property',
|
||||
'help',
|
||||
'code',
|
||||
'id'
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edit', function () {
|
||||
it('can change the other users password', function (done) {
|
||||
request.put(localUtils.API.getApiQuery('users/password/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
password: [{
|
||||
newPassword: 'superSecure',
|
||||
ne2Password: 'superSecure',
|
||||
user_id: otherAuthor.id
|
||||
}]
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,124 +0,0 @@
|
|||
const url = require('url');
|
||||
const _ = require('lodash');
|
||||
const testUtils = require('../../../../utils');
|
||||
const schema = require('../../../../../core/server/data/schema').tables;
|
||||
const API_URL = '/ghost/api/v3/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 mobiledoc
|
||||
.without('html', 'plaintext')
|
||||
.without('visibility')
|
||||
.without('locale')
|
||||
.without('page')
|
||||
.without('author_id', 'author')
|
||||
// always returns computed properties
|
||||
// primary_tag and primary_author properties are included
|
||||
// only because authors and tags are always included
|
||||
.concat('url', 'primary_tag', 'primary_author', 'excerpt')
|
||||
.concat('authors', 'tags')
|
||||
// returns meta fields from `posts_meta` schema
|
||||
.concat(
|
||||
..._(schema.posts_meta).keys().without('post_id', 'id')
|
||||
)
|
||||
.concat('send_email_when_published')
|
||||
,
|
||||
user: _(schema.users)
|
||||
.keys()
|
||||
.without('visibility')
|
||||
.without('password')
|
||||
.without('locale')
|
||||
.concat('url')
|
||||
,
|
||||
tag: _(schema.tags)
|
||||
.keys()
|
||||
// unused field
|
||||
.without('parent_id')
|
||||
,
|
||||
setting: _(schema.settings)
|
||||
.keys()
|
||||
,
|
||||
subscriber: _(schema.subscribers)
|
||||
.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()
|
||||
};
|
||||
|
||||
_.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, key) {
|
||||
const jwt = require('jsonwebtoken');
|
||||
key = key || testUtils.DataGenerator.Content.api_keys[0];
|
||||
|
||||
const JWT_OPTIONS = {
|
||||
keyid: key.id,
|
||||
algorithm: 'HS256',
|
||||
expiresIn: '5m',
|
||||
audience: endpoint
|
||||
};
|
||||
|
||||
return jwt.sign(
|
||||
{},
|
||||
Buffer.from(key.secret, 'hex'),
|
||||
JWT_OPTIONS
|
||||
);
|
||||
}
|
||||
};
|
|
@ -1,136 +0,0 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const testUtils = require('../../../../utils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
const localUtils = require('./utils');
|
||||
|
||||
const ghost = testUtils.startGhost;
|
||||
|
||||
describe('Webhooks API (v3)', function () {
|
||||
let request;
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return localUtils.doAuth(request, 'api_keys', 'webhooks');
|
||||
});
|
||||
});
|
||||
|
||||
it('Can create a webhook using integration', function () {
|
||||
let webhookData = {
|
||||
event: 'test.create',
|
||||
target_url: 'http://example.com/webhooks/test/extra/v3',
|
||||
integration_id: 'ignore_me',
|
||||
name: 'test',
|
||||
secret: 'thisissecret',
|
||||
api_version: 'v3'
|
||||
};
|
||||
|
||||
return request.post(localUtils.API.getApiQuery('webhooks/'))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', testUtils.DataGenerator.Content.api_keys[0])}`)
|
||||
.send({webhooks: [webhookData]})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(201)
|
||||
.then((res) => {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.webhooks);
|
||||
should.exist(jsonResponse.webhooks[0].event);
|
||||
should.exist(jsonResponse.webhooks[0].target_url);
|
||||
|
||||
jsonResponse.webhooks[0].event.should.eql('test.create');
|
||||
jsonResponse.webhooks[0].target_url.should.eql('http://example.com/webhooks/test/extra/v3');
|
||||
jsonResponse.webhooks[0].integration_id.should.eql(testUtils.DataGenerator.Content.api_keys[0].integration_id);
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse.webhooks[0], 'webhook');
|
||||
});
|
||||
});
|
||||
|
||||
it('Integration cannot edit or delete other integration\'s webhook', function () {
|
||||
let createdIntegration;
|
||||
let createdWebhook;
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
return request.post(localUtils.API.getApiQuery('integrations/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
integrations: [{
|
||||
name: 'Rubbish Integration Name'
|
||||
}]
|
||||
})
|
||||
.expect(201)
|
||||
.then(({body}) => {
|
||||
[createdIntegration] = body.integrations;
|
||||
|
||||
return request.post(localUtils.API.getApiQuery('webhooks/'))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({
|
||||
webhooks: [{
|
||||
name: 'Testing',
|
||||
event: 'site.changed',
|
||||
target_url: 'https://example.com/rebuild',
|
||||
integration_id: createdIntegration.id
|
||||
}]
|
||||
})
|
||||
.expect(201);
|
||||
});
|
||||
})
|
||||
.then(({body}) => {
|
||||
[createdWebhook] = body.webhooks;
|
||||
|
||||
return request.put(localUtils.API.getApiQuery(`webhooks/${createdWebhook.id}/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', testUtils.DataGenerator.Content.api_keys[0])}`)
|
||||
.send({
|
||||
webhooks: [{
|
||||
name: 'Edit Test',
|
||||
event: 'subscriber.added',
|
||||
target_url: 'https://example.com/new-subscriber'
|
||||
}]
|
||||
})
|
||||
.expect(403);
|
||||
})
|
||||
.then(() => {
|
||||
return request.del(localUtils.API.getApiQuery(`webhooks/${createdWebhook.id}/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', testUtils.DataGenerator.Content.api_keys[0])}`)
|
||||
.expect(403);
|
||||
});
|
||||
});
|
||||
|
||||
it('Integration editing non-existing webhook returns 404', function () {
|
||||
return request.put(localUtils.API.getApiQuery(`webhooks/5f27d0287c75da744d8615da/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', testUtils.DataGenerator.Content.api_keys[0])}`)
|
||||
.send({
|
||||
webhooks: [{
|
||||
name: 'Edit Test'
|
||||
}]
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('Integration deleting non-existing webhook returns 404', function () {
|
||||
return request.delete(localUtils.API.getApiQuery(`webhooks/5f27d0287c75da744d8615db/`))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', testUtils.DataGenerator.Content.api_keys[0])}`)
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('Cannot edit webhooks using content api keys', function () {
|
||||
let webhookData = {
|
||||
event: 'post.create',
|
||||
target_url: 'http://example.com/webhooks/test/extra/2'
|
||||
};
|
||||
|
||||
return request.post(localUtils.API.getApiQuery('webhooks/'))
|
||||
.set('Authorization', `Ghost ${localUtils.getValidAdminToken('/v3/admin/', testUtils.DataGenerator.Content.api_keys[1])}`)
|
||||
.send({webhooks: [webhookData]})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(401);
|
||||
});
|
||||
});
|
|
@ -1,41 +0,0 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const localUtils = require('./utils');
|
||||
const testUtils = require('../../../../utils');
|
||||
const configUtils = require('../../../../utils/configUtils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
|
||||
const ghost = testUtils.startGhost;
|
||||
|
||||
describe('Authors Content API', function () {
|
||||
const validKey = localUtils.getValidKey();
|
||||
let request;
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function (_ghostServer) {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.initFixtures('owner:post', 'users:no-owner', 'user:inactive', 'posts', 'api_keys');
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
configUtils.restore();
|
||||
});
|
||||
|
||||
it('can read authors with fields', function () {
|
||||
return request.get(localUtils.API.getApiQuery(`authors/1/?key=${validKey}&fields=name`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
// We don't expose any other attrs.
|
||||
localUtils.API.checkResponse(res.body.authors[0], 'author', null, null, ['id', 'name']);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,56 +0,0 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const testUtils = require('../../../../utils');
|
||||
const localUtils = require('./utils');
|
||||
const configUtils = require('../../../../utils/configUtils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
|
||||
const ghost = testUtils.startGhost;
|
||||
let request;
|
||||
|
||||
describe('api/v3/content/pages', function () {
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.initFixtures('users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys');
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
configUtils.restore();
|
||||
});
|
||||
|
||||
it('Can browse pages with page:false', function () {
|
||||
const key = localUtils.getValidKey();
|
||||
return request.get(localUtils.API.getApiQuery(`pages/?key=${key}&filter=page:false`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.headers.vary.should.eql('Accept-Encoding');
|
||||
should.exist(res.headers['access-control-allow-origin']);
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.pages);
|
||||
should.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.pages.should.have.length(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t read post', function () {
|
||||
const key = localUtils.getValidKey();
|
||||
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`pages/${testUtils.DataGenerator.Content.posts[0].id}/?key=${key}`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(404);
|
||||
});
|
||||
});
|
|
@ -1,377 +0,0 @@
|
|||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const moment = require('moment');
|
||||
const supertest = require('supertest');
|
||||
const _ = require('lodash');
|
||||
const labs = require('../../../../../core/server/services/labs');
|
||||
const testUtils = require('../../../../utils');
|
||||
const localUtils = require('./utils');
|
||||
const configUtils = require('../../../../utils/configUtils');
|
||||
const urlUtils = require('../../../../utils/urlUtils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
|
||||
const ghost = testUtils.startGhost;
|
||||
let request;
|
||||
|
||||
describe('api/v3/content/posts', function () {
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.initFixtures('users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys');
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
configUtils.restore();
|
||||
urlUtils.restore();
|
||||
});
|
||||
|
||||
const validKey = localUtils.getValidKey();
|
||||
|
||||
it('browse posts', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
res.headers.vary.should.eql('Accept-Encoding');
|
||||
should.exist(res.headers['access-control-allow-origin']);
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
localUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(11);
|
||||
localUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
|
||||
|
||||
// Default order 'published_at desc' check
|
||||
jsonResponse.posts[0].slug.should.eql('welcome');
|
||||
jsonResponse.posts[6].slug.should.eql('themes');
|
||||
|
||||
// check meta response for this test
|
||||
jsonResponse.meta.pagination.page.should.eql(1);
|
||||
jsonResponse.meta.pagination.limit.should.eql(15);
|
||||
jsonResponse.meta.pagination.pages.should.eql(1);
|
||||
jsonResponse.meta.pagination.total.should.eql(11);
|
||||
jsonResponse.meta.pagination.hasOwnProperty('next').should.be.true();
|
||||
jsonResponse.meta.pagination.hasOwnProperty('prev').should.be.true();
|
||||
should.not.exist(jsonResponse.meta.pagination.next);
|
||||
should.not.exist(jsonResponse.meta.pagination.prev);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('browse posts with related authors/tags also returns primary_author/primary_tag', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&include=authors,tags`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
res.headers.vary.should.eql('Accept-Encoding');
|
||||
should.exist(res.headers['access-control-allow-origin']);
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
localUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(11);
|
||||
localUtils.API.checkResponse(
|
||||
jsonResponse.posts[0],
|
||||
'post',
|
||||
['authors', 'tags', 'primary_tag', 'primary_author'],
|
||||
null
|
||||
);
|
||||
|
||||
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
|
||||
|
||||
// Default order 'published_at desc' check
|
||||
jsonResponse.posts[0].slug.should.eql('welcome');
|
||||
jsonResponse.posts[6].slug.should.eql('themes');
|
||||
|
||||
// check meta response for this test
|
||||
jsonResponse.meta.pagination.page.should.eql(1);
|
||||
jsonResponse.meta.pagination.limit.should.eql(15);
|
||||
jsonResponse.meta.pagination.pages.should.eql(1);
|
||||
jsonResponse.meta.pagination.total.should.eql(11);
|
||||
jsonResponse.meta.pagination.hasOwnProperty('next').should.be.true();
|
||||
jsonResponse.meta.pagination.hasOwnProperty('prev').should.be.true();
|
||||
should.not.exist(jsonResponse.meta.pagination.next);
|
||||
should.not.exist(jsonResponse.meta.pagination.prev);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('browse posts with basic page filter should not return pages', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=page:true`))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.posts);
|
||||
localUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
jsonResponse.posts.should.have.length(0);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('browse posts with basic page filter should not return pages', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=page:true,featured:true`))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
const jsonResponse = res.body;
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
should.exist(jsonResponse.posts);
|
||||
localUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
jsonResponse.posts.should.have.length(2);
|
||||
jsonResponse.posts.filter(p => (p.page === true)).should.have.length(0);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('browse posts with published and draft status, should not return drafts', function (done) {
|
||||
request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}&filter=status:published,status:draft`))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
const jsonResponse = res.body;
|
||||
|
||||
jsonResponse.posts.should.be.an.Array().with.lengthOf(11);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('ensure origin header on redirect is not getting lost', function (done) {
|
||||
// NOTE: force a redirect to the admin url
|
||||
configUtils.set('admin:url', 'http://localhost:9999');
|
||||
urlUtils.stubUrlUtilsFromConfig();
|
||||
|
||||
request.get(localUtils.API.getApiQuery(`posts?key=${validKey}`))
|
||||
.set('Origin', 'https://example.com')
|
||||
// 301 Redirects _should_ be cached
|
||||
.expect('Cache-Control', testUtils.cacheRules.year)
|
||||
.expect(301)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
res.headers.vary.should.eql('Accept, Accept-Encoding');
|
||||
res.headers.location.should.eql(`http://localhost:9999/ghost/api/v3/content/posts/?key=${validKey}`);
|
||||
should.exist(res.headers['access-control-allow-origin']);
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t read page', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[5].id}/?key=${validKey}`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('can read post with fields', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/?key=${validKey}&fields=title,slug`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
localUtils.API.checkResponse(res.body.posts[0], 'post', null, null, ['id', 'title', 'slug']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('content gating', function () {
|
||||
let publicPost;
|
||||
let membersPost;
|
||||
let paidPost;
|
||||
|
||||
before(function () {
|
||||
// NOTE: ideally this would be set through Admin API request not a stub
|
||||
sinon.stub(labs, 'isSet').withArgs('members').returns(true);
|
||||
});
|
||||
|
||||
before (function () {
|
||||
publicPost = testUtils.DataGenerator.forKnex.createPost({
|
||||
slug: 'free-to-see',
|
||||
visibility: 'public',
|
||||
published_at: moment().add(15, 'seconds').toDate() // here to ensure sorting is not modified
|
||||
});
|
||||
|
||||
membersPost = testUtils.DataGenerator.forKnex.createPost({
|
||||
slug: 'thou-shalt-not-be-seen',
|
||||
visibility: 'members',
|
||||
published_at: moment().add(45, 'seconds').toDate() // here to ensure sorting is not modified
|
||||
});
|
||||
|
||||
paidPost = testUtils.DataGenerator.forKnex.createPost({
|
||||
slug: 'thou-shalt-be-paid-for',
|
||||
visibility: 'paid',
|
||||
published_at: moment().add(30, 'seconds').toDate() // here to ensure sorting is not modified
|
||||
});
|
||||
|
||||
return testUtils.fixtures.insertPosts([
|
||||
publicPost,
|
||||
membersPost,
|
||||
paidPost
|
||||
]);
|
||||
});
|
||||
|
||||
it('public post fields are always visible', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${publicPost.id}/?key=${validKey}&fields=slug,html,plaintext&formats=html,plaintext`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
const post = jsonResponse.posts[0];
|
||||
|
||||
localUtils.API.checkResponse(post, 'post', null, null, ['id', 'slug', 'html', 'plaintext']);
|
||||
post.slug.should.eql('free-to-see');
|
||||
post.html.should.not.eql('');
|
||||
post.plaintext.should.not.eql('');
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot read members only post content', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/?key=${validKey}`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
const post = jsonResponse.posts[0];
|
||||
|
||||
localUtils.API.checkResponse(post, 'post', null, null);
|
||||
post.slug.should.eql('thou-shalt-not-be-seen');
|
||||
post.html.should.eql('');
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot read paid only post content', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${paidPost.id}/?key=${validKey}`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
const post = jsonResponse.posts[0];
|
||||
|
||||
localUtils.API.checkResponse(post, 'post', null, null);
|
||||
post.slug.should.eql('thou-shalt-be-paid-for');
|
||||
post.html.should.eql('');
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot read members only post plaintext', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`posts/${membersPost.id}/?key=${validKey}&formats=html,plaintext&fields=html,plaintext`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
const post = jsonResponse.posts[0];
|
||||
|
||||
localUtils.API.checkResponse(post, 'post', null, null, ['id', 'html', 'plaintext']);
|
||||
post.html.should.eql('');
|
||||
post.plaintext.should.eql('');
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot browse members only posts content', function () {
|
||||
return request.get(localUtils.API.getApiQuery(`posts/?key=${validKey}`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
res.headers.vary.should.eql('Accept-Encoding');
|
||||
should.exist(res.headers['access-control-allow-origin']);
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse.posts);
|
||||
localUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(14);
|
||||
localUtils.API.checkResponse(jsonResponse.posts[0], 'post', null, null);
|
||||
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||
_.isBoolean(jsonResponse.posts[0].featured).should.eql(true);
|
||||
|
||||
// Default order 'published_at desc' check
|
||||
jsonResponse.posts[0].slug.should.eql('thou-shalt-not-be-seen');
|
||||
jsonResponse.posts[1].slug.should.eql('thou-shalt-be-paid-for');
|
||||
jsonResponse.posts[2].slug.should.eql('free-to-see');
|
||||
jsonResponse.posts[7].slug.should.eql('organising-content');
|
||||
|
||||
jsonResponse.posts[0].html.should.eql('');
|
||||
jsonResponse.posts[1].html.should.eql('');
|
||||
jsonResponse.posts[2].html.should.not.eql('');
|
||||
jsonResponse.posts[7].html.should.not.eql('');
|
||||
|
||||
// check meta response for this test
|
||||
jsonResponse.meta.pagination.page.should.eql(1);
|
||||
jsonResponse.meta.pagination.limit.should.eql(15);
|
||||
jsonResponse.meta.pagination.pages.should.eql(1);
|
||||
jsonResponse.meta.pagination.total.should.eql(14);
|
||||
jsonResponse.meta.pagination.hasOwnProperty('next').should.be.true();
|
||||
jsonResponse.meta.pagination.hasOwnProperty('prev').should.be.true();
|
||||
should.not.exist(jsonResponse.meta.pagination.next);
|
||||
should.not.exist(jsonResponse.meta.pagination.prev);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,87 +0,0 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const _ = require('lodash');
|
||||
const localUtils = require('./utils');
|
||||
const testUtils = require('../../../../utils');
|
||||
const configUtils = require('../../../../utils/configUtils');
|
||||
const config = require('../../../../../core/shared/config');
|
||||
|
||||
const ghost = testUtils.startGhost;
|
||||
let request;
|
||||
|
||||
describe('api/v3/content/tags', function () {
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.initFixtures('users:no-owner', 'user:inactive', 'posts', 'tags:extra', 'api_keys');
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
configUtils.restore();
|
||||
});
|
||||
|
||||
const validKey = localUtils.getValidKey();
|
||||
|
||||
it('Can read tags with fields', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`tags/${testUtils.DataGenerator.Content.tags[0].id}/?key=${validKey}&fields=name,slug`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
localUtils.API.checkResponse(res.body.tags[0], 'tag', null, null, ['id', 'name', 'slug']);
|
||||
});
|
||||
});
|
||||
|
||||
it('Can request all tags with count.posts field', function () {
|
||||
return request
|
||||
.get(localUtils.API.getApiQuery(`tags/?key=${validKey}&include=count.posts`))
|
||||
.set('Origin', testUtils.API.getURL())
|
||||
.set('Origin', config.get('url'))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.tags);
|
||||
jsonResponse.tags.should.have.length(4);
|
||||
localUtils.API.checkResponse(jsonResponse.tags[0], 'tag', ['count', 'url']);
|
||||
|
||||
jsonResponse.meta.pagination.should.have.property('page', 1);
|
||||
jsonResponse.meta.pagination.should.have.property('limit', 15);
|
||||
jsonResponse.meta.pagination.should.have.property('pages', 4);
|
||||
jsonResponse.meta.pagination.should.have.property('total', 56);
|
||||
jsonResponse.meta.pagination.should.have.property('next', 2);
|
||||
jsonResponse.meta.pagination.should.have.property('prev', null);
|
||||
|
||||
should.exist(jsonResponse.tags[0].count.posts);
|
||||
// Each tag should have the correct count
|
||||
_.find(jsonResponse.tags, {name: 'Getting Started'}).count.posts.should.eql(7);
|
||||
_.find(jsonResponse.tags, {name: 'kitchen sink'}).count.posts.should.eql(2);
|
||||
_.find(jsonResponse.tags, {name: 'bacon'}).count.posts.should.eql(2);
|
||||
_.find(jsonResponse.tags, {name: 'chorizo'}).count.posts.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('Browse tags with slug filter, should order in slug order', function () {
|
||||
return request.get(localUtils.API.getApiQuery(`tags/?key=${validKey}&filter=slug:[kitchen-sink,bacon,chorizo]`))
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
const jsonResponse = res.body;
|
||||
|
||||
jsonResponse.tags.should.be.an.Array().with.lengthOf(3);
|
||||
jsonResponse.tags[0].slug.should.equal('kitchen-sink');
|
||||
jsonResponse.tags[1].slug.should.equal('bacon');
|
||||
jsonResponse.tags[2].slug.should.equal('chorizo');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,94 +0,0 @@
|
|||
const url = require('url');
|
||||
const _ = require('lodash');
|
||||
const testUtils = require('../../../../utils');
|
||||
const schema = require('../../../../../core/server/data/schema').tables;
|
||||
const API_URL = '/ghost/api/v3/content/';
|
||||
|
||||
const expectedProperties = {
|
||||
// API top level
|
||||
posts: ['posts', 'meta'],
|
||||
tags: ['tags', 'meta'],
|
||||
authors: ['authors', 'meta'],
|
||||
pagination: ['page', 'limit', 'pages', 'total', 'next', 'prev'],
|
||||
|
||||
post: _(schema.posts)
|
||||
.keys()
|
||||
// by default we only return html
|
||||
.without('mobiledoc', 'plaintext')
|
||||
// v3 doesn't return author_id OR author
|
||||
.without('author_id', 'author')
|
||||
// and always returns computed properties: url, primary_tag, primary_author
|
||||
.concat('url')
|
||||
// v3 API doesn't return unused fields
|
||||
.without('locale')
|
||||
// These fields aren't useful as they always have known values
|
||||
.without('status')
|
||||
// @TODO: https://github.com/TryGhost/Ghost/issues/10335
|
||||
// .without('page')
|
||||
.without('type')
|
||||
// v3 returns a calculated excerpt field
|
||||
.concat('excerpt')
|
||||
// Access is a calculated property in >= v3
|
||||
.concat('access')
|
||||
// returns meta fields from `posts_meta` schema
|
||||
.concat(
|
||||
..._(schema.posts_meta).keys().without('post_id', 'id')
|
||||
)
|
||||
.concat('reading_time')
|
||||
.concat('send_email_when_published')
|
||||
,
|
||||
author: _(schema.users)
|
||||
.keys()
|
||||
.without(
|
||||
'password',
|
||||
'email',
|
||||
'created_at',
|
||||
'created_by',
|
||||
'updated_at',
|
||||
'updated_by',
|
||||
'last_seen',
|
||||
'status'
|
||||
)
|
||||
// v3 API doesn't return unused fields
|
||||
.without('accessibility', 'locale', 'tour', 'visibility')
|
||||
,
|
||||
tag: _(schema.tags)
|
||||
.keys()
|
||||
// v3 Tag API doesn't return parent_id or parent
|
||||
.without('parent_id', 'parent')
|
||||
// v3 Tag API doesn't return date fields
|
||||
.without('created_at', 'updated_at')
|
||||
};
|
||||
|
||||
_.each(expectedProperties, (value, key) => {
|
||||
if (!value.__wrapped__) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated: x_by
|
||||
*/
|
||||
expectedProperties[key] = value
|
||||
.without(
|
||||
'created_by',
|
||||
'updated_by',
|
||||
'published_by'
|
||||
)
|
||||
.value();
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
API: {
|
||||
getApiQuery(route) {
|
||||
return url.resolve(API_URL, route);
|
||||
},
|
||||
|
||||
checkResponse(...args) {
|
||||
this.expectedProperties = expectedProperties;
|
||||
return testUtils.API.checkResponse.call(this, ...args);
|
||||
}
|
||||
},
|
||||
getValidKey() {
|
||||
return testUtils.DataGenerator.Content.api_keys[1].secret;
|
||||
}
|
||||
};
|
Loading…
Add table
Reference in a new issue