UNPKG

@case-contract-testing/case

Version:

Next-generation contract testing suite

96 lines (95 loc) 5.97 kB
"use strict"; 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;