UNPKG

simulado

Version:
121 lines (97 loc) 3.52 kB
const queryString = require('query-string'); const deepEqual = require('deep-equal'); const merge = require('lodash.merge'); let instance; class ResponseStore { constructor(initialState = {}) { if (!instance) { this.state = initialState; instance = this; } return instance; } getState() { return this.state; } add(responseToMock) { const defaults = { method: 'GET', status: 200 }; const mergedMock = merge({}, defaults, responseToMock); const responseMethod = mergedMock.method.toUpperCase(); this.state = Object.assign({}, this.state, { [responseMethod]: (this.state[responseMethod] || []).concat(mergedMock) }); } remove(method, path) { const responseToRemoveMethod = method.toUpperCase(); this.state = Object.assign({}, this.state, { [responseToRemoveMethod]: this.state[responseToRemoveMethod].filter( response => response.path !== path ) }); } match(method, path, requestHeaders = {}, requestBody) { const requestMethod = method.toUpperCase(); const responsesForMethod = this.state[requestMethod]; if (Boolean(responsesForMethod)) { const matchedResponses = this.state[requestMethod].filter(mockedResponse => { const isPathMatch = this._isPathMatch(mockedResponse, path); const isConditionalHeadersMatch = this._isConditionalHeadersMatch( mockedResponse, requestHeaders ); const isConditionalBodyMatch = this._isConditionalBodyMatch(mockedResponse, requestBody); return isPathMatch && isConditionalHeadersMatch && isConditionalBodyMatch; }) || []; return matchedResponses[matchedResponses.length - 1] || false; } return false; } removeAll() { this.state = {}; } _isPathMatch(mockedResponse, pathToMatch) { const { path, isRegexPath } = mockedResponse; if (path instanceof RegExp || isRegexPath) { const pathRegex = path instanceof RegExp ? path : path.slice(1, -1); const pathRegExp = new RegExp(pathRegex); return pathRegExp.test(pathToMatch); } const parsedPathToMatch = queryString.parseUrl(pathToMatch); const parsedPath = queryString.parseUrl(path); return deepEqual(parsedPathToMatch, parsedPath); } _isConditionalHeadersMatch(mockedResponse, requestHeaders) { const { conditionalHeaders = {} } = mockedResponse; return Object.keys(conditionalHeaders).reduce((hasMatched, conditionalHeaderName) => { if (hasMatched) { const lowerCaseConditionalHeaderName = conditionalHeaderName.toLowerCase(); const lowerCaseRequestHeaders = this._lowerCaseRequestHeaders(requestHeaders); const matchedHeader = lowerCaseRequestHeaders[lowerCaseConditionalHeaderName]; return matchedHeader === conditionalHeaders[conditionalHeaderName]; } return hasMatched; }, true); } _lowerCaseRequestHeaders(requestHeaders) { const lowerCaseRequestHeaders = {}; Object.keys(requestHeaders).forEach(headerName => { lowerCaseRequestHeaders[headerName.toLowerCase()] = requestHeaders[headerName]; }); return lowerCaseRequestHeaders; } _isConditionalBodyMatch(mockedResponse, requestBody) { const { conditionalBody } = mockedResponse; if (conditionalBody) { return deepEqual(conditionalBody, requestBody); } return true; } _removeInstance() { instance = null; } } module.exports = ResponseStore;