mirror of https://github.com/Seich/Beau.git
Added a new top-level setting: defaults.
Defaults allow you to set default settings for all requests. You can pass any configuration value and it'll be merged with any values the request already has allowing you to write even less repetitive code.
This commit is contained in:
parent
78a12e99f2
commit
40abf85a78
|
|
@ -4,7 +4,11 @@
|
|||
|
||||
<h1 align="center">Beau</h1>
|
||||
<p align="center">Testing JSON APIs made easy.</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://codeclimate.com/github/Seich/Beau/maintainability"><img src="https://api.codeclimate.com/v1/badges/bc2de4d71893d6a2d18b/maintainability" /></a>
|
||||
<a href="https://codeclimate.com/github/Seich/Beau/test_coverage"><img src="https://api.codeclimate.com/v1/badges/bc2de4d71893d6a2d18b/test_coverage" /></a>
|
||||
<a href="https://circleci.com/gh/Seich/Beau/tree/master"><img src="https://circleci.com/gh/Seich/Beau/tree/master.svg?style=svg" alt="CircleCI"></a>
|
||||
</p>
|
||||
## What is Beau?
|
||||
Beau, is a CLI that executes HTTP requests based on a YAML configuration file. This makes testing easy, it allows you to share test requests with others as part of your repo.
|
||||
|
||||
|
|
@ -33,7 +37,7 @@ Beau, is a CLI that executes HTTP requests based on a YAML configuration file. T
|
|||
## Example Configuration File
|
||||
|
||||
version: 1
|
||||
host: https://example.com/api/
|
||||
endpoint: https://example.com/api/
|
||||
|
||||
POST /session:
|
||||
ALIAS: session
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Beau's config Loader. should set up defaults for all requests 1`] = `
|
||||
Beau {
|
||||
"config": Object {
|
||||
"CACHE": false,
|
||||
"DEFAULTS": Object {
|
||||
"headers": Object {
|
||||
"authentication": "hello",
|
||||
},
|
||||
},
|
||||
"ENDPOINT": "http://jsonplaceholder.typicode.com",
|
||||
"PLUGINS": Array [],
|
||||
"VERSION": 1,
|
||||
},
|
||||
"configKeys": Array [
|
||||
"VERSION",
|
||||
"CACHE",
|
||||
"ENDPOINT",
|
||||
"PLUGINS",
|
||||
"DEFAULTS",
|
||||
],
|
||||
"defaults": Object {
|
||||
"CACHE": false,
|
||||
"DEFAULTS": Object {
|
||||
"headers": Object {
|
||||
"authentication": "hello",
|
||||
},
|
||||
},
|
||||
"ENDPOINT": "http://jsonplaceholder.typicode.com",
|
||||
"PLUGINS": Array [],
|
||||
"VERSION": 1,
|
||||
},
|
||||
"requests": RequestList {
|
||||
"cache": RequestCache {
|
||||
"$cache": Object {},
|
||||
},
|
||||
"config": Object {
|
||||
"CACHE": false,
|
||||
"DEFAULTS": Object {
|
||||
"headers": Object {
|
||||
"authentication": "hello",
|
||||
},
|
||||
},
|
||||
"ENDPOINT": "http://jsonplaceholder.typicode.com",
|
||||
"PLUGINS": Array [],
|
||||
"VERSION": 1,
|
||||
},
|
||||
"list": Array [
|
||||
Request {
|
||||
"ALIAS": "get-post",
|
||||
"DEPENDENCIES": Set {},
|
||||
"DOCUMENTATION": undefined,
|
||||
"ENDPOINT": "http://jsonplaceholder.typicode.com/posts/1",
|
||||
"HEADERS": Object {
|
||||
"authentication": "hello",
|
||||
},
|
||||
"PARAMS": undefined,
|
||||
"PAYLOAD": undefined,
|
||||
"VERB": "GET",
|
||||
"originalRequest": Object {
|
||||
"ALIAS": "get-post",
|
||||
"ENDPOINT": "http://jsonplaceholder.typicode.com",
|
||||
"headers": Object {
|
||||
"authentication": "hello",
|
||||
},
|
||||
"request": "GET /posts/1",
|
||||
},
|
||||
},
|
||||
Request {
|
||||
"ALIAS": "user",
|
||||
"DEPENDENCIES": Set {},
|
||||
"DOCUMENTATION": undefined,
|
||||
"ENDPOINT": "http://jsonplaceholder.typicode.com/user",
|
||||
"HEADERS": Object {
|
||||
"authentication": "hello",
|
||||
"hello": "world",
|
||||
},
|
||||
"PARAMS": undefined,
|
||||
"PAYLOAD": undefined,
|
||||
"VERB": "GET",
|
||||
"originalRequest": Object {
|
||||
"ENDPOINT": "http://jsonplaceholder.typicode.com",
|
||||
"alias": "user",
|
||||
"headers": Object {
|
||||
"authentication": "hello",
|
||||
"hello": "world",
|
||||
},
|
||||
"request": "GET /user",
|
||||
},
|
||||
},
|
||||
],
|
||||
"modifiers": Array [],
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
|
@ -48,7 +48,7 @@ Array [
|
|||
},
|
||||
Object {
|
||||
"alias": "show",
|
||||
"host": "http://martianwabbit.com",
|
||||
"endpoint": "http://martianwabbit.com",
|
||||
"request": "GET /user",
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,23 +1,44 @@
|
|||
const Beau = require('../beau');
|
||||
const yaml = require('js-yaml');
|
||||
const Beau = require('../beau');
|
||||
|
||||
describe(`Beau's config Loader.`, () => {
|
||||
it('Should only load valid configuration keys', () => {
|
||||
let host = 'http://martianwabbit.com';
|
||||
let version = 1;
|
||||
let cache = false;
|
||||
let shouldntBeAdded = true;
|
||||
it('Should only load valid configuration keys', () => {
|
||||
const doc = yaml.safeLoad(`
|
||||
version: 1
|
||||
endpoint: http://martianwabbit.com
|
||||
cache: false
|
||||
shouldntBeAdded: true
|
||||
`);
|
||||
|
||||
let beau = new Beau({
|
||||
version,
|
||||
host,
|
||||
cache,
|
||||
shouldntBeAdded
|
||||
});
|
||||
const beau = new Beau(doc);
|
||||
|
||||
expect(beau.config.HOST).toBe(host);
|
||||
expect(beau.config.CACHE).toBe(cache);
|
||||
expect(beau.config.VERSION).toBe(version);
|
||||
expect(beau.config.shouldntBeAdded).toBeUndefined();
|
||||
});
|
||||
expect(beau.config.ENDPOINT).toBe(doc.endpoint);
|
||||
expect(beau.config.CACHE).toBe(doc.cache);
|
||||
expect(beau.config.VERSION).toBe(doc.version);
|
||||
expect(beau.config.shouldntBeAdded).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should set up defaults for all requests', () => {
|
||||
const doc = yaml.safeLoad(`
|
||||
version: 1
|
||||
endpoint: 'http://jsonplaceholder.typicode.com'
|
||||
|
||||
defaults:
|
||||
headers:
|
||||
authentication: hello
|
||||
|
||||
GET /posts/1: get-post
|
||||
GET /user:
|
||||
alias: user
|
||||
headers:
|
||||
hello: world
|
||||
`);
|
||||
|
||||
const beau = new Beau(doc);
|
||||
|
||||
expect(beau).toMatchSnapshot();
|
||||
beau.requests.list.forEach(r => {
|
||||
expect(r.HEADERS.authentication).toMatch('hello');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ describe('Request', () => {
|
|||
beforeEach(() => {
|
||||
req = {
|
||||
request: 'POST /user',
|
||||
host: 'http://martianwabbit.com',
|
||||
endpoint: 'http://martianwabbit.com',
|
||||
alias: 'update',
|
||||
params: {
|
||||
userId: '$profile.UserId'
|
||||
|
|
@ -31,7 +31,7 @@ describe('Request', () => {
|
|||
|
||||
request = new Request(req);
|
||||
requestWithoutDependencies = new Request({
|
||||
host: 'http://martianwabbit.com',
|
||||
endpoint: 'http://martianwabbit.com',
|
||||
request: 'GET /user',
|
||||
alias: 'show'
|
||||
});
|
||||
|
|
@ -41,7 +41,7 @@ describe('Request', () => {
|
|||
|
||||
test('It should load up the given request', () => {
|
||||
expect(request.VERB).toBe('POST');
|
||||
expect(request.ENDPOINT).toBe(req.host + '/user');
|
||||
expect(request.ENDPOINT).toBe(req.endpoint + '/user');
|
||||
expect(request.HEADERS).toBeDefined();
|
||||
expect(request.PAYLOAD).toBeDefined();
|
||||
expect(request.PARAMS).toBeDefined();
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ const RequestList = require('../requestList');
|
|||
const requestPromiseNativeMock = require('request-promise-native');
|
||||
|
||||
describe('RequestList', () => {
|
||||
const host = 'http://martianwabbit.com';
|
||||
const endpoint = 'http://martianwabbit.com';
|
||||
const doc = {
|
||||
'POST /session': null,
|
||||
'Not a Request': null,
|
||||
'GET /post': 'get-posts',
|
||||
'GET /post': { alias: 'get-posts' },
|
||||
'POST /user': {
|
||||
alias: 'user',
|
||||
payload: {
|
||||
|
|
@ -20,7 +20,7 @@ describe('RequestList', () => {
|
|||
beforeEach(() => {
|
||||
requestPromiseNativeMock.fail = false;
|
||||
requests = new RequestList(doc, {
|
||||
HOST: host,
|
||||
ENDPOINT: endpoint,
|
||||
PLUGINS: [
|
||||
{
|
||||
'beau-jwt': {
|
||||
|
|
@ -40,7 +40,7 @@ describe('RequestList', () => {
|
|||
|
||||
expect(requests.list.length).toBe(3);
|
||||
expect(request.VERB).toBe('POST');
|
||||
expect(request.ENDPOINT).toBe(host + '/session');
|
||||
expect(request.ENDPOINT).toBe(endpoint + '/session');
|
||||
});
|
||||
|
||||
it('should fetch dependencies', () => {
|
||||
|
|
|
|||
32
beau.js
32
beau.js
|
|
@ -1,17 +1,43 @@
|
|||
const deepMerge = require('deepmerge');
|
||||
|
||||
const RequestList = require('./requestList');
|
||||
const requestRegex = require('./shared').requestRegex;
|
||||
|
||||
class Beau {
|
||||
constructor(doc) {
|
||||
this.defaults = {
|
||||
VERSION: 1,
|
||||
CACHE: false,
|
||||
HOST: '',
|
||||
PLUGINS: []
|
||||
ENDPOINT: '',
|
||||
PLUGINS: [],
|
||||
DEFAULTS: []
|
||||
};
|
||||
|
||||
this.configKeys = Object.keys(this.defaults);
|
||||
this.config = this.loadConfig(doc);
|
||||
this.requests = new RequestList(doc, this.config);
|
||||
this.requests = this.getRequests(doc);
|
||||
this.requests = new RequestList(this.requests, this.config);
|
||||
}
|
||||
|
||||
getRequests(doc) {
|
||||
let requests = Object.keys(doc).filter(key => {
|
||||
return requestRegex.test(key);
|
||||
});
|
||||
|
||||
let results = {};
|
||||
requests.forEach(r => {
|
||||
if (typeof doc[r] === 'string') {
|
||||
results[r] = {
|
||||
ALIAS: doc[r]
|
||||
};
|
||||
} else {
|
||||
results[r] = doc[r];
|
||||
}
|
||||
|
||||
results[r] = deepMerge(this.config.DEFAULTS, results[r]);
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
loadConfig(doc) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
machine:
|
||||
node:
|
||||
version: 8.9.3
|
||||
|
||||
dependencies:
|
||||
post:
|
||||
- npm install -g codeclimate-test-reporter
|
||||
|
||||
test:
|
||||
pre:
|
||||
- npm run test:coverage
|
||||
- codeclimate-test-reporter < ./coverage/lcov.info
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
VERSION: 1
|
||||
HOST: https://api.github.com
|
||||
ENDPOINT: https://api.github.com
|
||||
|
||||
auth: &auth
|
||||
HEADERS:
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
version: 1
|
||||
host: 'http://jsonplaceholder.typicode.com'
|
||||
endpoint: 'http://jsonplaceholder.typicode.com'
|
||||
|
||||
defaults:
|
||||
headers:
|
||||
hello: $posts.body.0.userId
|
||||
|
||||
GET /posts/1: get-post
|
||||
|
||||
GET /posts/:
|
||||
alias: posts
|
||||
documentation:
|
||||
title: Fetch Posts
|
||||
description: Fetches all posts available.
|
||||
headers:
|
||||
hello: false
|
||||
|
||||
POST /posts/:
|
||||
alias: new-post
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
host: http://localhost:10080
|
||||
endpoint: http://localhost:10080
|
||||
|
||||
plugins:
|
||||
- beau-jwt:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
VERSION: '1'
|
||||
HOST: https://slack.com/api
|
||||
ENDPOINT: https://slack.com/api
|
||||
|
||||
auth: &auth
|
||||
token: xoxp-139455775026-139455775090-147751461120-f224ed6ffee029869a0f138d0859e7d6
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,12 +7,14 @@
|
|||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"watch": "jest --watch"
|
||||
"watch": "jest --watch",
|
||||
"test:coverage": "jest --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"cli-color": "^1.1.0",
|
||||
"clui": "^0.3.1",
|
||||
"commander": "^2.12.2",
|
||||
"deepmerge": "^2.0.1",
|
||||
"js-yaml": "^3.7.0",
|
||||
"jsome": "^2.3.26",
|
||||
"request": "^2.83.0",
|
||||
|
|
@ -29,5 +31,8 @@
|
|||
},
|
||||
"bin": {
|
||||
"beau": "./bin/beau"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
request.js
10
request.js
|
|
@ -14,15 +14,15 @@ class Request {
|
|||
REQUEST,
|
||||
ALIAS,
|
||||
PAYLOAD,
|
||||
HOST,
|
||||
ENDPOINT,
|
||||
PARAMS,
|
||||
HEADERS,
|
||||
DOCUMENTATION
|
||||
} = config;
|
||||
const { verb, endpoint } = this.parseRequest(REQUEST);
|
||||
const { verb, path } = this.parseRequest(REQUEST);
|
||||
|
||||
this.VERB = verb;
|
||||
this.ENDPOINT = HOST + endpoint;
|
||||
this.ENDPOINT = ENDPOINT + path;
|
||||
|
||||
this.HEADERS = HEADERS;
|
||||
this.PAYLOAD = PAYLOAD;
|
||||
|
|
@ -39,11 +39,11 @@ class Request {
|
|||
}
|
||||
|
||||
parseRequest(request) {
|
||||
let parts = request.match(requestRegex);
|
||||
const parts = request.match(requestRegex);
|
||||
|
||||
return {
|
||||
verb: parts[1],
|
||||
endpoint: parts[2]
|
||||
path: parts[2]
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,17 +51,8 @@ class RequestList {
|
|||
});
|
||||
|
||||
return requests.map(request => {
|
||||
const type = typeof doc[request];
|
||||
|
||||
if (type === 'string') {
|
||||
doc[request] = {
|
||||
ALIAS: doc[request]
|
||||
};
|
||||
}
|
||||
|
||||
doc[request] = doc[request] || {};
|
||||
|
||||
doc[request].HOST = this.config.HOST;
|
||||
doc[request].ENDPOINT = this.config.ENDPOINT;
|
||||
doc[request].request = request;
|
||||
|
||||
return new Request(doc[request]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue