mucsi96 / nightwatch-api

[DEPRECATED] Cross-runner API for Nightwatch.js
https://nightwatch-api.netlify.com/
MIT License
84 stars 64 forks source link

Queue freeze and Cucumber timeout caused by certain sequence of nightwatch actions. #857

Closed LucaLis closed 3 years ago

LucaLis commented 4 years ago

Howdy!

I'm facing quite strange behaviour that seems to be related with custom commands, screenshots on failure and cucumber. The problem is that failing scenario is causing a freeze of subsequent scenario which at the end causes cucumber timeout. I managed to reduce the test code to bare minimum to isolate the problem - more details below. I also tried to cause similar problem using pure nightwatch but without luck so this is why I'm posting this in nightwatch-api project.

Expected Behavior

Framework should not freeze or cause cucumber step timout.

Current Behavior / Steps to Reproduce

I have prepared a project that allows to reproduce this problem (same case is described below): https://github.com/LucaLis/nightwatch-api-cucumber-bug-demonstration

I'm using following test:

@command
Feature: Google Search

Scenario: First scenario

  Given I simply open Google
  When i call custom command and wait for something important

Scenario: Next Scenario

  Given dummy step
  When dummy step
  Then dummy step

Implementation of steps is rather trivial:

import { Given, Then } from 'cucumber';
import { client } from 'nightwatch-api';

Given('I simply open Google', function() {
  return client.url('http://google.com');
});

Given('i call custom command and wait for something important', function(){
  client.customCommand() // comment out this line and test won't freeze 
  return client.waitForElementPresent('#thisWontBePresent')
});

Given('dummy step', function(){
  return client.pause(100)
});

Please note that client.waitForElementPresent('#thisWontBePresent') is here by purpose to simulate situation when element is not present on the page.

Custom command is also a dummy:

module.exports.command = function() {
    this.pause(1000,()=>{ 
        console.log("callback from custom command") 
    })
}

When I run this failed step from first scenario causes a problem with subsequent scenario which runs few `dummy step' steps and freezes (which in the end causes cucumber timeout) - log for this case: https://github.com/LucaLis/nightwatch-api-cucumber-bug-demonstration/blob/master/logs/cucumber-timeout-custom-command-present-screenshots-enabled.log

Hint

I've noticed that if i turn off screenshots (log https://github.com/LucaLis/nightwatch-api-cucumber-bug-demonstration/blob/master/logs/ok-custom-command-present-screenshots-disabled.log)

OR remove custom command from failing step definition (https://github.com/LucaLis/nightwatch-api-cucumber-bug-demonstration/blob/master/logs/ok-custom-command-commented-in-step-screenshots-enabled.log) then whole feature won't freeze/cause cucumber timeout.

Environment

Nightwatch.conf.js

const chromedriver = require('chromedriver');

module.exports = {
  silent: false,
  custom_commands_path: "./commands",
  disable_colors: true,

  globals: {
    abortOnFailure: true,
    abortOnAssertionFailure: true,
    waitForConditionPollInterval: 300,
    waitForConditionTimeout: 500,
    throwOnMultipleElementsReturned: true
  },

  test_settings: {
    default: {
      screenshots: {
        enabled: true, // turn off and test won't freeze 
        path: 'screenshots' 
      },
      webdriver: {
        start_process: true,
        port: 4444,
        server_path: chromedriver.path,
        cli_args: ['--port=4444'],
        use_legacy_jsonwire: true
      },
      desiredCapabilities: {
        browserName: 'chrome',
        'goog:chromeOptions': {
          w3c: "true"
        }
      },
    },

  }
};

cucumber.conf.js

const fs = require('fs');
const { setDefaultTimeout, After, AfterAll, BeforeAll } = require('cucumber');
const {
  createSession,
  closeSession,
  startWebDriver,
  stopWebDriver,
  getNewScreenshots
} = require('nightwatch-api');
const reporter = require('cucumber-html-reporter');

setDefaultTimeout(10000);

BeforeAll(async () => {
  await startWebDriver();
  await createSession();
});

AfterAll(async () => {
  await closeSession();
  await stopWebDriver();
  setTimeout(() => {
    reporter.generate({
      theme: 'bootstrap',
      jsonFile: 'report/cucumber_report.json',
      output: 'report/cucumber_report.html',
      reportSuiteAsScenarios: true,
      launchReport: true
    });
  }, 1000);
});

After(function() {
  getNewScreenshots().forEach(file => this.attach(fs.readFileSync(file), 'image/png'));
});

Dependencies:

"devDependencies": {
    "@babel/core": "^7.9.6",
    "@babel/preset-env": "^7.9.6",
    "@babel/register": "^7.9.0",
    "chromedriver": "^81.0.0",
    "cucumber": "^6.0.5",
    "cucumber-html-reporter": "^5.2.0",
    "cucumber-pretty": "^6.0.0",
    "mkdirp": "^1.0.4",
    "nightwatch": "^1.3.5",
    "nightwatch-api": "3.0.1"
  }

Windows 10 Node: v10.16.3 npm: 6.9.0

ituradastra commented 4 years ago

I had the same timeout error, my workaround at the moment is transforming the custom command to async/await command https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands. Hope it will work for you as well until the bug is fixed.

LucaLis commented 4 years ago

Thanks a lot @ituradastra - your workaround works!

spnraju commented 3 years ago

Thank you @ituradastra for the help.