mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Added API tests for custom theme settings (#13519)
refs https://github.com/TryGhost/Team/issues/1104 - bumped `@tryghost/custom-theme-settings-service` so it throws a more appropriate `ValidationError` when setting keys don't exist or a select value is not known - changed the custom theme settings service to have a `.init()` method which creates an instance of the service under `.api` so that we're able to create the instance at a particular point in the boot process when we know the models have been initialised - there were problems in tests because the service was being initialised through the require chain before models were initialised through the boot process - fixed incorrect `camelCase` of resource name in API responses
This commit is contained in:
parent
7ad6dec0e0
commit
c33b596e9c
10 changed files with 269 additions and 17 deletions
|
@ -119,6 +119,8 @@ async function initServicesForFrontend() {
|
|||
debug('Begin: Themes');
|
||||
const themeService = require('./server/services/themes');
|
||||
await themeService.init();
|
||||
const customThemeSettingsService = require('./server/services/custom-theme-settings');
|
||||
customThemeSettingsService.init();
|
||||
debug('End: Themes');
|
||||
|
||||
debug('End: initServicesForFrontend');
|
||||
|
|
|
@ -6,7 +6,7 @@ module.exports = {
|
|||
browse: {
|
||||
permissions: true,
|
||||
query() {
|
||||
return customThemeSettingsService.listSettings();
|
||||
return customThemeSettingsService.api.listSettings();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -16,7 +16,7 @@ module.exports = {
|
|||
},
|
||||
permissions: true,
|
||||
query(frame) {
|
||||
return customThemeSettingsService.updateSettings(frame.data.custom_theme_settings);
|
||||
return customThemeSettingsService.api.updateSettings(frame.data.custom_theme_settings);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
module.exports = {
|
||||
browse(models, apiConfig, frame) {
|
||||
frame.response = {
|
||||
customThemeSettings: models
|
||||
custom_theme_settings: models
|
||||
};
|
||||
},
|
||||
|
||||
edit(models, apiConfig, frame) {
|
||||
frame.response = {
|
||||
customThemeSettings: models
|
||||
custom_theme_settings: models
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,7 +2,13 @@ const {Service: CustomThemeSettingsService} = require('@tryghost/custom-theme-se
|
|||
const customThemeSettingsCache = require('../../shared/custom-theme-settings-cache');
|
||||
const models = require('../models');
|
||||
|
||||
module.exports = new CustomThemeSettingsService({
|
||||
class CustomThemeSettingsServiceWrapper {
|
||||
init() {
|
||||
this.api = new CustomThemeSettingsService({
|
||||
model: models.CustomThemeSetting,
|
||||
cache: customThemeSettingsCache
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new CustomThemeSettingsServiceWrapper();
|
||||
|
|
|
@ -12,7 +12,7 @@ module.exports = {
|
|||
debug('Activating theme (method A on boot)', themeName);
|
||||
// TODO: probably a better place for this to happen - after successful activation / when reloading site?
|
||||
if (labs.isSet('customThemeSettings')) {
|
||||
customThemeSettings.activateTheme(checkedTheme);
|
||||
customThemeSettings.api.activateTheme(checkedTheme);
|
||||
}
|
||||
bridge.activateTheme(theme, checkedTheme);
|
||||
},
|
||||
|
@ -20,7 +20,7 @@ module.exports = {
|
|||
debug('Activating theme (method B on API "activate")', themeName);
|
||||
// TODO: probably a better place for this to happen - after successful activation / when reloading site?
|
||||
if (labs.isSet('customThemeSettings')) {
|
||||
customThemeSettings.activateTheme(checkedTheme);
|
||||
customThemeSettings.api.activateTheme(checkedTheme);
|
||||
}
|
||||
bridge.activateTheme(theme, checkedTheme);
|
||||
},
|
||||
|
@ -28,7 +28,7 @@ module.exports = {
|
|||
debug('Activating theme (method C on API "override")', themeName);
|
||||
// TODO: probably a better place for this to happen - after successful activation / when reloading site?
|
||||
if (labs.isSet('customThemeSettings')) {
|
||||
customThemeSettings.activateTheme(checkedTheme);
|
||||
customThemeSettings.api.activateTheme(checkedTheme);
|
||||
}
|
||||
bridge.activateTheme(theme, checkedTheme);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
"@tryghost/color-utils": "0.1.2",
|
||||
"@tryghost/config-url-helpers": "0.1.2",
|
||||
"@tryghost/constants": "0.1.11",
|
||||
"@tryghost/custom-theme-settings-service": "0.1.0",
|
||||
"@tryghost/custom-theme-settings-service": "0.1.1",
|
||||
"@tryghost/debug": "0.1.5",
|
||||
"@tryghost/email-analytics-provider-mailgun": "1.0.2",
|
||||
"@tryghost/email-analytics-service": "1.0.2",
|
||||
|
|
211
test/e2e-api/admin/custom_theme_settings.test.js
Normal file
211
test/e2e-api/admin/custom_theme_settings.test.js
Normal file
|
@ -0,0 +1,211 @@
|
|||
const should = require('should');
|
||||
const supertest = require('supertest');
|
||||
const testUtils = require('../../utils');
|
||||
const localUtils = require('./utils');
|
||||
|
||||
const config = require('../../../core/shared/config');
|
||||
|
||||
describe('Custom Theme Settings API', function () {
|
||||
let request;
|
||||
|
||||
before(async function () {
|
||||
await testUtils.startGhost();
|
||||
request = supertest.agent(config.get('url'));
|
||||
await localUtils.doAuth(request, 'users:extra', 'custom_theme_settings');
|
||||
|
||||
// require here so we know it's already been set up with models
|
||||
const customThemeSettingsService = require('../../../core/server/services/custom-theme-settings');
|
||||
// fake a theme activation with custom settings - settings match fixtures
|
||||
await customThemeSettingsService.api.activateTheme({
|
||||
name: 'casper',
|
||||
customSettings: {
|
||||
header_typography: {
|
||||
type: 'select',
|
||||
options: ['Serif', 'Sans-serif'],
|
||||
default: 'Sans-serif'
|
||||
},
|
||||
footer_type: {
|
||||
type: 'select',
|
||||
options: ['Full', 'Minimal', 'CTA'],
|
||||
default: 'Full',
|
||||
group: 'homepage'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Browse', function () {
|
||||
it('can fetch settings for current theme', async function () {
|
||||
const res = await request
|
||||
.get(localUtils.API.getApiQuery(`custom_theme_settings/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.set('Accept', 'application/json')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.custom_theme_settings);
|
||||
|
||||
jsonResponse.custom_theme_settings.length.should.equal(2);
|
||||
|
||||
jsonResponse.custom_theme_settings[0].should.match({
|
||||
id: /.+/,
|
||||
key: 'header_typography',
|
||||
type: 'select',
|
||||
options: ['Serif', 'Sans-serif'],
|
||||
default: 'Sans-serif',
|
||||
value: 'Serif'
|
||||
});
|
||||
|
||||
jsonResponse.custom_theme_settings[1].should.match({
|
||||
id: /.+/,
|
||||
key: 'footer_type',
|
||||
type: 'select',
|
||||
options: ['Full', 'Minimal', 'CTA'],
|
||||
default: 'Full',
|
||||
value: 'Full',
|
||||
group: 'homepage'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edit', function () {
|
||||
it('can update all settings for current theme', async function () {
|
||||
// `.updateSettings()` only cares about `key` and `value`, everything else is set by the theme
|
||||
const custom_theme_settings = [{
|
||||
id: 'id',
|
||||
type: 'type',
|
||||
options: ['option'],
|
||||
default: 'default',
|
||||
key: 'header_typography',
|
||||
value: 'Sans-serif'
|
||||
}, {
|
||||
key: 'footer_type',
|
||||
value: 'Minimal'
|
||||
}];
|
||||
|
||||
const res = await request
|
||||
.put(localUtils.API.getApiQuery(`custom_theme_settings/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({custom_theme_settings})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
should.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.custom_theme_settings);
|
||||
|
||||
jsonResponse.custom_theme_settings.length.should.equal(2);
|
||||
|
||||
jsonResponse.custom_theme_settings[0].should.match({
|
||||
id: /.+/,
|
||||
key: 'header_typography',
|
||||
type: 'select',
|
||||
options: ['Serif', 'Sans-serif'],
|
||||
default: 'Sans-serif',
|
||||
value: 'Sans-serif'
|
||||
});
|
||||
|
||||
jsonResponse.custom_theme_settings[1].should.match({
|
||||
id: /.+/,
|
||||
key: 'footer_type',
|
||||
type: 'select',
|
||||
options: ['Full', 'Minimal', 'CTA'],
|
||||
default: 'Full',
|
||||
value: 'Minimal',
|
||||
group: 'homepage'
|
||||
});
|
||||
});
|
||||
|
||||
it('can update some settings', async function () {
|
||||
// `.updateSettings()` only cares about `key` and `value`, everything else is set by the theme
|
||||
const custom_theme_settings = [{
|
||||
key: 'footer_type',
|
||||
value: 'Minimal'
|
||||
}];
|
||||
|
||||
const res = await request
|
||||
.put(localUtils.API.getApiQuery(`custom_theme_settings/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({custom_theme_settings})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(200);
|
||||
|
||||
should.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.custom_theme_settings);
|
||||
|
||||
jsonResponse.custom_theme_settings.length.should.equal(2);
|
||||
|
||||
jsonResponse.custom_theme_settings[0].should.match({
|
||||
id: /.+/,
|
||||
key: 'header_typography',
|
||||
type: 'select',
|
||||
options: ['Serif', 'Sans-serif'],
|
||||
default: 'Sans-serif',
|
||||
value: 'Sans-serif' // set in previous test
|
||||
});
|
||||
|
||||
jsonResponse.custom_theme_settings[1].should.match({
|
||||
id: /.+/,
|
||||
key: 'footer_type',
|
||||
type: 'select',
|
||||
options: ['Full', 'Minimal', 'CTA'],
|
||||
default: 'Full',
|
||||
value: 'Minimal',
|
||||
group: 'homepage'
|
||||
});
|
||||
});
|
||||
|
||||
it('errors for unknown key', async function () {
|
||||
const custom_theme_settings = [{
|
||||
key: 'unknown',
|
||||
value: 'Not gonna work'
|
||||
}];
|
||||
|
||||
const res = await request
|
||||
.put(localUtils.API.getApiQuery(`custom_theme_settings/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({custom_theme_settings})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(422);
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.errors);
|
||||
});
|
||||
|
||||
it('errors for invalid select value', async function () {
|
||||
const custom_theme_settings = [{
|
||||
key: 'header_typography',
|
||||
value: 'Not gonna work'
|
||||
}];
|
||||
|
||||
const res = await request
|
||||
.put(localUtils.API.getApiQuery(`custom_theme_settings/`))
|
||||
.set('Origin', config.get('url'))
|
||||
.send({custom_theme_settings})
|
||||
.expect('Content-Type', /json/)
|
||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||
.expect(422);
|
||||
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
|
||||
const jsonResponse = res.body;
|
||||
should.exist(jsonResponse);
|
||||
should.exist(jsonResponse.errors);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -543,6 +543,12 @@ const fixtures = {
|
|||
});
|
||||
},
|
||||
|
||||
insertCustomThemeSettings: function insertCustomThemeSettings() {
|
||||
return Promise.map(DataGenerator.forKnex.custom_theme_settings, function (setting) {
|
||||
return models.CustomThemeSetting.add(setting, context.internal);
|
||||
});
|
||||
},
|
||||
|
||||
async enableAllLabsFeatures() {
|
||||
const labsValue = Object.fromEntries(labsService.WRITABLE_KEYS_ALLOWLIST.map(key => [key, true]));
|
||||
const labsSetting = DataGenerator.forKnex.createSetting({
|
||||
|
@ -652,6 +658,9 @@ const toDoList = {
|
|||
},
|
||||
'labs:enabled': function enableAllLabsFeatures() {
|
||||
return fixtures.enableAllLabsFeatures();
|
||||
},
|
||||
custom_theme_settings: function insertCustomThemeSettings() {
|
||||
return fixtures.insertCustomThemeSettings();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -668,6 +668,23 @@ DataGenerator.Content = {
|
|||
name: 'Test snippet 1',
|
||||
mobiledoc: '{}'
|
||||
}
|
||||
],
|
||||
|
||||
custom_theme_settings: [
|
||||
{
|
||||
id: ObjectId().toHexString(),
|
||||
theme: 'casper',
|
||||
key: 'header_typography',
|
||||
type: 'select',
|
||||
value: 'Serif'
|
||||
},
|
||||
{
|
||||
id: ObjectId().toHexString(),
|
||||
theme: 'casper',
|
||||
key: 'footer_type',
|
||||
type: 'select',
|
||||
value: 'Full'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
@ -1282,6 +1299,11 @@ DataGenerator.forKnex = (function () {
|
|||
createBasic(DataGenerator.Content.snippets[0])
|
||||
];
|
||||
|
||||
const custom_theme_settings = [
|
||||
createBasic(DataGenerator.Content.custom_theme_settings[0]),
|
||||
createBasic(DataGenerator.Content.custom_theme_settings[1])
|
||||
];
|
||||
|
||||
return {
|
||||
createPost,
|
||||
createGenericPost,
|
||||
|
@ -1306,6 +1328,7 @@ DataGenerator.forKnex = (function () {
|
|||
createWebhook,
|
||||
createIntegration,
|
||||
createEmail,
|
||||
createCustomThemeSetting: createBasic,
|
||||
|
||||
invites,
|
||||
posts,
|
||||
|
@ -1330,7 +1353,8 @@ DataGenerator.forKnex = (function () {
|
|||
stripe_customer_subscriptions,
|
||||
stripe_prices,
|
||||
stripe_products,
|
||||
snippets
|
||||
snippets,
|
||||
custom_theme_settings
|
||||
};
|
||||
}());
|
||||
|
||||
|
|
|
@ -1333,10 +1333,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@tryghost/constants/-/constants-0.1.11.tgz#ffcc6ccb10a768aaa9276c3a22b2dea9f560e247"
|
||||
integrity sha512-ml1aJ4nJmfA8MRAJ3l9+iTdccGDQiUN1En8XwYwypfrKlECR8Mw/kKRPnqHge598+ED6J1+at5gArSq6bLKbug==
|
||||
|
||||
"@tryghost/custom-theme-settings-service@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/custom-theme-settings-service/-/custom-theme-settings-service-0.1.0.tgz#ebb23289b7c092e3125db12e0fa8be74d2054db5"
|
||||
integrity sha512-n4nCEZOZLheSHWMykpMjYHuOc0AUn+XJRW9WAEgD7g9kXuArwvsa42uWVZ12VqyQ5JSz3W5rVYXNLlZX+M3k4w==
|
||||
"@tryghost/custom-theme-settings-service@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/custom-theme-settings-service/-/custom-theme-settings-service-0.1.1.tgz#f7403f7b9ad11a1ef0a0211ac28011210df31f36"
|
||||
integrity sha512-Mo0w+UMYbhsgHm47x2fGek7j2Qo3RhZaALCRvdaBrHjaXihaSAXTy6T+5dKY4eQeiZ4rZ+5QVza7bQ93ttcxbg==
|
||||
dependencies:
|
||||
"@tryghost/debug" "^0.1.5"
|
||||
"@tryghost/errors" "^0.2.14"
|
||||
|
|
Loading…
Add table
Reference in a new issue