unmock-core
Version:
[][npmjs] [](https://circleci.com/gh/unmock/unmock-js) [](h
115 lines • 5.15 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = require("debug");
const minimatch = require("minimatch");
const constants_1 = require("../constants");
const dsl_1 = require("../dsl");
const utils_1 = require("./utils");
const validator_1 = require("./validator");
const debugLog = debug_1.default("unmock:state");
class State {
constructor() {
this.state = {};
}
update(stateUpdate) {
const { endpoint, method, newState } = stateUpdate.stateInput;
debugLog(`Fetching operations for '${method} ${endpoint}'...`);
const ops = utils_1.getOperations(stateUpdate);
if (ops.error !== undefined) {
debugLog(`Couldn't find any matching operations: ${ops.error}`);
throw new Error(ops.error);
}
if (newState.isEmpty) {
return;
}
debugLog(`Found the following operations: ${JSON.stringify(ops.operations, undefined, 1)}`);
const mapped = ops.operations.map(op => (Object.assign(Object.assign({}, validator_1.getValidStatesForOperationWithState(op.operation, newState, stateUpdate.dereferencer)), { endpoint: op.endpoint, method: op.method })));
const failed = mapped.every(resp => resp.error !== undefined);
if (failed) {
const error = utils_1.chooseErrorFromList(mapped.map(resp => resp.error));
throw new Error(error
? error.msg
: `Unexpected error while setting state - ${JSON.stringify(newState.state)}`);
}
mapped
.filter(resp => resp.error === undefined)
.map(resp => ({
state: dsl_1.DSL.translateTopLevelToOAS(newState.top, resp.responses),
endpoint: utils_1.convertEndpointToWildcard(resp.endpoint),
method: resp.method,
}))
.forEach(aug => this.updateStateInternal(aug.endpoint, aug.method, aug.state));
}
getState(method, endpoint) {
debugLog(`Filtering all saved states that match '${endpoint}'...`);
const mostRelevantEndpoint = Object.keys(this.state)
.filter((sKey) => minimatch(endpoint, sKey, { nocase: true }) &&
(this.state[sKey][method] !== undefined ||
this.state[sKey][constants_1.DEFAULT_STATE_HTTP_METHOD] !== undefined))
.sort((a, b) => {
const nA = a.split("*");
const nB = b.split("*");
return nA > nB || (nA === nB && a.indexOf("*") < b.indexOf("*"))
? -1
: 1;
})
.shift();
if (mostRelevantEndpoint === undefined) {
debugLog(`No states match '${endpoint}'`);
return undefined;
}
debugLog(`Most relevant endpoint is ${mostRelevantEndpoint}`);
const matchingMethod = Object.keys(this.state[mostRelevantEndpoint]).includes(method)
? method
: constants_1.DEFAULT_STATE_HTTP_METHOD;
const relevantState = this.state[mostRelevantEndpoint][matchingMethod];
const { parsed, newState } = dsl_1.DSL.actTopLevelFromOAS(relevantState);
this.updateStateFromDSL(newState, mostRelevantEndpoint, matchingMethod);
return Object.keys(parsed).length > 0 ? parsed : undefined;
}
reset() {
this.state = {};
}
updateStateFromDSL(newState, endpoint, method) {
Object.keys(newState).forEach(code => Object.keys(newState[code]).forEach(media => {
const state = newState[code][media];
if (state === undefined) {
this.deleteStateInternal(endpoint, method, code, media);
}
else if (Object.keys(state).length > 0) {
this.updateStateInternal(endpoint, method, {
[code]: { [media]: state },
});
}
}));
}
updateStateInternal(endpoint, method, responses) {
if (this.state[endpoint] === undefined) {
this.state[endpoint] = {};
}
if (this.state[endpoint][method] === undefined) {
this.state[endpoint][method] = {};
}
this.state[endpoint][method] = Object.assign(Object.assign({}, this.state[endpoint][method]), responses);
}
deleteStateInternal(endpoint, method, code, mediaType) {
if (this.state[endpoint] === undefined ||
this.state[endpoint][method] === undefined ||
this.state[endpoint][method][code] === undefined ||
this.state[endpoint][method][code][mediaType] === undefined) {
return;
}
delete this.state[endpoint][method][code][mediaType];
if (Object.keys(this.state[endpoint][method][code]).length === 0) {
delete this.state[endpoint][method][code];
if (Object.keys(this.state[endpoint][method]).length === 0) {
delete this.state[endpoint][method];
if (Object.keys(this.state[endpoint]).length === 0) {
delete this.state[endpoint];
}
}
}
}
}
exports.State = State;
//# sourceMappingURL=state.js.map