@contract-case/case-core
Version:
Core functionality for the ContractCase contract testing suite
144 lines • 7.81 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReadingCaseContract = void 0;
const case_plugin_base_1 = require("@contract-case/case-plugin-base");
const BaseCaseContract_1 = require("./BaseCaseContract");
const executeExample_1 = require("./executeExample");
const entities_1 = require("../entities");
class ReadingCaseContract extends BaseCaseContract_1.BaseCaseContract {
mutex;
makeBrokerService;
links;
status;
/**
* Constructs a ReadingCaseContract
*
* @param contractFile - The DownloadedContract to verify
* @param readerDependencies - The dependencies for a contract reader (injected)
* @param config - the CaseConfig for this run
* @param parentVersions - the array of versions of all the ContractCase packages before this one
* @param mutex - a Mutex to use to ensure that only one test is run at once.
* this is injected, since the parent class might make more than one
* ReadingCaseContract objects (if verifying multiple contracts), but only one interaction can be run at once.
*/
constructor(contractFile, { resultFormatter: resultPrinter, makeLogger, defaultConfig, makeBrokerService, }, config, parentVersions, mutex) {
super(contractFile.description, { throwOnFail: false, testRunId: 'VERIFIER', ...config }, defaultConfig, resultPrinter, makeLogger, parentVersions);
this.currentContract = contractFile;
this.makeBrokerService = makeBrokerService;
this.links = contractFile;
this.status = 'UNKNOWN';
this.mutex = mutex;
}
/**
* Verifies this contract
*
* @param invoker - The invoker for this test
* @param runTestCb - a callback to tell the test framework that we're running a test
* @returns a Promise if the verification if asyncVerification is set,
* otherwise undefined. Note that if asyncVerification is false, this method
* returns before the verification has finished, leaving it up to the test
* callbacks.
*/
verifyContract(invoker, runTestCb) {
this.initialContext.logger.maintainerDebug(`Verifying contract between '${this.currentContract.description.consumerName}' and '${this.currentContract.description.providerName}'. There are '${this.currentContract.examples.length}' examples`);
const interactionFinishedIndicators = [];
const interactionFinishers = [];
this.currentContract.examples.forEach((example, index) => {
if (example.result !== 'VERIFIED') {
throw new case_plugin_base_1.CaseCoreError(`Attempting to verify an interaction which was '${example.result}'. This should never happen in normal operation, and might be the result of a corrupted ContractCase file, a file that was not written by ContractCase, or a bug.`);
}
const names = (0, entities_1.exampleToNames)(example, `${index}`);
this.initialContext.logger.maintainerDebug(`Preparing test framework's callback for: ${names.mockName} `);
interactionFinishedIndicators.push(new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
this.initialContext.logger.error(`Timeout in interaction[${index}]`);
reject(new Error(names.mockName));
}, 30000);
interactionFinishers[index] = () => {
clearTimeout(timeout);
resolve();
};
}));
runTestCb(names.mockName, () => this.mutex
.runExclusive(() => {
// Set running context instead of inlining this, so that
// stripMatchers etc have access to the context
this.runningContext = (0, case_plugin_base_1.applyNodeToContext)(example.mock, this.initialContext, {
'_case:currentRun:context:testName': `${index}`,
'_case:currentRun:context:contractMode': 'read',
'_case:currentRun:context:location': [
'verification',
`interaction[${index}]`,
],
});
this.initialContext.logger.maintainerDebug(`Run test callback for ${names.mockName}`);
return (0, executeExample_1.executeExample)({ ...example, result: 'PENDING' }, {
...invoker,
names,
}, this, this.runningContext);
})
.finally(() => {
this.initialContext.logger.deepMaintainerDebug(`Interaction[${index}] type of finisher`, interactionFinishers[index]);
this.initialContext.logger.maintainerDebug(`Interaction[${index}] completed: ${names.mockName}`);
interactionFinishers[index]?.();
}));
});
let publishFinished;
const publishFinishedIndicators = [];
publishFinishedIndicators.push(new Promise((resolve) => {
publishFinished = resolve;
}));
runTestCb(this.initialContext['_case:currentRun:context:publish']
? 'Publishing verification results'
: 'Finalising contract', () => {
this.initialContext.logger.maintainerDebug('Test callback for ending record');
return Promise.allSettled(interactionFinishedIndicators)
.then(() => this.endRecord())
.finally(() => {
this.initialContext.logger.maintainerDebug(`Publishing contract callback completed`);
publishFinished();
});
});
if (this.initialContext['_case:currentRun:context:internals'] &&
this.initialContext['_case:currentRun:context:internals']
.asyncVerification) {
return Promise.all([
...interactionFinishedIndicators,
...publishFinishedIndicators,
]).then(() => { });
}
return undefined;
}
recordExample(example, currentContext) {
currentContext.logger.deepMaintainerDebug(`recordExample called with`, example);
if (example.result === 'FAILED') {
currentContext.logger.maintainerDebug(`Interaction was a failure, marking verification failed (was '${this.status}')`);
this.status = 'FAILED';
}
else {
currentContext.logger.maintainerDebug(`Interaction was a success, no change to current status of '${this.status}'`);
}
return example;
}
async endRecord() {
const publishingContext = (0, case_plugin_base_1.addLocation)('PublishingResults', this.initialContext);
if (this.status === 'UNKNOWN') {
this.status = 'SUCCESS';
}
if (this.status === 'FAILED') {
// TODO: Print all failures
this.initialContext.logger.maintainerDebug('Verification failed');
}
else {
this.initialContext.logger.maintainerDebug('Verification successful');
}
if (!this.initialContext['_case:currentRun:context:brokerCiAccessToken']) {
this.initialContext.logger.warn('Not publishing verification results, as there is no brokerCiAccessToken set');
return;
}
this.initialContext.logger.maintainerDebug('Calling publishVerificationResults');
await this.makeBrokerService(publishingContext).publishVerificationResults(this.links, this.status === 'SUCCESS', (0, case_plugin_base_1.addLocation)(`PublishingVerification(${this.currentContract.description.consumerName} -> ${this.currentContract.description.providerName})`, this.initialContext));
}
}
exports.ReadingCaseContract = ReadingCaseContract;
//# sourceMappingURL=ReadingCaseContract.js.map