Formatted all code with new prettier conf. (#159)

This commit is contained in:
David Díaz 2020-11-20 17:52:13 -06:00 committed by GitHub
parent a9eb8c97dd
commit 44919334be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 579 additions and 583 deletions

View File

@ -41,7 +41,7 @@ endpoint: https://httpbin.org/
POST /anything: POST /anything:
alias: anything alias: anything
payload: payload:
hello: world hello: world
``` ```
``` ```

View File

@ -1,6 +1,6 @@
const fs = jest.genMockFromModule('fs'); const fs = jest.genMockFromModule('fs')
fs.existsSync = filename => filename === 'beau.yml'; fs.existsSync = (filename) => filename === 'beau.yml'
fs.readFileSync = () => ` fs.readFileSync = () => `
version: 1 version: 1
endpoint: https://example.org/ endpoint: https://example.org/
@ -9,6 +9,6 @@ GET /anything:
alias: anything alias: anything
payload: payload:
name: $env.params.name name: $env.params.name
`; `
module.exports = fs; module.exports = fs

View File

@ -1,23 +1,23 @@
const ListCommand = require('../commands/list'); const ListCommand = require('../commands/list')
jest.mock('../../../src/shared'); jest.mock('../../../src/shared')
jest.mock('../base'); jest.mock('../base')
describe('List Command', () => { describe('List Command', () => {
let result; let result
beforeEach(() => { beforeEach(() => {
result = []; result = []
jest.spyOn(process.stdout, 'write').mockImplementation(val => jest.spyOn(process.stdout, 'write').mockImplementation((val) =>
result.push(require('strip-ansi')(val.toString('utf8'))) result.push(require('strip-ansi')(val.toString('utf8')))
); )
}); })
afterEach(() => jest.restoreAllMocks()); afterEach(() => jest.restoreAllMocks())
test.each([[], ['--no-format']])('with flags:', async (...args) => { test.each([[], ['--no-format']])('with flags:', async (...args) => {
await ListCommand.run(args); await ListCommand.run(args)
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot()
}); })
}); })

View File

@ -1,22 +1,22 @@
const RequestCommand = require('../commands/request'); const RequestCommand = require('../commands/request')
const requestPromiseNativeMock = require('request-promise-native'); const requestPromiseNativeMock = require('request-promise-native')
jest.mock('../../../src/shared'); jest.mock('../../../src/shared')
jest.mock('../base'); jest.mock('../base')
describe('Request Command', () => { describe('Request Command', () => {
let result; let result
beforeEach(() => { beforeEach(() => {
requestPromiseNativeMock.fail = false; requestPromiseNativeMock.fail = false
result = []; result = []
jest.spyOn(process.stdout, 'write').mockImplementation(val => jest.spyOn(process.stdout, 'write').mockImplementation((val) =>
result.push(require('strip-ansi')(val.toString('utf8'))) result.push(require('strip-ansi')(val.toString('utf8')))
); )
}); })
afterEach(() => jest.restoreAllMocks()); afterEach(() => jest.restoreAllMocks())
test.each([ test.each([
['alias'], ['alias'],
@ -26,12 +26,12 @@ describe('Request Command', () => {
['alias', '--no-format'], ['alias', '--no-format'],
['alias', '--quiet'] ['alias', '--quiet']
])('with flags: %s %s %s', async (...args) => { ])('with flags: %s %s %s', async (...args) => {
await RequestCommand.run(args); await RequestCommand.run(args)
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot()
}); })
it('should throw an error when the request fails', async () => { it('should throw an error when the request fails', async () => {
requestPromiseNativeMock.fail = true; requestPromiseNativeMock.fail = true
await expect(RequestCommand.run(['anything'])).rejects.toThrow(Error); await expect(RequestCommand.run(['anything'])).rejects.toThrow(Error)
}); })
}); })

View File

@ -1,66 +1,66 @@
{ {
"name": "beau", "name": "beau",
"version": "0.10.1", "version": "0.10.1",
"description": "Testing APIs made easy.", "description": "Testing APIs made easy.",
"main": "./src/beau.js", "main": "./src/beau.js",
"author": "Sergio Diaz <seich@martianwabbit.com>", "author": "Sergio Diaz <seich@martianwabbit.com>",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"test": "jest -i", "test": "jest -i",
"test:coverage": "jest --coverage ./src", "test:coverage": "jest --coverage ./src",
"release": "np" "release": "np"
}, },
"files": [ "files": [
"/src", "/src",
"/bin" "/bin"
], ],
"dependencies": { "dependencies": {
"@oclif/command": "1.8.0", "@oclif/command": "1.8.0",
"@oclif/config": "1.17.0", "@oclif/config": "1.17.0",
"@oclif/plugin-help": "3.2.0", "@oclif/plugin-help": "3.2.0",
"@oclif/plugin-warn-if-update-available": "1.7.0", "@oclif/plugin-warn-if-update-available": "1.7.0",
"ajv": "7.0.0-beta.6", "ajv": "7.0.0-beta.6",
"beau-std": "0.9.4", "beau-std": "0.9.4",
"better-ajv-errors": "0.6.7", "better-ajv-errors": "0.6.7",
"cli-color": "2.0.0", "cli-color": "2.0.0",
"clui": "0.3.6", "clui": "0.3.6",
"color-json": "2.0.1", "color-json": "2.0.1",
"deepmerge": "4.2.2", "deepmerge": "4.2.2",
"dotenv": "8.2.0", "dotenv": "8.2.0",
"globby": "11.0.1", "globby": "11.0.1",
"is-plain-object": "5.0.0", "is-plain-object": "5.0.0",
"js-yaml": "3.14.0", "js-yaml": "3.14.0",
"request": "2.88.2", "request": "2.88.2",
"request-promise-native": "1.0.9", "request-promise-native": "1.0.9",
"requireg": "0.2.2" "requireg": "0.2.2"
}, },
"repository": "git@github.com:Seich/Beau.git", "repository": "git@github.com:Seich/Beau.git",
"devDependencies": { "devDependencies": {
"jest": "26.6.3", "jest": "26.6.3",
"jest-watch-typeahead": "0.6.1", "jest-watch-typeahead": "0.6.1",
"strip-ansi": "6.0.0", "strip-ansi": "6.0.0",
"np": "7.0.0" "np": "7.0.0"
}, },
"oclif": { "oclif": {
"commands": "./bin/cli/commands", "commands": "./bin/cli/commands",
"bin": "beau", "bin": "beau",
"plugins": [ "plugins": [
"@oclif/plugin-help", "@oclif/plugin-help",
"@oclif/plugin-warn-if-update-available" "@oclif/plugin-warn-if-update-available"
] ]
}, },
"jest": { "jest": {
"testEnvironment": "node", "testEnvironment": "node",
"notify": true, "notify": true,
"watchPlugins": [ "watchPlugins": [
"jest-watch-typeahead/filename", "jest-watch-typeahead/filename",
"jest-watch-typeahead/testname" "jest-watch-typeahead/testname"
] ]
}, },
"bin": { "bin": {
"beau": "./bin/beau" "beau": "./bin/beau"
}, },
"engines": { "engines": {
"node": ">=8.10.0" "node": ">=8.10.0"
} }
} }

View File

@ -1,11 +1,11 @@
class DynamicValues { class DynamicValues {
constructor(registry, settings = {}) { constructor(registry, settings = {}) {
registry.defineDynamicValue('add', this.add); registry.defineDynamicValue('add', this.add)
} }
add(x, y) { add(x, y) {
return x + y; return x + y
} }
} }
module.exports = DynamicValues; module.exports = DynamicValues

View File

@ -1,20 +1,20 @@
class Modifiers { class Modifiers {
constructor(registry, settings = {}) { constructor(registry, settings = {}) {
registry.addPreRequestModifier(this.preRequest); registry.addPreRequestModifier(this.preRequest)
registry.addPostRequestModifier(this.postRequest); registry.addPostRequestModifier(this.postRequest)
} }
preRequest(request, orig) { preRequest(request, orig) {
request.headers = request.headers || {}; request.headers = request.headers || {}
request.headers.preRequestModifier = true; request.headers.preRequestModifier = true
return request; return request
} }
postRequest(response, orig) { postRequest(response, orig) {
response.body = 'Hello World'; response.body = 'Hello World'
response.response.body = 'Hello World'; response.response.body = 'Hello World'
return response; return response
} }
} }
module.exports = Modifiers; module.exports = Modifiers

View File

@ -1,7 +1,7 @@
class BeauStd { class BeauStd {
constructor(registry, settings) { constructor(registry, settings) {
registry.defineDynamicValue('createReadStream', () => {}); registry.defineDynamicValue('createReadStream', () => {})
} }
} }
module.exports = BeauStd; module.exports = BeauStd

View File

@ -1,6 +1,6 @@
function Request(request) { function Request(request) {
if (Request.fail) { if (Request.fail) {
throw new Error(); throw new Error()
} }
return { return {
@ -14,9 +14,9 @@ function Request(request) {
statusCode: 200, statusCode: 200,
headers: [], headers: [],
body: '{"hello": "world"}' body: '{"hello": "world"}'
}; }
} }
Request.fail = false; Request.fail = false
module.exports = Request; module.exports = Request

View File

@ -1,15 +1,15 @@
function requireg(name) { function requireg(name) {
return require(name); return require(name)
} }
requireg.resolving = true; requireg.resolving = true
requireg.resolve = function(name) { requireg.resolve = function (name) {
if (requireg.resolving) { if (requireg.resolving) {
return ''; return ''
} else { } else {
return undefined; return undefined
} }
}; }
module.exports = requireg; module.exports = requireg

View File

@ -1,4 +1,4 @@
module.exports = { module.exports = {
...jest.requireActual('../shared'), ...jest.requireActual('../shared'),
moduleVersion: jest.fn().mockReturnValue(1) moduleVersion: jest.fn().mockReturnValue(1)
}; }

View File

@ -1,15 +1,15 @@
const yaml = require('js-yaml'); const yaml = require('js-yaml')
const Beau = require('../beau'); const Beau = require('../beau')
const { moduleVersion } = require('../shared'); const { moduleVersion } = require('../shared')
jest.mock('../shared'); jest.mock('../shared')
const requireg = require('requireg'); const requireg = require('requireg')
requireg.resolving = false; requireg.resolving = false
describe(`Beau's config Loader.`, () => { describe(`Beau's config Loader.`, () => {
it('should load the config', () => { it('should load the config', () => {
moduleVersion.mockReturnValue(1); moduleVersion.mockReturnValue(1)
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
version: 1 version: 1
@ -18,14 +18,14 @@ describe(`Beau's config Loader.`, () => {
defaults: defaults:
headers: headers:
authentication: hello authentication: hello
`); `)
const beau = new Beau(doc); const beau = new Beau(doc)
expect(beau).toMatchSnapshot(); expect(beau).toMatchSnapshot()
}); })
it(`should load the request list using the configuration`, () => { it(`should load the request list using the configuration`, () => {
moduleVersion.mockReturnValue(1); moduleVersion.mockReturnValue(1)
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
version: 1 version: 1
@ -36,24 +36,24 @@ describe(`Beau's config Loader.`, () => {
alias: user alias: user
headers: headers:
hello: world hello: world
`); `)
const beau = new Beau(doc); const beau = new Beau(doc)
expect(beau.requests).toMatchSnapshot(); expect(beau.requests).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', () => {
let stdout; let stdout
let spy = jest let spy = jest
.spyOn(console, 'warn') .spyOn(console, 'warn')
.mockImplementation(val => (stdout = val)); .mockImplementation((val) => (stdout = val))
moduleVersion.mockReturnValue(2); moduleVersion.mockReturnValue(2)
const beau = new Beau({ version: 1 }); const beau = new Beau({ version: 1 })
expect(stdout).toEqual('This Beau file expects v1. You are using v2.'); expect(stdout).toEqual('This Beau file expects v1. You are using v2.')
spy.mockReset(); spy.mockReset()
spy.mockRestore(); spy.mockRestore()
}); })
}); })

View File

@ -1,8 +1,8 @@
const yaml = require('js-yaml'); const yaml = require('js-yaml')
const Config = require('../config'); const Config = require('../config')
const requireg = require('requireg'); 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', () => {
@ -10,13 +10,13 @@ describe('Config', () => {
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(`
@ -29,11 +29,11 @@ describe('Config', () => {
alias: user alias: user
headers: headers:
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(`
@ -49,15 +49,15 @@ describe('Config', () => {
alias: user alias: user
headers: headers:
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(`
@ -97,12 +97,12 @@ describe('Config', () => {
endpoint: http://example.info endpoint: http://example.info
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(`
@ -113,13 +113,13 @@ describe('Config', () => {
- host: test2 - host: test2
endpoint: http://example.net endpoint: http://example.net
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(`
@ -130,10 +130,10 @@ describe('Config', () => {
- host: test2 - host: test2
endpoint: http://example.net endpoint: http://example.net
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(`
@ -152,11 +152,11 @@ describe('Config', () => {
headers: false headers: false
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)
}); })
it(`should allow different settings for the same request`, () => { it(`should allow different settings for the same request`, () => {
const doc = yaml.safeLoad(` const doc = yaml.safeLoad(`
@ -168,9 +168,9 @@ describe('Config', () => {
- alias: req2 - alias: req2
headers: headers:
request: 2 request: 2
`); `)
let config = new Config(doc); let config = new Config(doc)
expect(config.REQUESTS.length).toBe(2); expect(config.REQUESTS.length).toBe(2)
}); })
}); })

View File

@ -1,41 +1,41 @@
const Plugins = require('../plugins'); const Plugins = require('../plugins')
const Request = require('../request'); const Request = require('../request')
const RequestCache = require('../requestCache'); const RequestCache = require('../requestCache')
const requireg = require('requireg'); const requireg = require('requireg')
describe(`Beau's plugin system`, () => { describe(`Beau's plugin system`, () => {
let request; let request
let plugins; let plugins
beforeEach(() => { beforeEach(() => {
plugins = new Plugins([{ Modifiers: [Object] }, 'DynamicValues'], []); plugins = new Plugins([{ Modifiers: [Object] }, 'DynamicValues'], [])
}); })
it('should load all plugins', () => { it('should load all plugins', () => {
expect(plugins.registry.preRequestModifiers.length).toBe(1); expect(plugins.registry.preRequestModifiers.length).toBe(1)
expect(plugins.registry.postRequestModifiers.length).toBe(1); expect(plugins.registry.postRequestModifiers.length).toBe(1)
expect(plugins.registry.dynamicValues.length).toBe(1); expect(plugins.registry.dynamicValues.length).toBe(1)
}); })
it(`should throw if given an invalid configuration`, () => { it(`should throw if given an invalid configuration`, () => {
expect(() => new Plugins([{ test1: true, test2: true }])).toThrow(); expect(() => new Plugins([{ test1: true, test2: true }])).toThrow()
}); })
it(`shouldn't do anything when given an empty array.`, () => { it(`shouldn't do anything when given an empty array.`, () => {
expect(new Plugins([], [])).toMatchSnapshot(); expect(new Plugins([], [])).toMatchSnapshot()
}); })
it(`should warn if the plugin is not available.`, () => { it(`should warn if the plugin is not available.`, () => {
const spy = jest.spyOn(console, 'warn').mockImplementation(() => {}); const spy = jest.spyOn(console, 'warn').mockImplementation(() => {})
requireg.resolving = false; requireg.resolving = false
new Plugins(['not-a-Package']); new Plugins(['not-a-Package'])
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled()
requireg.resolving = true; requireg.resolving = true
spy.mockReset(); spy.mockReset()
spy.mockRestore(); spy.mockRestore()
}); })
describe(`Request Modifiers`, () => { describe(`Request Modifiers`, () => {
beforeEach(() => { beforeEach(() => {
@ -46,13 +46,13 @@ describe(`Beau's plugin system`, () => {
alias: 'update' alias: 'update'
}, },
plugins plugins
); )
}); })
it(`should modify the request and response using modifiers.`, async () => { it(`should modify the request and response using modifiers.`, async () => {
await expect(request.exec()).resolves.toMatchSnapshot(); await expect(request.exec()).resolves.toMatchSnapshot()
}); })
}); })
describe(`Dynamic Values`, () => { describe(`Dynamic Values`, () => {
beforeEach(() => { beforeEach(() => {
@ -68,34 +68,34 @@ describe(`Beau's plugin system`, () => {
payload: 'counted $[add(1, $value2)] so far.' payload: 'counted $[add(1, $value2)] so far.'
}, },
plugins plugins
); )
}); })
let cache = new RequestCache(); let cache = new RequestCache()
cache.add('value2', '2'); cache.add('value2', '2')
it(`should look for dynamic values executing and replacing them`, async () => { it(`should look for dynamic values executing and replacing them`, async () => {
let req = await request.exec(cache); let req = await request.exec(cache)
expect(req).toHaveProperty('request.body', 'counted 3 so far.'); expect(req).toHaveProperty('request.body', 'counted 3 so far.')
}); })
it(`should change the internal datatype if the only thing in the value is the dynamic value`, async () => { it(`should change the internal datatype if the only thing in the value is the dynamic value`, async () => {
let req = await request.exec(cache); let req = await request.exec(cache)
expect(req).toHaveProperty('request.headers.count', 3); expect(req).toHaveProperty('request.headers.count', 3)
}); })
it(`should return empty values as empty`, async () => { it(`should return empty values as empty`, async () => {
let req = await request.exec(cache); let req = await request.exec(cache)
expect(req).toHaveProperty('request.headers.empty', ''); expect(req).toHaveProperty('request.headers.empty', '')
}); })
it(`should throw when calling an undefined dynamic value`, async () => { it(`should throw when calling an undefined dynamic value`, async () => {
request = new Request({ request = new Request({
request: 'POST /hello/$[notAvailable(1, 2)]', request: 'POST /hello/$[notAvailable(1, 2)]',
alias: 'say-hello' alias: 'say-hello'
}); })
await expect(request.exec()).rejects.toThrow(); await expect(request.exec()).rejects.toThrow()
}); })
}); })
}); })

View File

@ -1,13 +1,13 @@
const Request = require('../request'); const Request = require('../request')
const RequestCache = require('../requestCache'); const RequestCache = require('../requestCache')
const requestPromiseNativeMock = require('request-promise-native'); const requestPromiseNativeMock = require('request-promise-native')
describe('Request', () => { describe('Request', () => {
let cache; let cache
let validRequestConfig; let validRequestConfig
let invalidRequestConfig; let invalidRequestConfig
let request; let request
let requestWithoutDependencies; let requestWithoutDependencies
beforeEach(() => { beforeEach(() => {
validRequestConfig = { validRequestConfig = {
@ -23,78 +23,78 @@ describe('Request', () => {
payload: { payload: {
username: 'seich' username: 'seich'
} }
}; }
invalidRequestConfig = { invalidRequestConfig = {
request: `POST /session`, request: `POST /session`,
endpoint: 'http://example.com' endpoint: 'http://example.com'
}; }
cache = new RequestCache(); cache = new RequestCache()
cache.add('session', { token: 'abc123' }); cache.add('session', { token: 'abc123' })
cache.add('profile', { UserId: 14 }); cache.add('profile', { UserId: 14 })
request = new Request(validRequestConfig); request = new Request(validRequestConfig)
requestWithoutDependencies = new Request({ requestWithoutDependencies = new Request({
endpoint: 'http://example.com', endpoint: 'http://example.com',
request: 'GET /user', request: 'GET /user',
alias: 'show' alias: 'show'
}); })
requestPromiseNativeMock.fail = false; requestPromiseNativeMock.fail = false
}); })
it('should load up the given request', () => { it('should load up the given request', () => {
expect(request.VERB).toBe('POST'); expect(request.VERB).toBe('POST')
expect(request.ENDPOINT).toBe(validRequestConfig.endpoint); expect(request.ENDPOINT).toBe(validRequestConfig.endpoint)
expect(request.HEADERS).toBeDefined(); expect(request.HEADERS).toBeDefined()
expect(request.PAYLOAD).toBeDefined(); expect(request.PAYLOAD).toBeDefined()
expect(request.PARAMS).toBeDefined(); expect(request.PARAMS).toBeDefined()
}); })
it('should throw if a given request is invalid', () => { it('should throw if a given request is invalid', () => {
expect(() => new Request(invalidRequestConfig)).toThrow(); expect(() => new Request(invalidRequestConfig)).toThrow()
}); })
it('should list all of its dependencies', () => { it('should list all of its dependencies', () => {
expect(request.DEPENDENCIES.size).toBe(2); expect(request.DEPENDENCIES.size).toBe(2)
expect(request.DEPENDENCIES).toContain('session'); expect(request.DEPENDENCIES).toContain('session')
expect(request.DEPENDENCIES).toContain('profile'); expect(request.DEPENDENCIES).toContain('profile')
}); })
it('should execute a request', async () => { it('should execute a request', async () => {
await expect(request.exec(cache)).resolves.toMatchSnapshot(); await expect(request.exec(cache)).resolves.toMatchSnapshot()
await expect( await expect(
requestWithoutDependencies.exec() requestWithoutDependencies.exec()
).resolves.toMatchSnapshot(); ).resolves.toMatchSnapshot()
}); })
it('should throw if the request fails', async () => { it('should throw if the request fails', async () => {
requestPromiseNativeMock.fail = true; requestPromiseNativeMock.fail = true
await expect(requestWithoutDependencies.exec()).rejects.toThrow(Error); await expect(requestWithoutDependencies.exec()).rejects.toThrow(Error)
}); })
it(`should use the full url if given one as part of the path instead of the global endpoint`, async () => { it(`should use the full url if given one as part of the path instead of the global endpoint`, async () => {
const requestWithPath = new Request({ const requestWithPath = new Request({
endpoint: 'http://example.com', endpoint: 'http://example.com',
request: 'GET http://martianwabbit.com/user', request: 'GET http://martianwabbit.com/user',
alias: 'get-user' alias: 'get-user'
}); })
const requestWithoutPath = new Request({ const requestWithoutPath = new Request({
endpoint: 'http://example.com', endpoint: 'http://example.com',
request: 'GET /user', request: 'GET /user',
alias: 'get-user' alias: 'get-user'
}); })
await expect(requestWithPath.exec()).resolves.toHaveProperty( await expect(requestWithPath.exec()).resolves.toHaveProperty(
'request.endpoint', 'request.endpoint',
'http://martianwabbit.com/user' 'http://martianwabbit.com/user'
); )
await expect(requestWithoutPath.exec()).resolves.toHaveProperty( await expect(requestWithoutPath.exec()).resolves.toHaveProperty(
'request.endpoint', 'request.endpoint',
'http://example.com/user' 'http://example.com/user'
); )
}); })
}); })

View File

@ -1,14 +1,14 @@
const RequestCache = require('../requestCache'); const RequestCache = require('../requestCache')
describe('Request Cache', () => { describe('Request Cache', () => {
let cache; let cache
beforeEach(() => { beforeEach(() => {
cache = new RequestCache(); cache = new RequestCache()
cache.add('session', { cache.add('session', {
hello: 'World' hello: 'World'
}); })
cache.add('array', [ cache.add('array', [
{ {
@ -19,36 +19,36 @@ describe('Request Cache', () => {
id: 2, id: 2,
name: 'Angela' name: 'Angela'
} }
]); ])
}); })
it('should add keys to the cache', () => { it('should add keys to the cache', () => {
expect(cache.$cache.session.hello).toBe('World'); expect(cache.$cache.session.hello).toBe('World')
}); })
describe('get', () => { describe('get', () => {
it('should be able to find key values with a given path', () => { it('should be able to find key values with a given path', () => {
expect(cache.get('session.hello')).toBe('World'); expect(cache.get('session.hello')).toBe('World')
}); })
it('should throw when given an invalid path', () => { it('should throw when given an invalid path', () => {
expect(() => cache.get('$session.world')).toThrow(); expect(() => cache.get('$session.world')).toThrow()
}); })
}); })
describe('parse', () => { describe('parse', () => {
it("should transform variables in strings using it's cache", () => { it("should transform variables in strings using it's cache", () => {
expect(cache.parse('Hello $session.hello')).toBe('Hello World'); expect(cache.parse('Hello $session.hello')).toBe('Hello World')
}); })
it('should go transform variables in all values when given an object', () => { it('should go transform variables in all values when given an object', () => {
let parsed = cache.parse({ let parsed = cache.parse({
hello: 'hello $session.hello', hello: 'hello $session.hello',
earth: '$session.hello' earth: '$session.hello'
}); })
expect(parsed.hello).toBe('hello World'); expect(parsed.hello).toBe('hello World')
expect(parsed.earth).toBe('World'); expect(parsed.earth).toBe('World')
}); })
it('should return every non-string value as-is', () => { it('should return every non-string value as-is', () => {
let parsed = cache.parse({ let parsed = cache.parse({
@ -56,34 +56,34 @@ describe('Request Cache', () => {
nulled: null, nulled: null,
truthy: false, truthy: false,
hello: '$session.hello' hello: '$session.hello'
}); })
expect(parsed.number).toBe(1); expect(parsed.number).toBe(1)
expect(parsed.nulled).toBeNull(); expect(parsed.nulled).toBeNull()
expect(parsed.truthy).toBe(false); expect(parsed.truthy).toBe(false)
expect(parsed.hello).toBe('World'); expect(parsed.hello).toBe('World')
}); })
it('should parse arrays as well', () => { it('should parse arrays as well', () => {
let parsed = cache.parse({ hello: '$array.0.name' }); let parsed = cache.parse({ hello: '$array.0.name' })
expect(parsed.hello).toBe('Sergio'); expect(parsed.hello).toBe('Sergio')
}); })
it('should return an object when given an undefined value', () => { it('should return an object when given an undefined value', () => {
expect(cache.parse(undefined)).toEqual({}); expect(cache.parse(undefined)).toEqual({})
}); })
it('should parse any value other than undefined', () => { it('should parse any value other than undefined', () => {
expect(cache.parse('Hello $session.hello')).toBe('Hello World'); expect(cache.parse('Hello $session.hello')).toBe('Hello World')
}); })
it('should return null when passed null', () => { it('should return null when passed null', () => {
expect(cache.parse(null)).toBe(null); expect(cache.parse(null)).toBe(null)
}); })
it(`shouldn't replace escaped variables`, () => { it(`shouldn't replace escaped variables`, () => {
expect(cache.parse(`\\$session.hello is $session.hello`)).toBe( expect(cache.parse(`\\$session.hello is $session.hello`)).toBe(
`$session.hello is World` `$session.hello is World`
); )
}); })
}); })
}); })

View File

@ -1,13 +1,13 @@
const Config = require('../config'); const Config = require('../config')
const RequestList = require('../requestList'); const RequestList = require('../requestList')
const requestPromiseNativeMock = require('request-promise-native'); const requestPromiseNativeMock = require('request-promise-native')
describe('RequestList', () => { describe('RequestList', () => {
const endpoint = 'http://martianwabbit.com'; const endpoint = 'http://martianwabbit.com'
let env = { let env = {
environmental: true environmental: true
}; }
const doc = { const doc = {
ENDPOINT: endpoint, ENDPOINT: endpoint,
@ -20,49 +20,49 @@ describe('RequestList', () => {
lastname: 'Diaz' lastname: 'Diaz'
} }
} }
}; }
let requests; let requests
beforeEach(() => { beforeEach(() => {
requestPromiseNativeMock.fail = false; requestPromiseNativeMock.fail = false
let config = new Config(doc); let config = new Config(doc)
requests = new RequestList(config); requests = new RequestList(config)
}); })
it('should allow an empty request list', () => { it('should allow an empty request list', () => {
requests = new RequestList(); requests = new RequestList()
expect(requests.list.length).toBe(0); expect(requests.list.length).toBe(0)
}); })
it('should load valid requests', () => { it('should load valid requests', () => {
expect(requests.list.length).toBe(2); expect(requests.list.length).toBe(2)
}); })
it('should fetch dependencies', async () => { it('should fetch dependencies', async () => {
await expect( await expect(
requests.fetchDependencies(['get-posts']) requests.fetchDependencies(['get-posts'])
).resolves.toMatchSnapshot(); ).resolves.toMatchSnapshot()
}); })
it('should execute requests by alias.', async () => { it('should execute requests by alias.', async () => {
await expect(requests.execByAlias('user')).resolves.toMatchSnapshot(); await expect(requests.execByAlias('user')).resolves.toMatchSnapshot()
}); })
it('should fail if the request fails', async () => { it('should fail if the request fails', async () => {
requestPromiseNativeMock.fail = true; requestPromiseNativeMock.fail = true
await expect(requests.execByAlias('user')).rejects.toThrow(); await expect(requests.execByAlias('user')).rejects.toThrow()
}); })
it('should return a cached result if available', async () => { it('should return a cached result if available', async () => {
const obj = { test: true }; const obj = { test: true }
requests.cache.add('test', obj); requests.cache.add('test', obj)
await expect(requests.execByAlias('test')).resolves.toBe(obj); await expect(requests.execByAlias('test')).resolves.toBe(obj)
}); })
it('should fail if the alias is not found', async () => { it('should fail if the alias is not found', async () => {
await expect(requests.execByAlias('notAnAlias')).rejects.toThrow(); await expect(requests.execByAlias('notAnAlias')).rejects.toThrow()
}); })
it(`should fail if a given request doesn't have an alias`, () => { it(`should fail if a given request doesn't have an alias`, () => {
let config = new Config({ let config = new Config({
@ -71,8 +71,8 @@ describe('RequestList', () => {
hello: 1 hello: 1
} }
} }
}); })
expect(() => new RequestList(config, config)).toThrow(); expect(() => new RequestList(config, config)).toThrow()
}); })
}); })

View File

@ -6,7 +6,7 @@ const {
removeOptionalKeys, removeOptionalKeys,
toKebabCase, toKebabCase,
replaceInObject replaceInObject
} = require('../shared'); } = require('../shared')
describe('Shared Utilities', () => { describe('Shared Utilities', () => {
describe('requestRegex', () => { describe('requestRegex', () => {
@ -21,9 +21,9 @@ describe('Shared Utilities', () => {
['TRACE /hello', true], ['TRACE /hello', true],
['PATCH /hello', true] ['PATCH /hello', true]
])('should match: %s', (example, expected) => { ])('should match: %s', (example, expected) => {
expect(requestRegex.test(example)).toBe(expected); expect(requestRegex.test(example)).toBe(expected)
}); })
}); })
describe('replacementRegex', () => { describe('replacementRegex', () => {
test.each([ test.each([
@ -32,9 +32,9 @@ describe('Shared Utilities', () => {
['PUT /hi/$a.a/$a.b', ['$a.a', '$a.b']], ['PUT /hi/$a.a/$a.b', ['$a.a', '$a.b']],
[`\\$value`, ['\\$value']] [`\\$value`, ['\\$value']]
])('should match: %s', (example, expected) => { ])('should match: %s', (example, expected) => {
expect(example.match(replacementRegex)).toEqual(expected); expect(example.match(replacementRegex)).toEqual(expected)
}); })
}); })
describe('dynamicValueRegex', () => { describe('dynamicValueRegex', () => {
test.each([ test.each([
@ -42,34 +42,34 @@ describe('Shared Utilities', () => {
['$[test(1, 2, 3)]', ['$[test(1, 2, 3)]']], ['$[test(1, 2, 3)]', ['$[test(1, 2, 3)]']],
[`$[test({ \n id: 1 \n })]`, ['$[test({ \n id: 1 \n })]']] [`$[test({ \n id: 1 \n })]`, ['$[test({ \n id: 1 \n })]']]
])('should match: %s', (example, expected) => { ])('should match: %s', (example, expected) => {
expect(example.match(dynamicValueRegex)).toEqual(expected); expect(example.match(dynamicValueRegex)).toEqual(expected)
}); })
}); })
describe('UpperCaseKeys', () => { describe('UpperCaseKeys', () => {
it('should uppercase all first-level keys in an object', () => { it('should uppercase all first-level keys in an object', () => {
let a = { test: 1, Test2: 2 }; let a = { test: 1, Test2: 2 }
expect(UpperCaseKeys(a)).toEqual({ TEST: 1, TEST2: 2 }); expect(UpperCaseKeys(a)).toEqual({ TEST: 1, TEST2: 2 })
}); })
}); })
describe('removeOptionalKeys', () => { describe('removeOptionalKeys', () => {
it('should remove empty objects from an object', () => { it('should remove empty objects from an object', () => {
let a = { b: {}, c: 2, d: {} }; let a = { b: {}, c: 2, d: {} }
expect(removeOptionalKeys(a, ['b', 'd'])).toEqual({ c: 2 }); expect(removeOptionalKeys(a, ['b', 'd'])).toEqual({ c: 2 })
}); })
}); })
describe('toKebabCase', () => { describe('toKebabCase', () => {
it('should convert camel case to kebab case', () => { it('should convert camel case to kebab case', () => {
expect(toKebabCase('helloWorld')).toBe('hello-world'); expect(toKebabCase('helloWorld')).toBe('hello-world')
}); })
}); })
describe('replaceInObject', () => { describe('replaceInObject', () => {
it('should replace every value in an object with the output of a function', () => { it('should replace every value in an object with the output of a function', () => {
let a = { b: 'b', c: 'c' }; let a = { b: 'b', c: 'c' }
expect(replaceInObject(a, obj => 'a')).toEqual({ b: 'a', c: 'a' }); expect(replaceInObject(a, (obj) => 'a')).toEqual({ b: 'a', c: 'a' })
}); })
}); })
}); })

View File

@ -1,20 +1,20 @@
const RequestList = require('./requestList'); const RequestList = require('./requestList')
const Config = require('./config'); const Config = require('./config')
const { moduleVersion } = require('./shared'); const { moduleVersion } = require('./shared')
class Beau { class Beau {
constructor(doc, env = {}) { constructor(doc, env = {}) {
this.config = new Config(doc, env); this.config = new Config(doc, env)
this.requests = new RequestList(this.config); this.requests = new RequestList(this.config)
if (this.config.VERSION !== moduleVersion()) { if (this.config.VERSION !== moduleVersion()) {
console.warn( console.warn(
`This Beau file expects v${ `This Beau file expects v${
this.config.VERSION this.config.VERSION
}. You are using v${moduleVersion()}.` }. You are using v${moduleVersion()}.`
); )
} }
} }
} }
module.exports = Beau; module.exports = Beau

View File

@ -1,6 +1,6 @@
const deepMerge = require('deepmerge'); const deepMerge = require('deepmerge')
const { requestRegex, UpperCaseKeys, moduleVersion } = require('./shared'); const { requestRegex, UpperCaseKeys, moduleVersion } = require('./shared')
const Plugins = require('./plugins'); const Plugins = require('./plugins')
class Config { class Config {
constructor(doc, env = {}) { constructor(doc, env = {}) {
@ -12,43 +12,43 @@ class Config {
ENVIRONMENT: {}, ENVIRONMENT: {},
HOSTS: [], HOSTS: [],
COOKIEJAR: false COOKIEJAR: false
}; }
this.configKeys = Object.keys(defaultConfigValues); this.configKeys = Object.keys(defaultConfigValues)
let config = this.loadConfig(doc); let config = this.loadConfig(doc)
Object.assign(this, defaultConfigValues, config); Object.assign(this, defaultConfigValues, config)
this.ENVIRONMENT = deepMerge(this.ENVIRONMENT, env); this.ENVIRONMENT = deepMerge(this.ENVIRONMENT, env)
this.REQUESTS = []; this.REQUESTS = []
this.loadRequests(doc, { this.loadRequests(doc, {
DEFAULTS: this.DEFAULTS, DEFAULTS: this.DEFAULTS,
ENDPOINT: this.ENDPOINT ENDPOINT: this.ENDPOINT
}); })
this.loadHosts(this.HOSTS, config, defaultConfigValues); this.loadHosts(this.HOSTS, config, defaultConfigValues)
this.PLUGINS = new Plugins(this.PLUGINS); this.PLUGINS = new Plugins(this.PLUGINS)
} }
loadHosts(hosts, rootConfig, defaultConfigValues) { loadHosts(hosts, rootConfig, defaultConfigValues) {
hosts.forEach(host => { hosts.forEach((host) => {
if (typeof host.host === 'undefined') { if (typeof host.host === 'undefined') {
throw new Error(`Host doesn't indicate it's host name.`); throw new Error(`Host doesn't indicate it's host name.`)
} }
let config = deepMerge(defaultConfigValues, this.loadConfig(host)); let config = deepMerge(defaultConfigValues, this.loadConfig(host))
config.DEFAULTS = deepMerge(rootConfig.DEFAULTS, config.DEFAULTS); config.DEFAULTS = deepMerge(rootConfig.DEFAULTS, config.DEFAULTS)
this.loadRequests(host, { this.loadRequests(host, {
DEFAULTS: config.DEFAULTS, DEFAULTS: config.DEFAULTS,
ENDPOINT: config.ENDPOINT, ENDPOINT: config.ENDPOINT,
NAMESPACE: host.host NAMESPACE: host.host
}); })
}); })
} }
loadRequests(host, settings) { loadRequests(host, settings) {
@ -56,45 +56,45 @@ class Config {
.filter(([key]) => requestRegex.test(key)) .filter(([key]) => requestRegex.test(key))
.forEach(([key, rDefinition]) => { .forEach(([key, rDefinition]) => {
if (Array.isArray(rDefinition)) { if (Array.isArray(rDefinition)) {
rDefinition.forEach(req => rDefinition.forEach((req) =>
this.addRequest(key, req, settings) this.addRequest(key, req, settings)
); )
} else { } else {
this.addRequest(key, rDefinition, settings); this.addRequest(key, rDefinition, settings)
} }
}); })
} }
addRequest(key, rDefinition, settings) { addRequest(key, rDefinition, settings) {
let requestDefinitionIsString = typeof rDefinition === 'string'; let requestDefinitionIsString = typeof rDefinition === 'string'
let originalRequest = requestDefinitionIsString let originalRequest = requestDefinitionIsString
? { ALIAS: rDefinition } ? { ALIAS: rDefinition }
: rDefinition; : rDefinition
let request = UpperCaseKeys(originalRequest); let request = UpperCaseKeys(originalRequest)
if (settings.NAMESPACE) { if (settings.NAMESPACE) {
request.ALIAS = `${settings.NAMESPACE}:${request.ALIAS}`; request.ALIAS = `${settings.NAMESPACE}:${request.ALIAS}`
} }
request.REQUEST = key; request.REQUEST = key
request.COOKIEJAR = this.COOKIEJAR; request.COOKIEJAR = this.COOKIEJAR
request.ENDPOINT = settings.ENDPOINT; request.ENDPOINT = settings.ENDPOINT
let defaults = UpperCaseKeys(settings.DEFAULTS); let defaults = UpperCaseKeys(settings.DEFAULTS)
this.REQUESTS.push(deepMerge(defaults, request)); this.REQUESTS.push(deepMerge(defaults, request))
} }
loadConfig(host) { loadConfig(host) {
let config = {}; let config = {}
Object.entries(host) Object.entries(host)
.filter(([key]) => this.configKeys.includes(key.toUpperCase())) .filter(([key]) => this.configKeys.includes(key.toUpperCase()))
.forEach(([key, value]) => (config[key.toUpperCase()] = value)); .forEach(([key, value]) => (config[key.toUpperCase()] = value))
return config; return config
} }
} }
module.exports = Config; module.exports = Config

View File

@ -1,8 +1,8 @@
const vm = require('vm'); const vm = require('vm')
const requireg = require('requireg'); const requireg = require('requireg')
const deepmerge = require('deepmerge'); const deepmerge = require('deepmerge')
const { toKebabCase, dynamicValueRegex, replaceInObject } = require('./shared'); const { toKebabCase, dynamicValueRegex, replaceInObject } = require('./shared')
const { isPlainObject } = require('is-plain-object'); const { isPlainObject } = require('is-plain-object')
class Plugins { class Plugins {
constructor(plugins = [], autoload = ['std']) { constructor(plugins = [], autoload = ['std']) {
@ -10,112 +10,110 @@ class Plugins {
preRequestModifiers: [], preRequestModifiers: [],
postRequestModifiers: [], postRequestModifiers: [],
dynamicValues: [] dynamicValues: []
}; }
this.context = {}; this.context = {}
this.autoload = autoload; this.autoload = autoload
this.loadPlugins(plugins.concat(this.autoload)); this.loadPlugins(plugins.concat(this.autoload))
} }
normalizePlugins(plugins) { normalizePlugins(plugins) {
let results = {}; let results = {}
plugins.forEach(plugin => { plugins.forEach((plugin) => {
let name = plugin; let name = plugin
let settings = undefined; let settings = undefined
if (typeof plugin === 'object') { if (typeof plugin === 'object') {
let keys = Object.keys(plugin); let keys = Object.keys(plugin)
if (keys.length !== 1) { if (keys.length !== 1) {
throw new Error( throw new Error(`Plugin items should contain only one key.`)
`Plugin items should contain only one key.`
);
} }
name = keys[0]; name = keys[0]
settings = plugin[name]; settings = plugin[name]
} }
results[name] = settings; results[name] = settings
}); })
return results; return results
} }
loadPlugins(plugins) { loadPlugins(plugins) {
plugins = this.normalizePlugins(plugins); plugins = this.normalizePlugins(plugins)
Object.keys(plugins).forEach(name => { Object.keys(plugins).forEach((name) => {
const module = `beau-${toKebabCase(name)}`; const module = `beau-${toKebabCase(name)}`
if (typeof requireg.resolve(module) !== 'undefined') { if (typeof requireg.resolve(module) !== 'undefined') {
const plugin = requireg(module); const plugin = requireg(module)
new plugin(this, plugins[name]); new plugin(this, plugins[name])
} else { } else {
if (this.autoload.includes(name)) 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?`
); )
} }
}); })
} }
executeModifier(modifier, obj, orig) { executeModifier(modifier, obj, orig) {
let result = deepmerge({}, obj, { isMergeableObject: isPlainObject }); let result = deepmerge({}, obj, { isMergeableObject: isPlainObject })
this.registry[modifier].forEach( this.registry[modifier].forEach(
modifier => (result = modifier(result, orig)) (modifier) => (result = modifier(result, orig))
); )
return result; return result
} }
replaceDynamicValues(obj) { replaceDynamicValues(obj) {
vm.createContext(this.context); vm.createContext(this.context)
return replaceInObject(obj, val => { return replaceInObject(obj, (val) => {
let valIsEmpty = val.trim().length === 0; let valIsEmpty = val.trim().length === 0
if (valIsEmpty) { if (valIsEmpty) {
return val; return val
} }
try { try {
let onlyHasDynamic = let onlyHasDynamic =
val.replace(dynamicValueRegex, '').trim() === ''; val.replace(dynamicValueRegex, '').trim() === ''
if (onlyHasDynamic) { if (onlyHasDynamic) {
let call; let call
val.replace(dynamicValueRegex, (match, c) => { val.replace(dynamicValueRegex, (match, c) => {
call = c; call = c
}); })
return vm.runInContext(call, this.context); return vm.runInContext(call, this.context)
} }
return val.replace(dynamicValueRegex, (match, call) => { return val.replace(dynamicValueRegex, (match, call) => {
return vm.runInContext(call, this.context); return vm.runInContext(call, this.context)
}); })
} catch (e) { } catch (e) {
throw new Error(`DynamicValue: ` + e); throw new Error(`DynamicValue: ` + e)
} }
}); })
} }
addPreRequestModifier(modifier) { addPreRequestModifier(modifier) {
this.registry.preRequestModifiers.push(modifier); this.registry.preRequestModifiers.push(modifier)
} }
addPostRequestModifier(modifier) { addPostRequestModifier(modifier) {
this.registry.postRequestModifiers.push(modifier); this.registry.postRequestModifiers.push(modifier)
} }
defineDynamicValue(name, fn) { defineDynamicValue(name, fn) {
this.registry.dynamicValues.push({ name, fn }); this.registry.dynamicValues.push({ name, fn })
this.context[name] = fn; this.context[name] = fn
} }
} }
module.exports = Plugins; module.exports = Plugins

View File

@ -1,6 +1,6 @@
const request = require('request-promise-native'); const request = require('request-promise-native')
const RequestCache = require('./requestCache'); const RequestCache = require('./requestCache')
const Plugins = require('./plugins'); const Plugins = require('./plugins')
const { const {
requestRegex, requestRegex,
@ -8,63 +8,63 @@ const {
UpperCaseKeys, UpperCaseKeys,
removeOptionalKeys, removeOptionalKeys,
isUrl isUrl
} = require('./shared'); } = require('./shared')
class Request { class Request {
constructor(req, plugins = new Plugins()) { constructor(req, plugins = new Plugins()) {
this.originalRequest = req; this.originalRequest = req
this.plugins = plugins; this.plugins = plugins
req = UpperCaseKeys(req); req = UpperCaseKeys(req)
Object.assign(this, req); Object.assign(this, req)
if (!this.ALIAS) { if (!this.ALIAS) {
throw new Error(`${this.REQUEST} is missing an alias.`); throw new Error(`${this.REQUEST} is missing an alias.`)
} }
const { VERB, PATH } = this.parseRequest(this.REQUEST); const { VERB, PATH } = this.parseRequest(this.REQUEST)
this.VERB = VERB; this.VERB = VERB
this.PATH = PATH; this.PATH = PATH
this.DEPENDENCIES = this.findDependencies(req); this.DEPENDENCIES = this.findDependencies(req)
} }
parseRequest(request) { parseRequest(request) {
const parts = request.match(requestRegex); const parts = request.match(requestRegex)
return { return {
VERB: parts[1], VERB: parts[1],
PATH: parts[2] PATH: parts[2]
}; }
} }
findDependencies(request, set = new Set()) { findDependencies(request, set = new Set()) {
let type = typeof request; let type = typeof request
if (type === 'object' && request !== null) { if (type === 'object' && request !== null) {
Object.entries(request) Object.entries(request)
.filter(([key]) => key !== 'ALIAS') .filter(([key]) => key !== 'ALIAS')
.forEach(([key, value]) => { .forEach(([key, value]) => {
set = this.findDependencies(value, set); set = this.findDependencies(value, set)
}); })
} else if (type === 'string') { } else if (type === 'string') {
const matches = []; const matches = []
request.replace( request.replace(
replacementRegex, replacementRegex,
(match, g1) => !match.startsWith('\\') && matches.push(g1) (match, g1) => !match.startsWith('\\') && matches.push(g1)
); )
const deps = matches.map(m => m.split('.')[0]); const deps = matches.map((m) => m.split('.')[0])
return new Set([...set, ...deps]); return new Set([...set, ...deps])
} }
return set; return set
} }
async exec(cache = new RequestCache()) { async exec(cache = new RequestCache()) {
const isPathFullUrl = isUrl(this.PATH); const isPathFullUrl = isUrl(this.PATH)
let settings = cache.parse({ let settings = cache.parse({
baseUrl: isPathFullUrl ? '' : this.ENDPOINT, baseUrl: isPathFullUrl ? '' : this.ENDPOINT,
@ -81,7 +81,7 @@ class Request {
json: true, json: true,
simple: false, simple: false,
resolveWithFullResponse: true resolveWithFullResponse: true
}); })
settings = removeOptionalKeys(settings, [ settings = removeOptionalKeys(settings, [
'headers', 'headers',
@ -89,17 +89,17 @@ class Request {
'body', 'body',
'form', 'form',
'formData' 'formData'
]); ])
settings = this.plugins.replaceDynamicValues(settings); settings = this.plugins.replaceDynamicValues(settings)
settings = this.plugins.executeModifier( settings = this.plugins.executeModifier(
'preRequestModifiers', 'preRequestModifiers',
settings, settings,
this.originalRequest this.originalRequest
); )
const response = await request(settings); const response = await request(settings)
let results = { let results = {
request: { request: {
@ -113,18 +113,18 @@ class Request {
body: response.body body: response.body
}, },
body: response.body body: response.body
}; }
results = this.plugins.executeModifier( results = this.plugins.executeModifier(
'postRequestModifiers', 'postRequestModifiers',
results, results,
this.originalRequest this.originalRequest
); )
cache.add(this.ALIAS, results); cache.add(this.ALIAS, results)
return results; return results
} }
} }
module.exports = Request; module.exports = Request

View File

@ -1,46 +1,46 @@
const { replacementRegex, replaceInObject } = require('./shared'); const { replacementRegex, replaceInObject } = require('./shared')
class RequestCache { class RequestCache {
constructor() { constructor() {
this.$cache = {}; this.$cache = {}
} }
exists(key) { exists(key) {
return typeof this.$cache[key] !== 'undefined'; return typeof this.$cache[key] !== 'undefined'
} }
add(key, value) { add(key, value) {
this.$cache[key] = value; this.$cache[key] = value
} }
get(path) { get(path) {
let result = this.$cache; let result = this.$cache
path.split('.').forEach(part => { path.split('.').forEach((part) => {
if (result[part] === undefined) { if (result[part] === undefined) {
throw new Error(`${path} not found in cache.`); throw new Error(`${path} not found in cache.`)
} }
result = result[part]; result = result[part]
}); })
return result; return result
} }
parse(item) { parse(item) {
if (item === null) { if (item === null) {
return null; return null
} }
return replaceInObject(item, item => return replaceInObject(item, (item) =>
item.replace(replacementRegex, (match, key) => { item.replace(replacementRegex, (match, key) => {
if (match.startsWith('\\')) { if (match.startsWith('\\')) {
return match.replace('\\$', '$'); return match.replace('\\$', '$')
} }
return this.get(key); return this.get(key)
}) })
); )
} }
} }
module.exports = RequestCache; module.exports = RequestCache

View File

@ -1,56 +1,54 @@
const Request = require('./request'); const Request = require('./request')
const RequestCache = require('./requestCache'); const RequestCache = require('./requestCache')
class RequestList { class RequestList {
constructor(config = { REQUESTS: [] }) { constructor(config = { REQUESTS: [] }) {
this.list = this.loadRequests(config.REQUESTS, config.PLUGINS); this.list = this.loadRequests(config.REQUESTS, config.PLUGINS)
this.cache = new RequestCache(); this.cache = new RequestCache()
this.cache.add(`env`, config.ENVIRONMENT); this.cache.add(`env`, config.ENVIRONMENT)
} }
async execByAlias(alias) { async execByAlias(alias) {
if (this.cache.exists(alias)) { if (this.cache.exists(alias)) {
return this.cache.get(alias); return this.cache.get(alias)
} }
const request = this.list.find(r => r.ALIAS === alias); const request = this.list.find((r) => r.ALIAS === alias)
if (typeof request === 'undefined') { if (typeof request === 'undefined') {
throw new Error(`${alias} not found among the requests.`); throw new Error(`${alias} not found among the requests.`)
} }
try { try {
await this.fetchDependencies(Array.from(request.DEPENDENCIES)); await this.fetchDependencies(Array.from(request.DEPENDENCIES))
return await request.exec(this.cache); return await request.exec(this.cache)
} catch (reason) { } catch (reason) {
throw new Error( throw new Error(
`Request ${request.VERB} ${ `Request ${request.VERB} ${request.ENDPOINT} FAILED. \n${reason}`
request.ENDPOINT )
} FAILED. \n${reason}`
);
} }
} }
async fetchDependencies(dependencies) { async fetchDependencies(dependencies) {
dependencies = dependencies.map(d => this.execByAlias(d)); dependencies = dependencies.map((d) => this.execByAlias(d))
await Promise.all(dependencies); await Promise.all(dependencies)
return this.cache; return this.cache
} }
loadRequests(REQUESTS, PLUGINS) { loadRequests(REQUESTS, PLUGINS) {
let requests = []; let requests = []
REQUESTS.forEach(request => { REQUESTS.forEach((request) => {
try { try {
requests.push(new Request(request, PLUGINS)); requests.push(new Request(request, PLUGINS))
} catch (e) { } catch (e) {
throw new Error(`${request.request} was ignored: ${e}`); throw new Error(`${request.request} was ignored: ${e}`)
} }
}); })
return requests; return requests
} }
} }
module.exports = RequestList; module.exports = RequestList

View File

@ -1,4 +1,4 @@
const { URL } = require('url'); const { URL } = require('url')
const httpVerbs = [ const httpVerbs = [
'GET', 'GET',
@ -10,72 +10,72 @@ const httpVerbs = [
'OPTIONS', 'OPTIONS',
'TRACE', 'TRACE',
'PATCH' 'PATCH'
]; ]
const requestRegex = new RegExp(`(${httpVerbs.join('|')})\\s(.*)`, 'i'); const requestRegex = new RegExp(`(${httpVerbs.join('|')})\\s(.*)`, 'i')
const replacementRegex = /(?:\\?)\$([a-zA-Z\.\d\-\_\:]+)/g; const replacementRegex = /(?:\\?)\$([a-zA-Z\.\d\-\_\:]+)/g
const dynamicValueRegex = /\$\[(\w+\((?:.|[\n\r])*?\))\]/g; const dynamicValueRegex = /\$\[(\w+\((?:.|[\n\r])*?\))\]/g
const UpperCaseKeys = function(obj) { const UpperCaseKeys = function (obj) {
let result = {}; let result = {}
Object.entries(obj).forEach(([k, v]) => (result[k.toUpperCase()] = v)); Object.entries(obj).forEach(([k, v]) => (result[k.toUpperCase()] = v))
return result; return result
}; }
const isEmptyObject = obj => const isEmptyObject = (obj) =>
Object.keys(obj).length === 0 && obj.constructor === Object; Object.keys(obj).length === 0 && obj.constructor === Object
const removeOptionalKeys = function(obj, optionalValues) { const removeOptionalKeys = function (obj, optionalValues) {
let result = {}; let result = {}
Object.entries(obj).forEach(([key, value]) => { Object.entries(obj).forEach(([key, value]) => {
if (optionalValues.includes(key) && isEmptyObject(value)) { if (optionalValues.includes(key) && isEmptyObject(value)) {
return; return
} }
result[key] = value; result[key] = value
}); })
return result; return result
}; }
const toKebabCase = function(str) { const toKebabCase = function (str) {
return str return str
.trim() .trim()
.replace(/([a-z])([A-Z])/g, '$1-$2') .replace(/([a-z])([A-Z])/g, '$1-$2')
.toLowerCase(); .toLowerCase()
}; }
const replaceInObject = function(obj, fn) { const replaceInObject = function (obj, fn) {
if (obj === null) { if (obj === null) {
return null; return null
} }
switch (typeof obj) { switch (typeof obj) {
case 'undefined': case 'undefined':
return {}; return {}
case 'string': case 'string':
return fn(obj); return fn(obj)
case 'object': case 'object':
obj = Object.assign({}, obj); obj = Object.assign({}, obj)
Object.entries(obj).forEach( Object.entries(obj).forEach(
([key, value]) => (obj[key] = replaceInObject(value, fn)) ([key, value]) => (obj[key] = replaceInObject(value, fn))
); )
default: default:
return obj; return obj
} }
}; }
const moduleVersion = () => parseInt(require('../package.json').version, 10); const moduleVersion = () => parseInt(require('../package.json').version, 10)
const isUrl = function(str) { const isUrl = function (str) {
try { try {
new URL(str); new URL(str)
return true; return true
} catch (e) { } catch (e) {
return false; return false
} }
}; }
module.exports = { module.exports = {
requestRegex, requestRegex,
@ -87,4 +87,4 @@ module.exports = {
replaceInObject, replaceInObject,
moduleVersion, moduleVersion,
isUrl isUrl
}; }