Skip to content

Commit

Permalink
Fix stuck tests (#3739)
Browse files Browse the repository at this point in the history
* added tests, improved bdd output

* .
  • Loading branch information
DavertMik committed Jul 10, 2023
1 parent 82fb299 commit 8d04cda
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 7 deletions.
10 changes: 9 additions & 1 deletion lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ class Cli extends Base {
if (!codeceptjsEventDispatchersRegistered) {
codeceptjsEventDispatchersRegistered = true;

event.dispatcher.on(event.bddStep.started, (step) => {
output.stepShift = 2;
output.step(step);
});

event.dispatcher.on(event.step.started, (step) => {
let processingStep = step;
const metaSteps = [];
Expand All @@ -93,7 +98,10 @@ class Cli extends Base {
for (let i = 0; i < Math.max(currentMetaStep.length, metaSteps.length); i++) {
if (currentMetaStep[i] !== metaSteps[i]) {
output.stepShift = 3 + 2 * i;
if (metaSteps[i]) output.step(metaSteps[i]);
if (!metaSteps[i]) continue;
// bdd steps are handled by bddStep.started
if (metaSteps[i].isBDD()) continue;
output.step(metaSteps[i]);
}
}
currentMetaStep = metaSteps;
Expand Down
2 changes: 2 additions & 0 deletions lib/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ module.exports = {
bddStep: {
before: 'bddStep.before',
after: 'bddStep.after',
started: 'bddStep.started',
finished: 'bddStep.finished',
},
/**
* @type {object}
Expand Down
8 changes: 8 additions & 0 deletions lib/interfaces/gherkin.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Gherkin = require('@cucumber/gherkin');
const Messages = require('@cucumber/messages');
const { Context, Suite, Test } = require('mocha');
const debug = require('debug')('codeceptjs:bdd');

const { matchStep } = require('./bdd');
const event = require('../event');
Expand Down Expand Up @@ -39,7 +40,9 @@ module.exports = (text, file) => {
for (const step of steps) {
const metaStep = new Step.MetaStep(null, step.text);
metaStep.actor = step.keyword.trim();
let helperStep;
const setMetaStep = (step) => {
helperStep = step;
if (step.metaStep) {
if (step.metaStep === metaStep) {
return;
Expand Down Expand Up @@ -67,18 +70,23 @@ module.exports = (text, file) => {
step.startTime = Date.now();
step.match = fn.line;
event.emit(event.bddStep.before, step);
event.emit(event.bddStep.started, metaStep);
event.dispatcher.prependListener(event.step.before, setMetaStep);
try {
debug(`Step '${step.text}' started...`);
await fn(...fn.params);
debug('Step passed');
step.status = 'passed';
} catch (err) {
debug(`Step failed: ${err?.message}`);
step.status = 'failed';
step.err = err;
throw err;
} finally {
step.endTime = Date.now();
event.dispatcher.removeListener(event.step.before, setMetaStep);
}
event.emit(event.bddStep.finished, metaStep);
event.emit(event.bddStep.after, step);
}
};
Expand Down
11 changes: 7 additions & 4 deletions lib/recorder.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const debug = require('debug')('codeceptjs:recorder');
const promiseRetry = require('promise-retry');

const { printObjectProperties } = require('./utils');
const { log } = require('./output');

const MAX_TASKS = 100;
Expand Down Expand Up @@ -41,6 +41,7 @@ module.exports = {
* @inner
*/
start() {
debug('Starting recording promises');
running = true;
asyncErr = null;
errFn = null;
Expand Down Expand Up @@ -175,7 +176,7 @@ module.exports = {
return;
}
tasks.push(taskName);
if (process.env.DEBUG) debug(`${currentQueue()}Queued | ${taskName}`);
debug(`${currentQueue()}Queued | ${taskName}`);

return promise = Promise.resolve(promise).then((res) => {
// prefer options for non-conditional retries
Expand Down Expand Up @@ -224,10 +225,11 @@ module.exports = {
* @inner
*/
catch(customErrFn) {
debug(`${currentQueue()}Queued | catch with error handler`);
return promise = promise.catch((err) => {
log(`${currentQueue()}Error | ${err}`);
if (!(err instanceof Error)) { // strange things may happen
err = new Error(`[Wrapped Error] ${JSON.stringify(err)}`); // we should be prepared for them
err = new Error(`[Wrapped Error] ${printObjectProperties(err)}`); // we should be prepared for them
}
if (customErrFn) {
customErrFn(err);
Expand Down Expand Up @@ -264,8 +266,9 @@ module.exports = {
* @param {*} err
* @inner
*/

throw(err) {
return this.add(`throw error ${err}`, () => {
return this.add(`throw error: ${err.message}`, () => {
throw err;
});
},
Expand Down
13 changes: 13 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,16 @@ module.exports.isNotSet = function (obj) {
module.exports.emptyFolder = async (directoryPath) => {
require('child_process').execSync(`rm -rf ${directoryPath}/*`);
};

module.exports.printObjectProperties = (obj) => {
if (typeof obj !== 'object' || obj === null) {
return obj;
}

let result = '';
for (const [key, value] of Object.entries(obj)) {
result += `${key}: "${value}"; `;
}

return `{${result}}`;
};
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
"fs-extra": "^8.1.0",
"glob": "^6.0.1",
"html-minifier": "^4.0.0",
"i": "^0.3.7",
"inquirer": "^6.5.2",
"joi": "^17.6.0",
"js-beautify": "^1.14.0",
Expand Down
6 changes: 6 additions & 0 deletions test/data/sandbox/features/fail.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@fail
Feature: Failing

Scenario: failed bdd test
Given I make a request (and it fails)
Then my test execution gets stuck
49 changes: 49 additions & 0 deletions test/data/sandbox/features/step_definitions/my_other_steps.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const I = actor();
const axios = require('axios');

Given('I have products in my cart', (table) => { // eslint-disable-line
for (const id in table.rows) {
Expand All @@ -20,3 +21,51 @@ Given(/I have simple product/, async () => {
setTimeout(resolve, 0);
});
});

const sendRequest = async (requestConfig) => {
if (!requestConfig) throw JSON.stringify({ error: 'Request config is null or undefined.' });
return axios({
method: requestConfig.method || 'GET',
timeout: requestConfig.timeout || 3000,
...requestConfig,
}).catch(error => {
if (error.response) {
error = {
message: 'The request was made and the server responded with a status code.',
status: error.response.status,
data: error.response.data,
headers: error.response.headers,
request: error.config.data,
url: error.response.config.url,
};
} else if (error.request) {
error = {
message: 'The request was made but no response was received.',
request: error.request,
};
} else {
error = {
message: `Something happened in setting up the request that triggered an Error.\n${error.message}`,
};
}
throw error;
});
};

Given(/^I make a request \(and it fails\)$/, async () => {
const requestPayload = {
method: 'GET',
url: 'https://google.com',
headers: {
Cookie: 'featureConfig=%7B%22enableCaptcha%22%3A%220%22%7D',
'X-Requested-With': 'XMLHttpRequest',
},
timeout: 1,
};

return sendRequest(requestPayload);
});

Then(/^my test execution gets stuck$/, async () => {
I.say('Test execution never gets here...');
});
23 changes: 22 additions & 1 deletion test/runner/bdd_test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const assert = require('assert');
const { log } = require('console');
const path = require('path');
const exec = require('child_process').exec;

Expand Down Expand Up @@ -193,6 +192,28 @@ describe('BDD Gherkin', () => {
});
});

it('should run scenario and scenario outline by tags', (done) => {
exec(config_run_config('codecept.bdd.js') + ' --grep "\@user|\@very" --steps', (err, stdout, stderr) => { //eslint-disable-line
stdout.should.not.include('0 passed');
stdout.should.include('I have product with price 10$');
stdout.should.include('I have product with $600 price in my cart');
stdout.should.include('6 passed');
assert(!err);
done();
});
});

it('should run not get stuck on failing step', (done) => {
exec(config_run_config('codecept.bdd.js') + ' --grep "@fail" --steps', (err, stdout, stderr) => { //eslint-disable-line
// stdout.should.include('Given I make a request (and it fails)');
// stdout.should.not.include('Then my test execution gets stuck');
stdout.should.include('1 failed');
stdout.should.include('[Wrapped Error]');
assert(err);
done();
});
});

it('should show all available steps', (done) => {
exec(`${runner} gherkin:steps --config ${codecept_dir}/codecept.bdd.js`, (err, stdout, stderr) => { //eslint-disable-line
stdout.should.include('Gherkin');
Expand Down

0 comments on commit 8d04cda

Please sign in to comment.