@case-contract-testing/case
Version:
Next-generation contract testing suite
96 lines (95 loc) • 5.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseCaseContract = void 0;
const diffmatch_1 = require("../diffmatch");
const entities_1 = require("../entities");
const context_1 = require("../entities/context");
const auxiliary_1 = require("../entities/nodes/matchers/auxiliary");
const results_1 = require("../entities/results");
const structure_1 = require("./structure");
const config_1 = require("./config");
const defaultTestId_1 = require("./defaultTestId");
class BaseCaseContract {
currentContract;
initialContext;
constructor(description, config, defaultConfig, resultPrinter, makeLogger) {
this.currentContract = (0, structure_1.makeContract)(description);
const contractFns = {
lookupMatcher: this.lookupMatcher.bind(this),
saveLookupableMatcher: this.saveLookupableMatcher.bind(this),
addVariable: this.addVariable.bind(this),
lookupVariable: this.lookupVariable.bind(this),
};
const makeLookup = (context) => ({
lookupMatcher: (uniqueName) => contractFns.lookupMatcher(uniqueName, context),
saveLookupableMatcher: (matcher) => contractFns.saveLookupableMatcher(matcher, context),
addDefaultVariable: (name, stateName, value) => contractFns.addVariable(name, 'default', stateName, value, context),
addStateVariable: (name, stateName, value) => contractFns.addVariable(name, 'state', stateName, value, context),
lookupVariable: (name) => contractFns.lookupVariable(name, context),
});
this.initialContext = (0, context_1.constructMatchContext)(diffmatch_1.traversals, makeLogger, makeLookup, resultPrinter, { ...(0, config_1.configToRunContext)({ ...defaultConfig, ...config }) }, defaultConfig);
if (this.initialContext['case:currentRun:context:testRunId'] ===
defaultTestId_1.DEFAULT_TEST_ID) {
this.initialContext.logger.warn("The 'testRunId' config property has not been set for this run. It is recommended to set it for each CaseContract() or CaseVerifier() invocation."
// TODO: put in a URL to the documentation here
);
}
}
lookupVariable(name, context) {
if (this.currentContract === undefined) {
context.logger.error(`lookupVariable was called without initialising the contract file. This should not be possible.`);
throw new entities_1.CaseConfigurationError('Contract was not initialised at the time that lookupVariable was called');
}
const defaultVariable = (0, structure_1.findVariable)(this.currentContract, name);
if (defaultVariable === undefined) {
throw new entities_1.CaseConfigurationError(`Variable '${name}' was requested but appears not to be set. Is the variable spelt correctly, and the states for this mock are correctly set`);
}
return (0, auxiliary_1.coreShapedLike)(defaultVariable);
}
addVariable(name, type, stateName, value, context) {
if (this.currentContract === undefined) {
context.logger.error(`addVariable was called by state '${stateName}' without initialising the contract file. This should not be possible.`);
throw new entities_1.CaseConfigurationError('Contract was not initialised at the time that addVariable was called');
}
if (type !== 'state') {
this.currentContract = (0, structure_1.addVariable)(this.currentContract, name, (0, auxiliary_1.coreShapedLike)(value), context);
}
return [name, value];
}
saveLookupableMatcher(namedMatcher, context) {
if (this.currentContract === undefined) {
context.logger.error('saveNamedMatcher was called without initialising the contract file. This should not be possible.');
throw new entities_1.CaseConfigurationError('Contract was not initialised at the time that saveNamedMatcher was called');
}
this.currentContract = (0, structure_1.addLookupableMatcher)(this.currentContract, namedMatcher, context);
return this.currentContract;
}
lookupMatcher(uniqueName, context) {
if (!this.currentContract) {
context.logger.error('lookupMatcher was called without initialising the contract file. This should not be possible.');
throw new entities_1.CaseCoreError('Contract was not initialised at the time that lookupMatcher was called');
}
// Have to pull this out, because typescript can't see that it's the same result even if we call twice
const possibleMatch = (0, structure_1.findMatcher)(this.currentContract, uniqueName);
if (possibleMatch !== undefined) {
return possibleMatch;
}
throw new entities_1.CaseConfigurationError(`Contract did not contain a matcher with the name '${uniqueName}'. Did you ask for it before it was defined?`);
}
stripMatchers(matcherOrData) {
return diffmatch_1.traversals.descendAndStrip(matcherOrData, (0, context_1.applyNodeToContext)(matcherOrData, this.initialContext));
}
checkMatch(matcherOrData, actual) {
return Promise.resolve()
.then(() => diffmatch_1.traversals.selfVerify(matcherOrData, (0, context_1.applyNodeToContext)(matcherOrData, this.initialContext)))
.then((selfVerification) => {
if ((0, results_1.hasErrors)(selfVerification)) {
throw new entities_1.CaseConfigurationError(
// TODO document this extensively.
`The matchers used have been given an example that doesn't pass the matcher: ${selfVerification[0]?.message} (at ${selfVerification[0]?.location})`);
}
})
.then(() => diffmatch_1.traversals.descendAndCheck(matcherOrData, (0, context_1.applyNodeToContext)(matcherOrData, this.initialContext), actual));
}
}
exports.BaseCaseContract = BaseCaseContract;