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('config', () => {
describe('applyDefaults', () => { 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', () => { it('should set publish_mode if not set', () => {
expect(config.applyDefaults({ expect(applyDefaults({
foo: 'bar', foo: 'bar',
media_folder: 'path/to/media', media_folder: 'path/to/media',
})).toEqual({ })).toEqual({
@ -21,7 +15,7 @@ describe('config', () => {
}); });
it('should set publish_mode from config', () => { it('should set publish_mode from config', () => {
expect(config.applyDefaults({ expect(applyDefaults({
foo: 'bar', foo: 'bar',
publish_mode: 'complex', publish_mode: 'complex',
media_folder: 'path/to/media', media_folder: 'path/to/media',
@ -34,7 +28,7 @@ describe('config', () => {
}); });
it('should set public_folder based on media_folder if not set', () => { it('should set public_folder based on media_folder if not set', () => {
expect(config.applyDefaults({ expect(applyDefaults({
foo: 'bar', foo: 'bar',
media_folder: 'path/to/media', media_folder: 'path/to/media',
})).toEqual({ })).toEqual({
@ -46,7 +40,7 @@ describe('config', () => {
}); });
it('should not overwrite public_folder if set', () => { it('should not overwrite public_folder if set', () => {
expect(config.applyDefaults({ expect(applyDefaults({
foo: 'bar', foo: 'bar',
media_folder: 'path/to/media', media_folder: 'path/to/media',
public_folder: '/publib/path', 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 yaml from "js-yaml";
import { set, defaultsDeep } from "lodash"; import { set, defaultsDeep, get } from "lodash";
import { authenticateUser } from "../actions/auth"; import { authenticateUser } from "../actions/auth";
import * as publishModes from "../constants/publishModes"; import * as publishModes from "../constants/publishModes";
@ -12,10 +12,6 @@ const defaults = {
}; };
export function applyDefaults(config) { 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 // Make sure there is a public folder
set(defaults, set(defaults,
"public_folder", "public_folder",
@ -24,20 +20,40 @@ export function applyDefaults(config) {
return defaultsDeep(config, defaults); return defaultsDeep(config, defaults);
} }
function parseConfig(data) { export function validateConfig(config) {
const config = yaml.safeLoad(data); if (!get(config, 'backend')) {
if (typeof CMS_ENV === "string" && config[CMS_ENV]) { throw new Error("Error in configuration file: A `backend` wasn't found. Check your config.yml file.");
// 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];
} }
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; 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) { export function configLoaded(config) {
return { return {
@ -81,6 +97,7 @@ export function loadConfig() {
return response.text(); return response.text();
}) })
.then(parseConfig) .then(parseConfig)
.then(validateConfig)
.then(applyDefaults) .then(applyDefaults)
.then((config) => { .then((config) => {
dispatch(configDidLoad(config)); dispatch(configDidLoad(config));

View File

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