@serenity-js/jasmine
Version:
Serenity/JS test runner adapter for Jasmine, enabling the use of the Screenplay Pattern in Jasmine-based test suites and leveraging Serenity/JS reporting capabilities
132 lines • 5.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.bootstrap = bootstrap;
const core_1 = require("@serenity-js/core");
const io_1 = require("@serenity-js/core/io");
const monkeyPatched_js_1 = require("./monkeyPatched.js");
const SerenityReporterForJasmine_js_1 = require("./SerenityReporterForJasmine.js");
/**
* Bootstraps the Serenity/JS reporter for Jasmine.
*
* This function monkey-patches Jasmine's Suite and Spec constructors
* so that they provide more accurate location information.
*
* For Jasmine 5.x, Suite and Spec are on the jasmine object directly.
* For Jasmine 6.x, Suite and Spec are in jasmine.private.
*
* ## Registering the reporter from the command line
*
* ```terminal
* jasmine --reporter=@serenity-js/jasmine
* ```
*
* ## Registering the reporter programmatically
*
* ```ts
* import serenityReporterForJasmine = require('@serenity-js/jasmine');
*
* jasmine.getEnv().addReporter(serenityReporterForJasmine);
* ```
*
* @param config
* @param jasmine
* the global.jasmine instance
*/
function bootstrap(config = {}, jasmine = global.jasmine) {
// Jasmine 6+ moved Suite and Spec to jasmine.private,
// so we check both locations for backwards compatibility
const Suite = jasmine.Suite || jasmine.private?.Suite;
const Spec = jasmine.Spec || jasmine.private?.Spec;
if (Suite && Spec) {
// Monkey-patch Suite and Spec to capture location info
const wrappers = {
expectationResultFactory: originalExpectationResultFactory => ((attributes) => {
const result = originalExpectationResultFactory(attributes);
if (!attributes.passed && attributes.error instanceof core_1.RuntimeError) {
result.stack = attributes.error.stack;
}
return result;
}),
};
// Jasmine 5.x: Suite and Spec are on jasmine directly
if (jasmine.Suite && jasmine.Spec) {
jasmine.Suite = (0, monkeyPatched_js_1.monkeyPatched)(jasmine.Suite, wrappers);
jasmine.Spec = (0, monkeyPatched_js_1.monkeyPatched)(jasmine.Spec, wrappers);
}
// Jasmine 6+: Suite and Spec are in jasmine.private
else if (jasmine.private?.Suite && jasmine.private?.Spec) {
jasmine.private.Suite = (0, monkeyPatched_js_1.monkeyPatched)(jasmine.private.Suite, wrappers);
jasmine.private.Spec = (0, monkeyPatched_js_1.monkeyPatched)(jasmine.private.Spec, wrappers);
}
}
// For Jasmine 6+, patch the Expector and buildExpectationResult to restore expected/actual values
// This is needed because Jasmine 6 removed these from expectation results
patchBuildExpectationResultForExpectedActual(jasmine);
patchExpectorForExpectedActual(jasmine);
const cwd = io_1.Path.from(process.cwd());
const requirementsHierarchy = new io_1.RequirementsHierarchy(new io_1.FileSystem(cwd), config?.specDirectory && cwd.resolve(io_1.Path.from(config?.specDirectory)));
return new SerenityReporterForJasmine_js_1.SerenityReporterForJasmine(core_1.serenity, requirementsHierarchy);
}
/**
* Patches Jasmine's buildExpectationResult to include expected/actual values
* in the expectation result. This restores functionality that was removed in Jasmine 6.
*
* In Jasmine 6, the buildExpectationResult function no longer includes expected/actual
* values in the result object. This patch wraps the function to preserve these values
* when they are provided.
*
* @param jasmine - The global jasmine instance
*/
function patchBuildExpectationResultForExpectedActual(jasmine) {
// Access the private buildExpectationResult function
const originalBuildExpectationResult = jasmine?.private?.buildExpectationResult;
if (!originalBuildExpectationResult) {
// buildExpectationResult not available, skip
return;
}
jasmine.private.buildExpectationResult = function (options) {
const result = originalBuildExpectationResult(options);
// Restore expected/actual values that Jasmine 6 removed
if (options.expected !== undefined) {
result.expected = options.expected;
}
if (options.actual !== undefined) {
result.actual = options.actual;
}
return result;
};
}
/**
* Patches Jasmine's Expector.prototype.processResult to include expected/actual values
* when calling addExpectationResult. This ensures the values are passed to
* buildExpectationResult.
*
* @param jasmine - The global jasmine instance
*/
function patchExpectorForExpectedActual(jasmine) {
// Access the private Expector class through jasmine's internal structure
// In Jasmine 6+, Expector is in jasmine.private.Expector
const Expector = jasmine?.private?.Expector;
if (!Expector || !Expector.prototype || !Expector.prototype.processResult) {
// Expector not available, skip
return;
}
Expector.prototype.processResult = function (result, errorForStack) {
const message = this.buildMessage(result);
let expected = this.expected;
if (Array.isArray(expected) && expected.length === 1) {
expected = expected[0];
}
this.addExpectationResult(result.pass, {
matcherName: this.matcherName,
passed: result.pass,
message: message,
error: errorForStack ? undefined : result.error,
errorForStack: errorForStack || undefined,
// Include expected/actual values that Jasmine 6 removed
expected: expected,
actual: this.actual,
});
};
}
//# sourceMappingURL=bootstrap.js.map