Fixes 298 Basic validation for config

This commit is contained in:
Joseph Earl 2017-04-14 22:36:41 +01:00 committed by David Calavera
parent 365c0358e9
commit 6d7bf3b186
3 changed files with 104 additions and 31 deletions

View File

@ -1,15 +1,9 @@
import * as config from '../config';
import { applyDefaults, validateConfig } from '../config';
describe('config', () => {
describe('applyDefaults', () => {
it('should throw if media_folder is not defined in config', () => {
expect(() => {
config.applyDefaults({ foo: 'bar' });
}).toThrowError('Error in configuration file: A `media_folder` wasn\'t found. Check your config.yml file.');
});
it('should set publish_mode if not set', () => {
expect(config.applyDefaults({
expect(applyDefaults({
foo: 'bar',
media_folder: 'path/to/media',
})).toEqual({
@ -21,7 +15,7 @@ describe('config', () => {
});
it('should set publish_mode from config', () => {
expect(config.applyDefaults({
expect(applyDefaults({
foo: 'bar',
publish_mode: 'complex',
media_folder: 'path/to/media',
@ -34,7 +28,7 @@ describe('config', () => {
});
it('should set public_folder based on media_folder if not set', () => {
expect(config.applyDefaults({
expect(applyDefaults({
foo: 'bar',
media_folder: 'path/to/media',
})).toEqual({
@ -46,7 +40,7 @@ describe('config', () => {
});
it('should not overwrite public_folder if set', () => {
expect(config.applyDefaults({
expect(applyDefaults({
foo: 'bar',
media_folder: 'path/to/media',
public_folder: '/publib/path',
@ -58,4 +52,67 @@ describe('config', () => {
});
});
});
});
describe('validateConfig', () => {
it('should return the config if no errors', () => {
const config = { foo: 'bar', backend: { name: 'bar' }, media_folder: 'baz', collections: [{}] };
expect(
validateConfig(config)
).toEqual(config);
});
it('should throw if backend is not defined in config', () => {
expect(() => {
validateConfig({ foo: 'bar' });
}).toThrowError('Error in configuration file: A `backend` wasn\'t found. Check your config.yml file.');
});
it('should throw if backend name is not defined in config', () => {
expect(() => {
validateConfig({ foo: 'bar', backend: {} });
}).toThrowError('Error in configuration file: A `backend.name` wasn\'t found. Check your config.yml file.');
});
it('should throw if backend name is not a string in config', () => {
expect(() => {
validateConfig({ foo: 'bar', backend: { name: { } } });
}).toThrowError('Error in configuration file: Your `backend.name` must be a string. Check your config.yml file.');
});
it('should throw if media_folder is not defined in config', () => {
expect(() => {
validateConfig({ foo: 'bar', backend: { name: 'bar' } });
}).toThrowError('Error in configuration file: A `media_folder` wasn\'t found. Check your config.yml file.');
});
it('should throw if media_folder is not a string in config', () => {
expect(() => {
validateConfig({ foo: 'bar', backend: { name: 'bar' }, media_folder: {} });
}).toThrowError('Error in configuration file: Your `media_folder` must be a string. Check your config.yml file.');
});
it('should throw if collections is not defined in config', () => {
expect(() => {
validateConfig({ foo: 'bar', backend: { name: 'bar' }, media_folder: 'baz' });
}).toThrowError('Error in configuration file: A `collections` wasn\'t found. Check your config.yml file.');
});
it('should throw if collections not an array in config', () => {
expect(() => {
validateConfig({ foo: 'bar', backend: { name: 'bar' }, media_folder: 'baz', collections: {} });
}).toThrowError('Error in configuration file: Your `collections` must be an array with at least one element. Check your config.yml file.');
});
it('should throw if collections is an empty array in config', () => {
expect(() => {
validateConfig({ foo: 'bar', backend: { name: 'bar' }, media_folder: 'baz', collections: [] });
}).toThrowError('Error in configuration file: Your `collections` must be an array with at least one element. Check your config.yml file.');
});
it('should throw if collections is an array with a single null element in config', () => {
expect(() => {
validateConfig({ foo: 'bar', backend: { name: 'bar' }, media_folder: 'baz', collections: [null] });
}).toThrowError('Error in configuration file: Your `collections` must be an array with at least one element. Check your config.yml file.');
});
});
});

View File

@ -1,5 +1,5 @@
import yaml from "js-yaml";
import { set, defaultsDeep } from "lodash";
import { set, defaultsDeep, get } from "lodash";
import { authenticateUser } from "../actions/auth";
import * as publishModes from "../constants/publishModes";
@ -12,10 +12,6 @@ const defaults = {
};
export function applyDefaults(config) {
if (!("media_folder" in config)) {
throw new Error("Error in configuration file: A `media_folder` wasn't found. Check your config.yml file.");
}
// Make sure there is a public folder
set(defaults,
"public_folder",
@ -24,20 +20,40 @@ export function applyDefaults(config) {
return defaultsDeep(config, defaults);
}
function parseConfig(data) {
const config = yaml.safeLoad(data);
if (typeof CMS_ENV === "string" && config[CMS_ENV]) {
// TODO: Add tests and refactor
for (const key in config[CMS_ENV]) { // eslint-disable-line no-restricted-syntax
if (config[CMS_ENV].hasOwnProperty(key)) { // eslint-disable-line no-prototype-builtins
config[key] = config[CMS_ENV][key];
}
}
export function validateConfig(config) {
if (!get(config, 'backend')) {
throw new Error("Error in configuration file: A `backend` wasn't found. Check your config.yml file.");
}
if (!get(config, ['backend', 'name'])) {
throw new Error("Error in configuration file: A `backend.name` wasn't found. Check your config.yml file.");
}
if (typeof config.backend.name !== 'string') {
throw new Error("Error in configuration file: Your `backend.name` must be a string. Check your config.yml file.");
}
if (!get(config, 'media_folder')) {
throw new Error("Error in configuration file: A `media_folder` wasn\'t found. Check your config.yml file.");
}
if (typeof config.media_folder !== 'string') {
throw new Error("Error in configuration file: Your `media_folder` must be a string. Check your config.yml file.");
}
if (!get(config, 'collections')) {
throw new Error("Error in configuration file: A `collections` wasn\'t found. Check your config.yml file.");
}
if (!Array.isArray(config.collections) || config.collections.length === 0 || !config.collections[0]) {
throw new Error("Error in configuration file: Your `collections` must be an array with at least one element. Check your config.yml file.");
}
return config;
}
function parseConfig(data) {
const config = yaml.safeLoad(data);
if (typeof CMS_ENV === "string" && config[CMS_ENV]) {
Object.keys(config[CMS_ENV]).forEach((key) => {
config[key] = config[CMS_ENV][key];
});
}
return config;
}
export function configLoaded(config) {
return {
@ -81,6 +97,7 @@ export function loadConfig() {
return response.text();
})
.then(parseConfig)
.then(validateConfig)
.then(applyDefaults)
.then((config) => {
dispatch(configDidLoad(config));

View File

@ -1,20 +1,19 @@
import { OrderedMap, fromJS } from 'immutable';
import { has } from 'lodash';
import consoleError from '../lib/consoleError';
import { CONFIG_SUCCESS } from '../actions/config';
import { FILES, FOLDER } from '../constants/collectionTypes';
import { INFERABLE_FIELDS } from '../constants/fieldInference';
const hasProperty = (config, property) => ({}.hasOwnProperty.call(config, property));
const collections = (state = null, action) => {
const configCollections = action.payload && action.payload.collections;
switch (action.type) {
case CONFIG_SUCCESS:
return OrderedMap().withMutations((map) => {
(configCollections || []).forEach((configCollection) => {
if (hasProperty(configCollection, 'folder')) {
if (has(configCollection, 'folder')) {
configCollection.type = FOLDER; // eslint-disable-line no-param-reassign
} else if (hasProperty(configCollection, 'files')) {
} else if (has(configCollection, 'files')) {
configCollection.type = FILES; // eslint-disable-line no-param-reassign
} else {
throw new Error('Unknown collection type. Collections can be either Folder based or File based. Please verify your site configuration');