2019-01-30 16:14:27 +03:00
|
|
|
const should = require('should');
|
|
|
|
const path = require('path');
|
|
|
|
const fs = require('fs');
|
|
|
|
const _ = require('lodash');
|
|
|
|
const supertest = require('supertest');
|
2019-09-20 18:02:45 +03:00
|
|
|
const testUtils = require('../../utils');
|
2020-05-27 20:47:53 +03:00
|
|
|
const config = require('../../../core/shared/config');
|
2019-01-30 16:14:27 +03:00
|
|
|
const localUtils = require('./utils');
|
2019-09-20 18:02:45 +03:00
|
|
|
|
2019-01-30 16:14:27 +03:00
|
|
|
const ghost = testUtils.startGhost;
|
|
|
|
|
2019-02-04 17:16:24 +03:00
|
|
|
describe('Themes API', function () {
|
2019-01-30 16:14:27 +03:00
|
|
|
let ghostServer;
|
|
|
|
let ownerRequest;
|
|
|
|
|
|
|
|
const uploadTheme = (options) => {
|
|
|
|
const themePath = options.themePath;
|
2019-02-25 15:26:03 +03:00
|
|
|
const fieldName = 'file';
|
2019-01-30 16:14:27 +03:00
|
|
|
const request = options.request || ownerRequest;
|
|
|
|
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('themes/upload'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.attach(fieldName, themePath);
|
|
|
|
};
|
|
|
|
|
|
|
|
before(function () {
|
|
|
|
return ghost()
|
|
|
|
.then((_ghostServer) => {
|
|
|
|
ghostServer = _ghostServer;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
before(function () {
|
|
|
|
ownerRequest = supertest.agent(config.get('url'));
|
|
|
|
return localUtils.doAuth(ownerRequest);
|
|
|
|
});
|
|
|
|
|
2019-02-04 17:16:24 +03:00
|
|
|
it('Can request all available themes', function () {
|
2019-01-30 16:14:27 +03:00
|
|
|
return ownerRequest
|
|
|
|
.get(localUtils.API.getApiQuery('themes/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
should.exist(jsonResponse.themes);
|
|
|
|
localUtils.API.checkResponse(jsonResponse, 'themes');
|
|
|
|
jsonResponse.themes.length.should.eql(5);
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.themes[0], 'theme');
|
|
|
|
jsonResponse.themes[0].name.should.eql('broken-theme');
|
|
|
|
jsonResponse.themes[0].package.should.be.an.Object().with.properties('name', 'version');
|
|
|
|
jsonResponse.themes[0].active.should.be.false();
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.themes[1], 'theme', 'templates');
|
|
|
|
jsonResponse.themes[1].name.should.eql('casper');
|
|
|
|
jsonResponse.themes[1].package.should.be.an.Object().with.properties('name', 'version');
|
|
|
|
jsonResponse.themes[1].active.should.be.true();
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.themes[2], 'theme');
|
|
|
|
jsonResponse.themes[2].name.should.eql('casper-1.4');
|
|
|
|
jsonResponse.themes[2].package.should.be.an.Object().with.properties('name', 'version');
|
|
|
|
jsonResponse.themes[2].active.should.be.false();
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.themes[3], 'theme');
|
|
|
|
jsonResponse.themes[3].name.should.eql('test-theme');
|
|
|
|
jsonResponse.themes[3].package.should.be.an.Object().with.properties('name', 'version');
|
|
|
|
jsonResponse.themes[3].active.should.be.false();
|
|
|
|
|
|
|
|
localUtils.API.checkResponse(jsonResponse.themes[4], 'theme');
|
|
|
|
jsonResponse.themes[4].name.should.eql('test-theme-channels');
|
|
|
|
jsonResponse.themes[4].package.should.be.false();
|
|
|
|
jsonResponse.themes[4].active.should.be.false();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-02-04 17:16:24 +03:00
|
|
|
it('Can download a theme', function () {
|
2019-01-30 16:14:27 +03:00
|
|
|
return ownerRequest
|
|
|
|
.get(localUtils.API.getApiQuery('themes/casper/download/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /application\/zip/)
|
|
|
|
.expect('Content-Disposition', 'attachment; filename=casper.zip')
|
|
|
|
.expect(200);
|
|
|
|
});
|
|
|
|
|
2019-02-04 17:16:24 +03:00
|
|
|
it('Can upload a valid theme', function () {
|
2019-09-20 18:02:45 +03:00
|
|
|
return uploadTheme({themePath: path.join(__dirname, '..', '..', 'utils', 'fixtures', 'themes', 'valid.zip')})
|
2019-01-30 16:14:27 +03:00
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
|
|
|
|
|
|
should.exist(jsonResponse.themes);
|
|
|
|
localUtils.API.checkResponse(jsonResponse, 'themes');
|
|
|
|
jsonResponse.themes.length.should.eql(1);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.themes[0], 'theme');
|
|
|
|
jsonResponse.themes[0].name.should.eql('valid');
|
|
|
|
jsonResponse.themes[0].active.should.be.false();
|
|
|
|
|
|
|
|
// upload same theme again to force override
|
2019-09-20 18:02:45 +03:00
|
|
|
return uploadTheme({themePath: path.join(__dirname, '..', '..', 'utils', 'fixtures', 'themes', 'valid.zip')});
|
2019-01-30 16:14:27 +03:00
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
|
|
|
|
should.not.exist(res.headers['x-cache-invalidate']);
|
|
|
|
should.exist(jsonResponse.themes);
|
|
|
|
localUtils.API.checkResponse(jsonResponse, 'themes');
|
|
|
|
jsonResponse.themes.length.should.eql(1);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.themes[0], 'theme');
|
|
|
|
jsonResponse.themes[0].name.should.eql('valid');
|
|
|
|
jsonResponse.themes[0].active.should.be.false();
|
|
|
|
|
|
|
|
// ensure tmp theme folder contains two themes now
|
|
|
|
const tmpFolderContents = fs.readdirSync(config.getContentPath('themes'));
|
|
|
|
tmpFolderContents.forEach((theme, index) => {
|
|
|
|
if (theme.match(/^\./)) {
|
|
|
|
tmpFolderContents.splice(index, 1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-06-03 18:29:34 +03:00
|
|
|
// Note: at this point, the tmpFolder can legitimately still contain a valid_34324324 backup
|
|
|
|
// As it is deleted asynchronously
|
|
|
|
tmpFolderContents.should.containEql('valid');
|
|
|
|
tmpFolderContents.should.containEql('valid.zip');
|
2019-01-30 16:14:27 +03:00
|
|
|
|
|
|
|
// Check the Themes API returns the correct result
|
|
|
|
return ownerRequest
|
|
|
|
.get(localUtils.API.getApiQuery('themes/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
|
|
|
|
should.exist(jsonResponse.themes);
|
|
|
|
localUtils.API.checkResponse(jsonResponse, 'themes');
|
|
|
|
jsonResponse.themes.length.should.eql(6);
|
|
|
|
|
|
|
|
// Casper should be present and still active
|
|
|
|
const casperTheme = _.find(jsonResponse.themes, {name: 'casper'});
|
|
|
|
should.exist(casperTheme);
|
|
|
|
localUtils.API.checkResponse(casperTheme, 'theme', 'templates');
|
|
|
|
casperTheme.active.should.be.true();
|
|
|
|
|
|
|
|
// The added theme should be here
|
|
|
|
const addedTheme = _.find(jsonResponse.themes, {name: 'valid'});
|
|
|
|
should.exist(addedTheme);
|
|
|
|
localUtils.API.checkResponse(addedTheme, 'theme');
|
|
|
|
addedTheme.active.should.be.false();
|
2020-06-03 18:29:34 +03:00
|
|
|
|
|
|
|
// Note: at this point, the API should not return a valid_34324324 backup folder as a theme
|
|
|
|
_.map(jsonResponse.themes, 'name').should.eql([
|
|
|
|
'broken-theme',
|
|
|
|
'casper',
|
|
|
|
'casper-1.4',
|
|
|
|
'test-theme',
|
|
|
|
'test-theme-channels',
|
|
|
|
'valid'
|
|
|
|
]);
|
2019-01-30 16:14:27 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-02-04 17:16:24 +03:00
|
|
|
it('Can delete a theme', function () {
|
2019-01-30 16:14:27 +03:00
|
|
|
return ownerRequest
|
|
|
|
.del(localUtils.API.getApiQuery('themes/valid'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(204)
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
// Delete requests have empty bodies
|
|
|
|
jsonResponse.should.eql({});
|
|
|
|
|
|
|
|
// ensure tmp theme folder contains one theme again now
|
|
|
|
const tmpFolderContents = fs.readdirSync(config.getContentPath('themes'));
|
|
|
|
tmpFolderContents.forEach((theme, index) => {
|
|
|
|
if (theme.match(/^\./)) {
|
|
|
|
tmpFolderContents.splice(index, 1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
tmpFolderContents.should.be.an.Array().with.lengthOf(9);
|
|
|
|
|
|
|
|
tmpFolderContents.should.eql([
|
|
|
|
'broken-theme',
|
|
|
|
'casper',
|
|
|
|
'casper-1.4',
|
|
|
|
'casper.zip',
|
|
|
|
'invalid.zip',
|
|
|
|
'test-theme',
|
|
|
|
'test-theme-channels',
|
|
|
|
'valid.zip',
|
|
|
|
'warnings.zip'
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Check the themes API returns the correct result after deletion
|
|
|
|
return ownerRequest
|
|
|
|
.get(localUtils.API.getApiQuery('themes/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
|
|
|
|
should.exist(jsonResponse.themes);
|
|
|
|
localUtils.API.checkResponse(jsonResponse, 'themes');
|
|
|
|
jsonResponse.themes.length.should.eql(5);
|
|
|
|
|
|
|
|
// Casper should be present and still active
|
|
|
|
const casperTheme = _.find(jsonResponse.themes, {name: 'casper'});
|
|
|
|
should.exist(casperTheme);
|
|
|
|
localUtils.API.checkResponse(casperTheme, 'theme', 'templates');
|
|
|
|
casperTheme.active.should.be.true();
|
|
|
|
|
|
|
|
// The deleted theme should not be here
|
|
|
|
const deletedTheme = _.find(jsonResponse.themes, {name: 'valid'});
|
|
|
|
should.not.exist(deletedTheme);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-02-04 17:16:24 +03:00
|
|
|
it('Can upload a theme, which has warnings', function () {
|
2019-09-20 18:02:45 +03:00
|
|
|
return uploadTheme({themePath: path.join(__dirname, '/../../utils/fixtures/themes/warnings.zip')})
|
2019-01-30 16:14:27 +03:00
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
|
|
|
|
should.exist(jsonResponse.themes);
|
|
|
|
localUtils.API.checkResponse(jsonResponse, 'themes');
|
|
|
|
jsonResponse.themes.length.should.eql(1);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.themes[0], 'theme', ['warnings']);
|
|
|
|
jsonResponse.themes[0].name.should.eql('warnings');
|
|
|
|
jsonResponse.themes[0].active.should.be.false();
|
|
|
|
jsonResponse.themes[0].warnings.should.be.an.Array();
|
|
|
|
|
|
|
|
// Delete the theme to clean up after the test
|
|
|
|
return ownerRequest
|
|
|
|
.del(localUtils.API.getApiQuery('themes/warnings'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(204);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-02-04 17:16:24 +03:00
|
|
|
it('Can activate a theme', function () {
|
2019-01-30 16:14:27 +03:00
|
|
|
return ownerRequest
|
|
|
|
.get(localUtils.API.getApiQuery('themes/'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
|
|
|
|
should.exist(jsonResponse.themes);
|
|
|
|
localUtils.API.checkResponse(jsonResponse, 'themes');
|
|
|
|
jsonResponse.themes.length.should.eql(5);
|
|
|
|
|
|
|
|
const casperTheme = _.find(jsonResponse.themes, {name: 'casper'});
|
|
|
|
should.exist(casperTheme);
|
|
|
|
localUtils.API.checkResponse(casperTheme, 'theme', 'templates');
|
|
|
|
casperTheme.active.should.be.true();
|
|
|
|
|
|
|
|
const testTheme = _.find(jsonResponse.themes, {name: 'test-theme'});
|
|
|
|
should.exist(testTheme);
|
|
|
|
localUtils.API.checkResponse(testTheme, 'theme');
|
|
|
|
testTheme.active.should.be.false();
|
|
|
|
|
|
|
|
// Finally activate the new theme
|
|
|
|
return ownerRequest
|
|
|
|
.put(localUtils.API.getApiQuery('themes/test-theme/activate'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
|
|
|
|
should.exist(res.headers['x-cache-invalidate']);
|
|
|
|
should.exist(jsonResponse.themes);
|
|
|
|
localUtils.API.checkResponse(jsonResponse, 'themes');
|
|
|
|
jsonResponse.themes.length.should.eql(1);
|
|
|
|
|
|
|
|
const casperTheme = _.find(jsonResponse.themes, {name: 'casper'});
|
|
|
|
should.not.exist(casperTheme);
|
|
|
|
|
|
|
|
const testTheme = _.find(jsonResponse.themes, {name: 'test-theme'});
|
|
|
|
should.exist(testTheme);
|
|
|
|
localUtils.API.checkResponse(testTheme, 'theme', ['warnings', 'templates']);
|
|
|
|
testTheme.active.should.be.true();
|
|
|
|
testTheme.warnings.should.be.an.Array();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|