webdriverio / webdriverio

Next-gen browser and mobile automation test framework for Node.js
http://webdriver.io
MIT License
9.06k stars 2.51k forks source link

[Cucumber + v5] Using a positive look-ahead in Step RegExp throws Exception #4170

Closed nextlevelbeard closed 5 years ago

nextlevelbeard commented 5 years ago

Environment (please complete the following information):

Config of WebdriverIO Simple Cucumber setup.

Describe the bug Trying to use a non-capture group or a positive look-ahead in the regular expression that defines a Step Definition will throw an error. WDIO wants an extra step argument to be enunciated in the Step function.

To Reproduce Feature file:

Feature: Example

  Background: Open the Issues
    Given I go to the Issues page

  Scenario: Example Scenario
    When I do stuff
    Then I expect stuff

Trying to match these Gherkin Steps

Given I go to the Issues
Given I go to the Issues page

to a single Step Definition.

Given(/^I (?:go to|open) the (.*)(?= page$)/, function(page) {
// Do stuff
});

Despite being valid, webdriverIO throws an Exception :

function has 1 arguments, should have 2 (if synchronous or returning a promise) or 3 (if accepting a callback)

Expected behavior Should be able to use non-capture groups / positive look-ahead.

Log Not applicable.

Additional context

// Works!
Given(/^I (?:go to|open) the (.*) page$/, function(page) {
// Do stuff
});

// Is valid but does not work !!!
// Throws => function has 1 arguments, should have 2 (if synchronous or returning a promise) or 3 (if accepting a callback)
Given(/^I (?:go to|open) the (.*)(?= page$)/, function(page) {
// Do stuff
});

// Workaround (specify one more function argurment)
Given(/^I (?:go to|open) the (.*)(?= page$)/, function(page, uselessArgument) {
// Do stuff
});
mgrybyk commented 5 years ago

@nextlevelbeard are you sure this is webdriverio specific? I saw something similar here https://github.com/cucumber/cucumber-js/issues/872

nextlevelbeard commented 5 years ago

It should be 2 arguments according to your regexp

Can you double check? I believe it shouldn't. The second parentheses represents a positive-look-ahead, not a capture group.

If you add a second argument like so

Given(/^I (?:go to|open) the (.*)(?= page$)/, function(page, uselessArgument) {
// Do stuff
});

It will be undefined.

nextlevelbeard commented 5 years ago

@nextlevelbeard are you sure this is webdriverio specific? I saw something similar here cucumber/cucumber-js#872

Since I'm not using tables in my example, I don't believe it's the same problem.

mgrybyk commented 5 years ago

@nextlevelbeard it reproduces for me even with simple Given("qwe {string}", () => {}) if I pass no args to it.

Your regexp "I open the Issue page".match(/^I (?:go to|open) the (.*)(?= page$)/) results into ["I open the Issue", "Issue"].

May it be the problem?

nextlevelbeard commented 5 years ago

Both expressions match the Gherkin Step to the Step Definition. It matches with

"I open the Issue page".match(/^I (?:go to|open) the (.*)(?= page$)/)

and with

"I open the Issue page".match(/^I (?:go to|open) the (.*) page$/)

Otherwise, null would be returned.

For both those cases, index zero is the match, and index 1 is the first (and only) capture group / argument. For both cases the step definition is matched to the Gherkin step.

The problem is in the first case, webdriverIO throws an Exception, assumes the Step definition needs a second argument when there is only one argument. In fact, there is only one argument for both cases: Issues

wswebcreation commented 5 years ago

@nextlevelbeard

I've been checking this with a different framework that is also using CucumberJS and I got the same issue. this is not related to WebdriverIO, but the upgrade to CucumberJS V5.

Just an example, this is with Protractor and CucumberJS 5

Feature: Example

  Scenario: : Scenario 1
    Given I go to the Issues

  Scenario: Scenario 2
    Given I go to the Issues page
Given(/^I (?:go to|open) the (.*)(?= page$)/, (page) => {
    // Do stuff
    console.log('page = ', page);
});

My editor already provides me the info that the step Given I go to the Issues doesn't have a matching step.

Secondly when I run this scenario with Protractor I get this logs

Failures:

1) Scenario: Scenario 2 # test/cucumber/features/example.feature:6
   ✖ Given I go to the Issues page # test/cucumber/step_definitions/steps.js:17
       function has 1 arguments, should have 2 (if synchronous or returning a promise) or 3 (if accepting a callback)
   ✔ After # node_modules/protractor-cucumber-framework/lib/resultsCapturer.js:26

Warnings:

1) Scenario: : Scenario 1 # test/cucumber/features/example.feature:3
   ? Given I go to the Issues
       Undefined. Implement with the following snippet:

         Given('I go to the Issues', function () {
           // Write code here that turns the phrase above into concrete actions
           return 'pending';
         });

   ✔ After # node_modules/protractor-cucumber-framework/lib/resultsCapturer.js:26

4 scenarios (1 failed, 1 undefined, 2 passed)
8 steps (1 failed, 1 undefined, 6 passed)
0m00.004s

I'd advice you to contact the CucumberJS project and ask what's wrong

mgrybyk commented 5 years ago

Closed according to @wswebcreation

Please feel free to reopen if it is wdio related.