@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
92 lines • 3.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.monkeyPatched = monkeyPatched;
const errors_1 = require("@serenity-js/core/errors");
const parser = new errors_1.ErrorStackParser();
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/**
* Monkey-patches Jasmine domain model constructors so that they
* record information about the file system location of the caller function.
*
* This helps to make reporting more accurate.
*
* For Jasmine 5.x, the location is stored on instance.result.location.
* For Jasmine 6.x, the location is stored on instance._serenityLocation and
* injected into the result events via patched startedEvent/doneEvent methods.
*
* @param jasmineConstructor - A Jasmine constructor function to be patched
* @param {object} wrappers - Attributes to wrap when the monkey-patched Jasmine constructor is invoked
*/
function monkeyPatched(jasmineConstructor, wrappers = {}) {
const result = function MonkeyPatched(attrs) {
Object.keys(wrappers).forEach(key => {
attrs[key] = wrappers[key](attrs[key]);
});
const instance = new jasmineConstructor(attrs);
const location = callerLocation();
// Jasmine 5.x: instance.result exists, store location there
if (instance.result) {
instance.result.location = location;
}
// Jasmine 6.x: store location on instance and patch event methods
else {
instance._serenityLocation = location;
// Patch startedEvent to include location
if (typeof instance.startedEvent === 'function') {
const originalStartedEvent = instance.startedEvent.bind(instance);
instance.startedEvent = function () {
const event = originalStartedEvent();
if (event && instance._serenityLocation) {
event.location = instance._serenityLocation;
}
return event;
};
}
// Patch doneEvent to include location
if (typeof instance.doneEvent === 'function') {
const originalDoneEvent = instance.doneEvent.bind(instance);
instance.doneEvent = function () {
const event = originalDoneEvent();
if (event && instance._serenityLocation) {
event.location = instance._serenityLocation;
}
return event;
};
}
}
return instance;
};
Object.getOwnPropertyNames(jasmineConstructor)
.filter(isAStaticProperty)
.forEach(property => {
result[property] = jasmineConstructor[property];
});
return result;
}
// eslint-enable
/**
* Retrieves the file system location of the caller function.
*
* @package
*/
function callerLocation() {
const frames = parser.parse(new Error('fake error'));
const found = frames
.filter(frame => !/(node_modules)/.test(frame.fileName))
.find(frame => /^(Suite|Object|Proxy)/.test(frame.functionName) || !frame.functionName);
const caller = found || { fileName: 'unknown', lineNumber: 0, columnNumber: 0 };
return {
path: caller.fileName,
line: caller.lineNumber,
column: caller.columnNumber,
};
}
/**
* Checks if a given property is likely to be a static method or a static field on the constructor function.
*
* @package
*/
function isAStaticProperty(property) {
return !~['length', 'name', 'arguments', 'caller', 'prototype'].indexOf(property);
}
//# sourceMappingURL=monkeyPatched.js.map