This allows extra documents in a yaml config file to be embeded as

hosts.

This makes the syntax for defining multiple hosts a lot nicer and faster
to use.
This commit is contained in:
David Diaz 2018-07-31 23:17:31 -06:00
parent 8849fe1e90
commit 5af119e915
10 changed files with 197 additions and 210 deletions

View File

@ -10,6 +10,9 @@ Config {
}, },
"HOSTS": Array [], "HOSTS": Array [],
"PLUGINS": Plugins { "PLUGINS": Plugins {
"autoload": Array [
"std",
],
"context": Object { "context": Object {
"createReadStream": [Function], "createReadStream": [Function],
}, },

View File

@ -10,7 +10,20 @@ const openConfigFile = configFile => {
throw new Error(`The config file, ${configFile} was not found.`); throw new Error(`The config file, ${configFile} was not found.`);
} }
return yaml.safeLoad(fs.readFileSync(configFile, 'utf-8')); let config;
yaml.safeLoadAll(fs.readFileSync(configFile, 'utf-8'), doc => {
if (typeof config === 'undefined') {
config = doc;
} else {
if (typeof config.hosts === 'undefined') {
config.hosts = [];
}
config.hosts.push(doc);
}
});
return config;
}; };
const loadConfig = (configFile, params = []) => { const loadConfig = (configFile, params = []) => {

View File

@ -1,4 +1,5 @@
version: 1 version: 1
endpoint: http://httpbin.org
environment: environment:
the: the:
@ -8,25 +9,14 @@ defaults:
headers: headers:
hello: 'Hello2' hello: 'Hello2'
GET http://jsonplaceholder.typicode.com/posts/1: POST /anything:
alias: a-post alias: anything
headers: payload:
hello: $jpa2:get-post.body.id title: $jpa:get-post.body.title
hosts:
- host: jpa
endpoint: http://jsonplaceholder.typicode.com
GET /posts/$env.the.post: get-post
GET /users/$jpa:get-post.body.userId: hello
- host: jpa2
endpoint: http://jsonplaceholder.typicode.com
defaults:
headers: false
GET /posts/$jpa:get-post.body.id:
alias: get-post
---
host: jpa
endpoint: http://jsonplaceholder.typicode.com
GET /posts/$env.the.post: get-post
GET /users/$jpa:get-post.body.userId: hello

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Beau's config Loader. should create a request list 1`] = ` exports[`Beau's config Loader. should load the config 1`] = `
Beau { Beau {
"config": Config { "config": Config {
"COOKIEJAR": false, "COOKIEJAR": false,
@ -9,10 +9,13 @@ Beau {
"authentication": "hello", "authentication": "hello",
}, },
}, },
"ENDPOINT": "http://jsonplaceholder.typicode.com", "ENDPOINT": "http://example.com",
"ENVIRONMENT": Object {}, "ENVIRONMENT": Object {},
"HOSTS": Array [], "HOSTS": Array [],
"PLUGINS": Plugins { "PLUGINS": Plugins {
"autoload": Array [
"std",
],
"context": Object {}, "context": Object {},
"registry": Object { "registry": Object {
"dynamicValues": Array [], "dynamicValues": Array [],
@ -20,27 +23,7 @@ Beau {
"preRequestModifiers": Array [], "preRequestModifiers": Array [],
}, },
}, },
"REQUESTS": Array [ "REQUESTS": Array [],
Object {
"ALIAS": "get-post",
"COOKIEJAR": false,
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
},
"REQUEST": "GET /posts/1",
},
Object {
"ALIAS": "user",
"COOKIEJAR": false,
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
"hello": "world",
},
"REQUEST": "GET /user",
},
],
"VERSION": 1, "VERSION": 1,
"configKeys": Array [ "configKeys": Array [
"VERSION", "VERSION",
@ -53,43 +36,82 @@ Beau {
], ],
}, },
"requests": RequestList { "requests": RequestList {
"REQUESTS": Array [ "PLUGINS": Plugins {
Object { "autoload": Array [
"ALIAS": "get-post", "std",
"COOKIEJAR": false, ],
"ENDPOINT": "http://jsonplaceholder.typicode.com", "context": Object {},
"HEADERS": Object { "registry": Object {
"authentication": "hello", "dynamicValues": Array [],
}, "postRequestModifiers": Array [],
"REQUEST": "GET /posts/1", "preRequestModifiers": Array [],
}, },
Object { },
"ALIAS": "user", "REQUESTS": Array [],
"COOKIEJAR": false,
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
"hello": "world",
},
"REQUEST": "GET /user",
},
],
"cache": RequestCache { "cache": RequestCache {
"$cache": Object { "$cache": Object {
"env": Object {}, "env": Object {},
}, },
}, },
"config": Config { "list": Array [],
},
}
`;
exports[`Beau's config Loader. should load the request list using the configuration 1`] = `
RequestList {
"PLUGINS": Plugins {
"autoload": Array [
"std",
],
"context": Object {},
"registry": Object {
"dynamicValues": Array [],
"postRequestModifiers": Array [],
"preRequestModifiers": Array [],
},
},
"REQUESTS": Array [
Object {
"ALIAS": "get-post",
"COOKIEJAR": false, "COOKIEJAR": false,
"DEFAULTS": Object { "ENDPOINT": "http://example.com",
"headers": Object { "REQUEST": "GET /posts/1",
"authentication": "hello", },
}, Object {
"ALIAS": "user",
"COOKIEJAR": false,
"ENDPOINT": "http://example.com",
"HEADERS": Object {
"hello": "world",
}, },
"ENDPOINT": "http://jsonplaceholder.typicode.com", "REQUEST": "GET /user",
"ENVIRONMENT": Object {}, },
"HOSTS": Array [], ],
"PLUGINS": Plugins { "cache": RequestCache {
"$cache": Object {
"env": Object {},
},
},
"list": Array [
Request {
"ALIAS": "get-post",
"COOKIEJAR": false,
"DEPENDENCIES": Set {},
"ENDPOINT": "http://example.com",
"PATH": "/posts/1",
"REQUEST": "GET /posts/1",
"VERB": "GET",
"originalRequest": Object {
"ALIAS": "get-post",
"COOKIEJAR": false,
"ENDPOINT": "http://example.com",
"REQUEST": "GET /posts/1",
},
"plugins": Plugins {
"autoload": Array [
"std",
],
"context": Object {}, "context": Object {},
"registry": Object { "registry": Object {
"dynamicValues": Array [], "dynamicValues": Array [],
@ -97,100 +119,39 @@ Beau {
"preRequestModifiers": Array [], "preRequestModifiers": Array [],
}, },
}, },
"REQUESTS": Array [
Object {
"ALIAS": "get-post",
"COOKIEJAR": false,
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
},
"REQUEST": "GET /posts/1",
},
Object {
"ALIAS": "user",
"COOKIEJAR": false,
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
"hello": "world",
},
"REQUEST": "GET /user",
},
],
"VERSION": 1,
"configKeys": Array [
"VERSION",
"ENDPOINT",
"PLUGINS",
"DEFAULTS",
"ENVIRONMENT",
"HOSTS",
"COOKIEJAR",
],
}, },
"list": Array [ Request {
Request { "ALIAS": "user",
"ALIAS": "get-post", "COOKIEJAR": false,
"COOKIEJAR": false, "DEPENDENCIES": Set {},
"DEPENDENCIES": Set {}, "ENDPOINT": "http://example.com",
"ENDPOINT": "http://jsonplaceholder.typicode.com", "HEADERS": Object {
"HEADERS": Object { "hello": "world",
"authentication": "hello",
},
"PATH": "/posts/1",
"REQUEST": "GET /posts/1",
"VERB": "GET",
"originalRequest": Object {
"ALIAS": "get-post",
"COOKIEJAR": false,
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object {
"authentication": "hello",
},
"REQUEST": "GET /posts/1",
},
"plugins": Plugins {
"context": Object {},
"registry": Object {
"dynamicValues": Array [],
"postRequestModifiers": Array [],
"preRequestModifiers": Array [],
},
},
}, },
Request { "PATH": "/user",
"REQUEST": "GET /user",
"VERB": "GET",
"originalRequest": Object {
"ALIAS": "user", "ALIAS": "user",
"COOKIEJAR": false, "COOKIEJAR": false,
"DEPENDENCIES": Set {}, "ENDPOINT": "http://example.com",
"ENDPOINT": "http://jsonplaceholder.typicode.com",
"HEADERS": Object { "HEADERS": Object {
"authentication": "hello",
"hello": "world", "hello": "world",
}, },
"PATH": "/user",
"REQUEST": "GET /user", "REQUEST": "GET /user",
"VERB": "GET", },
"originalRequest": Object { "plugins": Plugins {
"ALIAS": "user", "autoload": Array [
"COOKIEJAR": false, "std",
"ENDPOINT": "http://jsonplaceholder.typicode.com", ],
"HEADERS": Object { "context": Object {},
"authentication": "hello", "registry": Object {
"hello": "world", "dynamicValues": Array [],
}, "postRequestModifiers": Array [],
"REQUEST": "GET /user", "preRequestModifiers": Array [],
},
"plugins": Plugins {
"context": Object {},
"registry": Object {
"dynamicValues": Array [],
"postRequestModifiers": Array [],
"preRequestModifiers": Array [],
},
}, },
}, },
], },
}, ],
} }
`; `;

View File

@ -42,6 +42,9 @@ Config {
}, },
], ],
"PLUGINS": Plugins { "PLUGINS": Plugins {
"autoload": Array [
"std",
],
"context": Object {}, "context": Object {},
"registry": Object { "registry": Object {
"dynamicValues": Array [], "dynamicValues": Array [],
@ -130,10 +133,13 @@ Config {
"authentication": "hello", "authentication": "hello",
}, },
}, },
"ENDPOINT": "http://jsonplaceholder.typicode.com", "ENDPOINT": "http://example.com",
"ENVIRONMENT": Object {}, "ENVIRONMENT": Object {},
"HOSTS": Array [], "HOSTS": Array [],
"PLUGINS": Plugins { "PLUGINS": Plugins {
"autoload": Array [
"std",
],
"context": Object {}, "context": Object {},
"registry": Object { "registry": Object {
"dynamicValues": Array [], "dynamicValues": Array [],
@ -145,7 +151,7 @@ Config {
Object { Object {
"ALIAS": "get-post", "ALIAS": "get-post",
"COOKIEJAR": false, "COOKIEJAR": false,
"ENDPOINT": "http://jsonplaceholder.typicode.com", "ENDPOINT": "http://example.com",
"HEADERS": Object { "HEADERS": Object {
"authentication": "hello", "authentication": "hello",
}, },
@ -154,7 +160,7 @@ Config {
Object { Object {
"ALIAS": "user", "ALIAS": "user",
"COOKIEJAR": false, "COOKIEJAR": false,
"ENDPOINT": "http://jsonplaceholder.typicode.com", "ENDPOINT": "http://example.com",
"HEADERS": Object { "HEADERS": Object {
"authentication": "hello", "authentication": "hello",
"hello": "world", "hello": "world",

View File

@ -20,6 +20,7 @@ Object {
exports[`Beau's plugin system shouldn't do anything when given an empty array. 1`] = ` exports[`Beau's plugin system shouldn't do anything when given an empty array. 1`] = `
Plugins { Plugins {
"autoload": Array [],
"context": Object {}, "context": Object {},
"registry": Object { "registry": Object {
"dynamicValues": Array [], "dynamicValues": Array [],

View File

@ -8,16 +8,28 @@ const requireg = require('requireg');
requireg.resolving = false; requireg.resolving = false;
describe(`Beau's config Loader.`, () => { describe(`Beau's config Loader.`, () => {
it('should create a request list', () => { it('should load the config', () => {
moduleVersion.mockReturnValue(1); moduleVersion.mockReturnValue(1);
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
version: 1 version: 1
endpoint: 'http://jsonplaceholder.typicode.com' endpoint: 'http://example.com'
defaults: defaults:
headers: headers:
authentication: hello authentication: hello
`);
const beau = new Beau(doc);
expect(beau).toMatchSnapshot();
});
it(`should load the request list using the configuration`, () => {
moduleVersion.mockReturnValue(1);
const doc = yaml.safeLoad(`
version: 1
endpoint: 'http://example.com'
GET /posts/1: get-post GET /posts/1: get-post
GET /user: GET /user:
@ -27,8 +39,7 @@ describe(`Beau's config Loader.`, () => {
`); `);
const beau = new Beau(doc); const beau = new Beau(doc);
expect(beau.requests).toMatchSnapshot();
expect(beau).toMatchSnapshot();
}); });
it('should display a warning if the module version and the beau file version are different', () => { it('should display a warning if the module version and the beau file version are different', () => {

View File

@ -5,21 +5,21 @@ const requireg = require('requireg');
requireg.resolving = false; requireg.resolving = false;
describe('Config', () => { describe('Config', () => {
it('should load valid config keys', () => { it('should load valid config keys', () => {
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
version: 1 version: 1
endpoint: http://martianwabbit.com endpoint: http://martianwabbit.com
shouldntBeAdded: true shouldntBeAdded: true
`); `);
const config = new Config(doc); const config = new Config(doc);
expect(config.ENDPOINT).toBe(doc.endpoint); expect(config.ENDPOINT).toBe(doc.endpoint);
expect(config.VERSION).toBe(doc.version); expect(config.VERSION).toBe(doc.version);
expect(config.shouldntBeAdded).toBeUndefined(); expect(config.shouldntBeAdded).toBeUndefined();
}); });
it('should load requests', () => { it('should load requests', () => {
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
endpoint: http://example.com endpoint: http://example.com
GET /profile: get-profile GET /profile: get-profile
@ -31,14 +31,14 @@ describe('Config', () => {
hello: world hello: world
`); `);
const config = new Config(doc); const config = new Config(doc);
expect(Object.keys(config.REQUESTS).length).toBe(4); expect(Object.keys(config.REQUESTS).length).toBe(4);
}); });
it('should set up defaults for all requests', () => { it('should set up defaults for all requests', () => {
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
version: 1 version: 1
endpoint: 'http://jsonplaceholder.typicode.com' endpoint: 'http://example.com'
defaults: defaults:
HEADERS: HEADERS:
@ -51,16 +51,16 @@ describe('Config', () => {
hello: world hello: world
`); `);
const config = new Config(doc); const config = new Config(doc);
expect(config).toMatchSnapshot(); expect(config).toMatchSnapshot();
Object.values(config.REQUESTS).forEach(r => { Object.values(config.REQUESTS).forEach(r => {
expect(r.HEADERS.authentication).toMatch('hello'); expect(r.HEADERS.authentication).toMatch('hello');
});
}); });
});
it('should load multiple hosts', () => { it('should load multiple hosts', () => {
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
version: 1 version: 1
endpoint: http://example.org endpoint: http://example.org
@ -99,13 +99,13 @@ describe('Config', () => {
GET /posts: posts GET /posts: posts
`); `);
let config = new Config(doc); let config = new Config(doc);
expect(config).toMatchSnapshot(); expect(config).toMatchSnapshot();
}); });
it('should namespace all aliases within an host', () => { it('should namespace all aliases within an host', () => {
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
hosts: hosts:
- host: test1 - host: test1
endpoint: http://example.com endpoint: http://example.com
@ -115,14 +115,14 @@ describe('Config', () => {
GET /posts: posts GET /posts: posts
`); `);
let config = new Config(doc); let config = new Config(doc);
expect(config.REQUESTS[0].ALIAS).toBe('test1:posts'); expect(config.REQUESTS[0].ALIAS).toBe('test1:posts');
expect(config.REQUESTS[1].ALIAS).toBe('test2:posts'); expect(config.REQUESTS[1].ALIAS).toBe('test2:posts');
}); });
it(`should throw if host doesn't have a host key`, () => { it(`should throw if host doesn't have a host key`, () => {
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
hosts: hosts:
- endpoint: http://example.com - endpoint: http://example.com
GET /posts: posts GET /posts: posts
@ -132,11 +132,11 @@ describe('Config', () => {
GET /posts: posts GET /posts: posts
`); `);
expect(() => new Config(doc)).toThrow(); expect(() => new Config(doc)).toThrow();
}); });
it(`should merge host settings with global settings`, () => { it(`should merge host settings with global settings`, () => {
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
defaults: defaults:
headers: headers:
hello: 1 hello: 1
@ -154,7 +154,7 @@ describe('Config', () => {
GET /posts: posts GET /posts: posts
`); `);
let config = new Config(doc); let config = new Config(doc);
expect(config.REQUESTS[0].HEADERS.hello).toBe(1); expect(config.REQUESTS[0].HEADERS.hello).toBe(1);
}); });
}); });

View File

@ -14,7 +14,9 @@ class Plugins {
this.context = {}; this.context = {};
this.loadPlugins(autoload.concat(plugins)); this.autoload = autoload;
this.loadPlugins(plugins.concat(this.autoload));
} }
normalizePlugins(plugins) { normalizePlugins(plugins) {
@ -52,7 +54,7 @@ class Plugins {
const plugin = requireg(module); const plugin = requireg(module);
new plugin(this, plugins[name]); new plugin(this, plugins[name]);
} else { } else {
if (name === 'std') return; if (this.autoload.includes(name)) return;
console.warn( console.warn(
`Plugin ${name} couldn't be found. It is available globally?` `Plugin ${name} couldn't be found. It is available globally?`

View File

@ -3,13 +3,13 @@ const RequestCache = require('./requestCache');
class RequestList { class RequestList {
constructor(config = { REQUESTS: [] }) { constructor(config = { REQUESTS: [] }) {
this.config = config; this.PLUGINS = config.PLUGINS;
this.REQUESTS = config.REQUESTS; this.REQUESTS = config.REQUESTS;
this.list = this.loadRequests(); this.list = this.loadRequests();
this.cache = new RequestCache(); this.cache = new RequestCache();
this.cache.add(`env`, this.config.ENVIRONMENT); this.cache.add(`env`, config.ENVIRONMENT);
} }
async execByAlias(alias) { async execByAlias(alias) {
@ -46,7 +46,7 @@ class RequestList {
let requests = []; let requests = [];
this.REQUESTS.forEach(request => { this.REQUESTS.forEach(request => {
try { try {
requests.push(new Request(request, this.config.PLUGINS)); requests.push(new Request(request, this.PLUGINS));
} catch (e) { } catch (e) {
throw new Error(`${request.request} was ignored: ${e}`); throw new Error(`${request.request} was ignored: ${e}`);
} }