soda-test
Version:
Package for Unit and API tests
122 lines • 4.89 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.testCase = exports.testStep = void 0;
const testInfo_1 = require("./testInfo");
function createFactory(constructorMethod, args) {
args = args || [];
return () => new constructorMethod(...args);
}
class StepsCalls {
addMethod(name) {
this[name] = function (...args) {
this.__lastCall = {
methodName: name,
args
};
};
}
append(calls) {
for (const name of Object.keys(calls)) {
if (!this[name]) {
this[name] = calls[name];
}
}
}
}
// The testStep descorator is defined on a method in a (test-steps) class.
// The class has a metadata named "soda-steps" of type StepsCalls that holds information about
// all the test-step methods. This decorator adds the method name to the "soda-steps" (create it first if does not exist)
function testStep() {
return (target, propertyKey) => {
if (!Reflect.hasMetadata("soda-steps", target)) {
Reflect.defineMetadata("soda-steps", new StepsCalls(), target);
}
const steps = Reflect.getMetadata("soda-steps", target);
steps.addMethod(propertyKey);
};
}
exports.testStep = testStep;
// this methods returns a "StepsClass" instances that holds information about all the steps in that target class type
// note taht targetType might defined from a nother class, so it should holds steps defines in base class too.
function getSodaSteps(target) {
const steps = new StepsCalls();
if (!target)
return steps;
const parent = Reflect.getPrototypeOf(target);
steps.append(getSodaSteps(parent));
if (Reflect.hasMetadata("soda-steps", target)) {
steps.append(Reflect.getMetadata("soda-steps", target));
}
return steps;
}
// testCase is a decorator defined on a method that defines calls to test-steps
// text - the name of the test-case
// stepsConstructor - the class that holds the test-steps to be used
// constructorArgs - optionaly arguments to the constractor for the class of the test-stpes
function testCase(text, stepsConstructor, constructorArgs, extraData) {
return (target, propertyKey, descriptor) => {
// testStepsTarget is the prototype of the steps-class
const testStepsTarget = stepsConstructor.prototype;
// validate the steps-class as an "soda-steps" metadata
if (!Reflect.hasMetadata("soda-steps", testStepsTarget)) {
console.error(`cannot create case ${text}`);
return;
}
// create the case info in this class info
const tcase = (0, testInfo_1.getInfo)(target).getCase(propertyKey, text, createFactory(stepsConstructor, constructorArgs));
if (extraData) {
tcase.extraData = extraData;
}
// get lists of the possible steps from steps-class
const steps = getSodaSteps(testStepsTarget);
//
steps.__lastCall = undefined;
let lastStep = undefined;
let lastInstanceIndex = undefined;
let lastExtraData = undefined;
let comments = [];
let lastComments = undefined;
const addTestStep = () => {
if (steps.__lastCall) {
const text = lastStep;
const instanceIndex = lastInstanceIndex;
const methodName = steps.__lastCall.methodName;
const args = steps.__lastCall.args;
tcase.its.push({
itText: text,
extraData: lastExtraData,
instanceIndex: lastInstanceIndex,
comments: lastComments,
pending: false,
sinons: null,
method: function () {
const method = this.instances[instanceIndex][methodName];
return method.apply(this.instances[instanceIndex], args);
}
});
}
};
const stepMethod = (text, instanceIndex, extraData) => {
if (!instanceIndex)
instanceIndex = 0;
addTestStep();
lastStep = text;
lastExtraData = extraData;
lastComments = comments;
comments = [];
lastInstanceIndex = instanceIndex;
return steps;
};
stepMethod.comment = (text, extraData) => {
const comment = {
commentText: text,
extraData
};
comments.push(comment);
};
descriptor.value(stepMethod);
addTestStep();
};
}
exports.testCase = testCase;
//# sourceMappingURL=testCase.js.map
;