const should = require('should'); const supertest = require('supertest'); const testUtils = require('../../utils'); const localUtils = require('./utils'); const config = require('../../../core/shared/config'); const sinon = require('sinon'); const logging = require('@tryghost/logging'); describe('Custom Theme Settings API', function () { let request; before(async function () { // NOTE: needs force start to be able to reinitialize Ghost process with frontend services - custom-theme-settings, to be specific await localUtils.startGhost({ }); request = supertest.agent(config.get('url')); await localUtils.doAuth(request, 'users:extra', 'custom_theme_settings'); // require and init here so we know it's already been set up with models const customThemeSettingsService = require('../../../core/server/services/custom-theme-settings'); await customThemeSettingsService.init(); // fake a theme activation with custom settings - settings match fixtures await customThemeSettingsService.api.activateTheme('casper', { 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' } } }); }); afterEach(function () { sinon.restore(); }); 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 loggingStub = sinon.stub(logging, 'error'); 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); sinon.assert.calledOnce(loggingStub); }); it('errors for invalid select value', async function () { const custom_theme_settings = [{ key: 'header_typography', value: 'Not gonna work' }]; const loggingStub = sinon.stub(logging, 'error'); 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); sinon.assert.calledOnce(loggingStub); }); }); });