Ghost/core/test/unit/models/settings_spec.js

173 lines
5.8 KiB
JavaScript
Raw Normal View History

const should = require('should');
const sinon = require('sinon');
const mockDb = require('mock-knex');
const models = require('../../../server/models');
const {knex} = require('../../../server/data/db');
const common = require('../../../server/lib/common');
describe('Unit: models/settings', function () {
before(function () {
models.init();
});
describe('events', function () {
let tracker;
let eventSpy;
beforeEach(function () {
mockDb.mock(knex);
tracker = mockDb.getTracker();
tracker.install();
});
afterEach(function () {
mockDb.unmock(knex);
});
beforeEach(function () {
eventSpy = sinon.spy(common.events, 'emit');
});
afterEach(function () {
sinon.restore();
});
it('emits add events', function () {
tracker.on('query', (query, step) => {
return [
function fetchAddQuery() {
query.response([{}]);
},
function addQuery() {
query.response([{
key: 'description',
value: 'added value'
}]);
}
][step - 1]();
});
return models.Settings.edit({
key: 'description',
value: 'added value'
})
.then(() => {
eventSpy.calledTwice.should.be.true();
eventSpy.firstCall.calledWith('settings.added').should.be.true();
eventSpy.secondCall.calledWith('settings.description.added').should.be.true();
});
});
it('emits edit events', function () {
tracker.on('query', (query, step) => {
return [
function fetchEditQuery() {
query.response([{
id: 1, // NOTE: `id` imitates existing value for 'edit' event
key: 'description',
value: 'db value'
}]);
}
][step - 1]();
});
return models.Settings.edit({
key: 'description',
value: 'edited value'
})
.then(() => {
eventSpy.calledTwice.should.be.true();
eventSpy.firstCall.calledWith('settings.edited').should.be.true();
eventSpy.secondCall.calledWith('settings.description.edited').should.be.true();
});
});
});
describe('defaults', function () {
let tracker;
let eventSpy;
beforeEach(function () {
mockDb.mock(knex);
tracker = mockDb.getTracker();
tracker.install();
});
afterEach(function () {
mockDb.unmock(knex);
tracker.uninstall();
});
beforeEach(function () {
eventSpy = sinon.spy(common.events, 'emit');
});
afterEach(function () {
sinon.restore();
});
it('populates unset defaults', function () {
tracker.on('query', (query) => {
return query.response([{}]);
});
return models.Settings.populateDefaults()
.then(() => {
// 2 events per item - settings.added and settings.[name].added
Implemented externally verifiable identity tokens no-issue This adds two new endpoints, one at /ghost/.well-known/jwks.json for exposing a public key, and one on the canary api /identities, which allows the Owner user to fetch a JWT. This token can then be used by external services to verify the domain * Added ghost_{public,private}_key settings This key can be used for generating tokens for communicating with external services on behalf of Ghost * Added .well-known directory to /ghost/.well-known We add a jwks.json file to the .well-known directory which exposes a public JWK which can be used to verify the signatures of JWT's created by Ghost This is added to the /ghost/ path so that it can live on the admin domain, rather than the frontend. This is because most of its uses/functions will be in relation to the admin domain. * Improved settings model tests This removes hardcoded positions in favour of testing that a particular event wasn't emitted which is less brittle and more precise about what's being tested * Fixed parent app unit tests for well-known This updates the parent app unit tests to check that the well-known route is mounted. We all change proxyquire to use `noCallThru` which ensures that the ubderlying modules are not required. This stops the initialisation logic in ./well-known erroring in tests https://github.com/thlorenz/proxyquire/issues/215 * Moved jwt signature to a separate 'token' propery This structure corresponds to other resources and allows to exptend with additional properties in future if needed
2020-01-20 14:45:58 +03:00
eventSpy.callCount.should.equal(92);
const eventsEmitted = eventSpy.args.map(args => args[0]);
const checkEventEmitted = event => should.ok(eventsEmitted.includes(event), `${event} event should be emitted`);
checkEventEmitted('settings.db_hash.added');
checkEventEmitted('settings.description.added');
checkEventEmitted('settings.default_content_visibility.added');
checkEventEmitted('settings.members_subscription_settings.added');
});
});
it('doesn\'t overwrite any existing settings', function () {
tracker.on('query', (query) => {
return query.response([{
key: 'description',
value: 'Adam\'s Blog'
}]);
});
return models.Settings.populateDefaults()
.then(() => {
Implemented externally verifiable identity tokens no-issue This adds two new endpoints, one at /ghost/.well-known/jwks.json for exposing a public key, and one on the canary api /identities, which allows the Owner user to fetch a JWT. This token can then be used by external services to verify the domain * Added ghost_{public,private}_key settings This key can be used for generating tokens for communicating with external services on behalf of Ghost * Added .well-known directory to /ghost/.well-known We add a jwks.json file to the .well-known directory which exposes a public JWK which can be used to verify the signatures of JWT's created by Ghost This is added to the /ghost/ path so that it can live on the admin domain, rather than the frontend. This is because most of its uses/functions will be in relation to the admin domain. * Improved settings model tests This removes hardcoded positions in favour of testing that a particular event wasn't emitted which is less brittle and more precise about what's being tested * Fixed parent app unit tests for well-known This updates the parent app unit tests to check that the well-known route is mounted. We all change proxyquire to use `noCallThru` which ensures that the ubderlying modules are not required. This stops the initialisation logic in ./well-known erroring in tests https://github.com/thlorenz/proxyquire/issues/215 * Moved jwt signature to a separate 'token' propery This structure corresponds to other resources and allows to exptend with additional properties in future if needed
2020-01-20 14:45:58 +03:00
const eventsEmitted = eventSpy.args.map(args => args[0]);
const checkEventNotEmitted = event => should.ok(!eventsEmitted.includes(event), `${event} event should be emitted`);
checkEventNotEmitted('settings.description.added');
});
});
});
describe('parse', function () {
it('ensure correct parsing when fetching from db', function () {
const setting = models.Settings.forge();
let returns = setting.parse({key: 'is_private', value: 'false'});
should.equal(returns.value, false);
returns = setting.parse({key: 'is_private', value: false});
should.equal(returns.value, false);
returns = setting.parse({key: 'is_private', value: true});
should.equal(returns.value, true);
returns = setting.parse({key: 'is_private', value: 'true'});
should.equal(returns.value, true);
returns = setting.parse({key: 'is_private', value: '0'});
should.equal(returns.value, false);
returns = setting.parse({key: 'is_private', value: '1'});
should.equal(returns.value, true);
returns = setting.parse({key: 'something', value: 'null'});
should.equal(returns.value, 'null');
});
});
});