Skip to content

Commit

Permalink
[functional_test_runner] convert config and logger class to use creat…
Browse files Browse the repository at this point in the history
…e* functions
  • Loading branch information
spalger committed Feb 4, 2017
1 parent 05f6c2f commit fbd1115
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 95 deletions.
2 changes: 0 additions & 2 deletions src/functional_test_runner/__tests__/integration/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export { startupEs } from './es';
export { startupKibana } from './kibana';
export { runCli } from './run_cli';
1 change: 1 addition & 0 deletions src/functional_test_runner/functional_test_runner.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { resolve, relative } from 'path';

import { isArray, mapValues } from 'lodash';

import {
Expand Down
94 changes: 48 additions & 46 deletions src/functional_test_runner/lib/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,66 @@ import Joi from 'joi';
import { schema } from './schema';
import { createJoiValidationError } from '../user_errors';

const $values = Symbol('values');

export class Config {
constructor(settings) {
const { error, value } = schema.validate(settings);
if (error) {
throw createJoiValidationError(error);
export function createConfig(settings) {
class Config {
constructor() {
const { error, value } = schema.validate(settings);
if (error) {
throw createJoiValidationError(error);
}
this._values = value;
}
this[$values] = value;
}

has(key) {
function recursiveHasCheck(path, values, schema) {
if (!schema._inner) return false;
has(key) {
function recursiveHasCheck(path, values, schema) {
if (!schema._inner) return false;

// normalize child and pattern checks so we can iterate the checks in a single loop
const checks = [].concat(
// match children first, they have priority
(schema._inner.children || []).map(child => ({
test: key => child.key === key,
schema: child.schema
})),
// match patterns on any key that doesn't match an explicit child
(schema._inner.patterns || []).map(pattern => ({
test: key => pattern.regex.test(key) && has(values, key),
schema: pattern.rule
}))
);
// normalize child and pattern checks so we can iterate the checks in a single loop
const checks = [].concat(
// match children first, they have priority
(schema._inner.children || []).map(child => ({
test: key => child.key === key,
schema: child.schema
})),
// match patterns on any key that doesn't match an explicit child
(schema._inner.patterns || []).map(pattern => ({
test: key => pattern.regex.test(key) && has(values, key),
schema: pattern.rule
}))
);

for (const check of checks) {
if (!check.test(path[0])) {
continue;
}
for (const check of checks) {
if (!check.test(path[0])) {
continue;
}

if (path.length > 1) {
return recursiveHasCheck(path.slice(1), get(values, path[0]), check.schema);
}

if (path.length > 1) {
return recursiveHasCheck(path.slice(1), get(values, path[0]), check.schema);
return true;
}

return true;
return false;
}

return false;
const path = toPath(key);
if (!path.length) return true;
return recursiveHasCheck(path, this._values, schema);
}

const path = toPath(key);
if (!path.length) return true;
return recursiveHasCheck(path, this[$values], schema);
}
get(key, defaultValue) {
if (!this.has(key)) {
throw new Error(`Unknown config key "${key}"`);
}

get(key, defaultValue) {
if (!this.has(key)) {
throw new Error(`Unknown config key "${key}"`);
return cloneDeep(get(this._values, key, defaultValue), (v) => {
if (typeof v === 'function') {
return v;
}
});
}

return cloneDeep(get(this[$values], key, defaultValue), (v) => {
if (typeof v === 'function') {
return v;
}
});
}

return new Config();
}
2 changes: 1 addition & 1 deletion src/functional_test_runner/lib/config/index.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { readConfigFile } from './create_config';
export { readConfigFile } from './read_config_file';
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { relative } from 'path';

import { defaultsDeep } from 'lodash';

import { Config } from './config';
import { createConfig } from './config';
import { createInvalidConfigError } from '../';

export async function readConfigFile(log, configFile, settingOverrides) {
Expand Down Expand Up @@ -33,5 +34,5 @@ export async function readConfigFile(log, configFile, settingOverrides) {
})
);

return new Config(settings);
return createConfig(settings);
}
1 change: 0 additions & 1 deletion src/functional_test_runner/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export { createLifecycle } from './lifecycle';
export { readConfigFile } from './config';
export { createLog } from './log';
export { modifyUrl } from './url';
export { ConsoleReporterProvider } from './reporters';
export { createProviderCollection } from './provider';
export { runTests } from './run_tests';
Expand Down
17 changes: 10 additions & 7 deletions src/functional_test_runner/lib/load_tracer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { resolve } from 'path';

import { isArray } from 'lodash';
import { createGenericUserError } from './';

import {
createGenericUserError,
isUserError,
} from './';

const globalLoadPath = [];
function getPath(startAt = 0) {
Expand All @@ -17,23 +21,22 @@ function addPathToMessage(message, startAt) {
return `${message} -- from ${path}`;
}

export function loadTracer(ident, descrption, load) {
const isCircular = globalLoadPath.find(step => step.ident === ident);
export function loadTracer(identity, descrption, load) {
const isCircular = globalLoadPath.find(step => step.identity === identity);
if (isCircular) {
throw createGenericUserError(addPathToMessage(`Circular reference to "${descrption}"`));
}

try {
globalLoadPath.unshift({ ident, descrption });
globalLoadPath.unshift({ identity, descrption });
return load();
} catch (err) {
if (err.__fromLoadTracer) {
if (isUserError(err)) {
throw err;
}

const wrapped = new Error(addPathToMessage(`Failure to load ${descrption}`, 1));
const wrapped = createGenericUserError(addPathToMessage(`Failure to load ${descrption}`, 1));
wrapped.stack = `${wrapped.message}\n\n Original Error: ${err.stack}`;
wrapped.__fromLoadTracer = true;
throw wrapped;
} finally {
globalLoadPath.shift();
Expand Down
31 changes: 16 additions & 15 deletions src/functional_test_runner/lib/log.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import { format } from 'util';

import { magenta, yellow, red, blue, brightBlack } from 'ansicolors';

export function createLog(logLevel, output, lifecycle) {
let indentString = '';

function write(...args) {
format(...args).split('\n').forEach((line, i) => {
const subLineIndent = i === 0 ? '' : ' ';
const indent = !indentString ? '' : indentString.slice(0, -1) + (i === 0 && line[0] === '-' ? '└' : '│');
output.write(`${indent}${subLineIndent}${line}\n`);
});
}

class Log {
constructor() {
lifecycle.on('phaseStart', name => {
Expand All @@ -22,22 +31,22 @@ export function createLog(logLevel, output, lifecycle) {

verbose = (...args) => {
if (logLevel < 4) return;
this._write(' %s ', magenta('sill'), format(...args));
write(' %s ', magenta('sill'), format(...args));
}

debug = (...args) => {
if (logLevel < 3) return;
this._write(' %s ', brightBlack('debg'), format(...args));
write(' %s ', brightBlack('debg'), format(...args));
}

warning = (...args) => {
if (logLevel < 2) return;
this._write(' %s ', yellow('warn'), format(...args));
write(' %s ', yellow('warn'), format(...args));
}

info = (...args) => {
if (logLevel < 2) return;
this._write(' %s ', blue('info'), format(...args));
write(' %s ', blue('info'), format(...args));
}

error = (err) => {
Expand All @@ -47,25 +56,17 @@ export function createLog(logLevel, output, lifecycle) {
err = new Error(`"${err}" thrown`);
}

this._write('%s ', red('ERROR'), err.stack || err.message || err);
write('%s ', red('ERROR'), err.stack || err.message || err);
}

writeLn = (...args) => {
if (logLevel < 2) return;
this._write(...args);
write(...args);
}

writeErrorLn = (...args) => {
if (logLevel < 1) return;
this._write(...args);
}

_write(...args) {
format(...args).split('\n').forEach((line, i) => {
const subLineIndent = i === 0 ? '' : ' ';
const indent = !indentString ? '' : indentString.slice(0, -1) + (i === 0 && line[0] === '-' ? '└' : '│');
output.write(`${indent}${subLineIndent}${line}\n`);
});
write(...args);
}
}

Expand Down
20 changes: 0 additions & 20 deletions src/functional_test_runner/lib/url.js

This file was deleted.

6 changes: 5 additions & 1 deletion src/functional_test_runner/lib/user_errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,17 @@ export function createFailedTestCasesError(failureCount) {
);
}

export function isUserError(error) {
return error && !!error.isUserError;
}

export function handleTopLevelError(log, error) {
if (!log) {
console.log('FATAL ERROR', error.stack || error.message);
return;
}

if (error.isUserError) {
if (isUserError(error)) {
log.error(error.message);
return;
}
Expand Down

0 comments on commit fbd1115

Please sign in to comment.