Skip to content

Commit

Permalink
updated custom reporters interface to better support plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
beatfactor committed Nov 15, 2023
1 parent a587526 commit d8492c1
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 42 deletions.
123 changes: 87 additions & 36 deletions lib/reporter/global-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,12 @@ module.exports = class GlobalReporter {
const reporters = plugins.reduce((prev, pluginName) => {
const plugin = PluginLoader.load(pluginName);
if (isFunction(plugin.instance?.reporter)) {
prev.push(plugin.instance.reporter);
prev.push(plugin.instance);
} else if (plugin.globals?.reporter && isFunction(plugin.globals.reporter)) {
prev.push(plugin.globals.reporter);
prev.push({
reporter: plugin.globals.reporter,
settings: plugin.globals.settings || {}
});
}

return prev;
Expand All @@ -353,51 +356,99 @@ module.exports = class GlobalReporter {
return reporters;
}

getTimeoutValueMs(customReporter) {
// global timeout for all custom reporters – set by user
if (this.settings.custom_reporter_timeout) {
return this.settings.custom_reporter_timeout;
}

// timeout for a specific custom reporter – set by plugin
if (customReporter.settings?.timeoutMs) {
return customReporter.settings.timeoutMs;
}

// default timeout when nothing is set – set by nightwatch
return this.settings.globals.customReporterCallbackTimeout;
}

callReporterFn(reporter, globalResults, {callbackTimeoutId, resolve, reject}) {
try {
if (reporter.length === 2) {
const reporterFnAsync = Utils.makeFnAsync(2, reporter, this.settings.globals);
reporterFnAsync.call(this.settings.globals, globalResults, function () {
clearTimeout(callbackTimeoutId);
resolve();
});
} else {
const promise = reporter.call(this.settings.globals, globalResults);

if (promise instanceof Promise) {
promise
.then(() => {
clearTimeout(callbackTimeoutId);
resolve();
})
.catch(err => {
clearTimeout(callbackTimeoutId);
reject(err);
});
} else {
clearTimeout(callbackTimeoutId);
resolve();
}
}
} catch (err) {
clearTimeout(callbackTimeoutId);
reject(err);
}
}

runCustomGlobalReporter(globalResults) {
const pluginReporters = this.getPluginReporters();
let customReporters = this.settings.globals.reporter;
let customReporters;

if (Utils.isFunction(this.settings.globals.reporter)) {
customReporters = [{
reporter: this.settings.globals.reporter,
settings: {
timeoutMs: this.settings.globals.customReporterCallbackTimeout
}
}];
} else if (Array.isArray(this.settings.globals.reporter)) {
customReporters = this.settings.globals.reporter.map(reporter => {
if (Utils.isFunction(reporter)) {
return {
reporter,
settings: {
timeoutMs: this.settings.globals.customReporterCallbackTimeout
}
};
}

if (customReporters && !Array.isArray(customReporters)) {
customReporters = [customReporters];
return reporter;
});
}

customReporters = customReporters.concat(pluginReporters);

const results = customReporters.map(customReporter => {
return new Promise((resolve, reject) => {
const callbackTimeoutId = setTimeout(() => {
reject(new Error('Timeout while waiting (20s) for the custom global reporter callback to be called.'));
}, this.settings.globals.customReporterCallbackTimeout);
const reporterName = customReporter.reporterName ? `"${customReporter.reporterName}" ` : '';

try {
if (customReporter.length === 2) {
const reporterFnAsync = Utils.makeFnAsync(2, customReporter, this.settings.globals);
reporterFnAsync.call(this.settings.globals, globalResults, function () {
clearTimeout(callbackTimeoutId);
resolve();
});
} else {
const promise = customReporter.call(this.settings.globals, globalResults);

if (promise instanceof Promise) {
promise
.then(() => {
clearTimeout(callbackTimeoutId);
resolve();
})
.catch(err => {
clearTimeout(callbackTimeoutId);
reject(err);
});
} else {
clearTimeout(callbackTimeoutId);
resolve();
}
}
} catch (err) {
clearTimeout(callbackTimeoutId);
reject(err);
}
const error = new Error(`Timeout while waiting for the custom reporter ${reporterName}to finish.`);
error.help = [
'Make sure the custom reporter calls the "done" callback when finished.',
'If the reporter is async, make sure the async operation is completed before the timeout is reached.',
'You can extend the timeout by defining the "custom_reporter_timeout" config setting in your nightwatch config file.'
];
error.link = 'See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-reporters.html for more details.';

reject(error);
}, this.getTimeoutValueMs(customReporter));

const {reporter} = customReporter;
this.callReporterFn(reporter, globalResults, {callbackTimeoutId, resolve, reject});
});
});

Expand Down
12 changes: 6 additions & 6 deletions test/src/runner/testRunWithGlobalReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('testRunWithGlobalReporter', function() {
});

it('testRunWithGlobalReporter', function() {
let testsPath = path.join(__dirname, '../../sampletests/before-after');
const testsPath = path.join(__dirname, '../../sampletests/before-after');
const globals = {
reporterCount: 0
};
Expand All @@ -42,7 +42,7 @@ describe('testRunWithGlobalReporter', function() {
});

it('testRunner with global async reporter', function() {
let testsPath = path.join(__dirname, '../../sampletests/before-after');
const testsPath = path.join(__dirname, '../../sampletests/before-after');
let reporterCount = 0;

return runTests(testsPath, settings({
Expand All @@ -62,7 +62,7 @@ describe('testRunWithGlobalReporter', function() {
});

it('testRunner with global async reporter and timeout error', function() {
let testsPath = path.join(__dirname, '../../sampletests/before-after');
const testsPath = path.join(__dirname, '../../sampletests/before-after');
let reporterCount = 0;

return runTests(testsPath, settings({
Expand All @@ -77,12 +77,12 @@ describe('testRunWithGlobalReporter', function() {
})).then(_ => {
assert.strictEqual(reporterCount, 1);
}).catch(err => {
assert.strictEqual(err.message, 'Timeout while waiting (20s) for the custom global reporter callback to be called.');
assert.strictEqual(err.message, 'Timeout while waiting for the custom reporter to finish.');
});
});

it('to check skipped count in global reporter', function() {
let testsPath = path.join(__dirname, '../../sampletests/globalreporterskippedcount/sample.js');
const testsPath = path.join(__dirname, '../../sampletests/globalreporterskippedcount/sample.js');
let reporterCount = 0;

return runTests(testsPath, settings({
Expand All @@ -97,7 +97,7 @@ describe('testRunWithGlobalReporter', function() {
output_folder: false
})).then(_ => {
assert.strictEqual(reporterCount, 1);
}).catch(err => (err))
}).catch(err => (err));
});


Expand Down

0 comments on commit d8492c1

Please sign in to comment.