cartman
cartman

Reputation: 190

retrieving a parameter ending before a specific string in cucumber-js

I tried to set this regex for an authentication Given step with two optional parameters:

Given(/^I log in as ([A-Za-z\-]+)(?: with the contract ((?:.(?!for the protal))+))?(?: for the protal (.*))?$/, 
  function(user, contract, portal, callback) { 
    console.log({user, contract, portal}); 
  }
);

Cucumber-js fails to detect the second optional parameter even if it successfully matches the expressions to the Given sentence with one, two or three parameters. I put .(?!for the protal) in the second parameter to end it when the third one (portal) eventually begins as the list of contracts isn't exhaustive.

Here's the output I get for the three cases:

Given I log in as tester1

user: tester1,

contract: undefined,

portal: undefined

OK

Given I log in as tester1 with the contract contract1

user: tester1,

contract: undefined,

portal: undefined

KO

Given I log in as tester1 with the contract contract1 for the protal portal1

user: tester1,

contract: portal1,

portal: undefined

KO

I think there is an issue with detecting this part of the regex .(?!for the protal) in cucumber-js as exactly the same expression works in Java. In addition to that, Cucumber in Java successfully sets to second parameter as undefined when only the first and the third are mentioned (but this is another issue).

Thanks !

Upvotes: 1

Views: 1399

Answers (2)

cartman
cartman

Reputation: 190

There is a bug in cucumber-js abour this issue: https://github.com/cucumber/cucumber-js/issues/1096

I resolved it temporarily by wrapping the contract by quotes using this expression:

/^I log in as ([\w-]+)(?: with the contract "([^"]+)")?(?: for the portal (.+))?$/

Upvotes: 0

kfairns
kfairns

Reputation: 3057

You'll need to do 3 versions of this step, one with contract, one with contract and portal and one without either.

Given(/^I log in as ([\w-]+)$/,(user)=>{
   // log in
});

Given(/^I log in as ([\w-]+) with the contract ([\w-]+)$/, (user, contract) => {
  // log in with contract
});

Given(/^I log in as ([\w-]+) with the contract ([\w-]+) for portal ([\w-]+)$/, (user, contract, portal)=>{
  // log in with contract for portal
});

Optional parameters aren't really a thing with cucumber, which is a slight issue, but as the steps are all trying to achieve different things (I know, technically they are all trying to log in, but what I mean is that they are logging in in different ways), using the same step with multiple options for completing it may mean that your step is trying to achieve too much.

Your step definition no doubt has multiple conditional statements inside it that are reliant on the parameters that come through. Why not simplifying it by defining them as different (yet similar) steps?

If you feel they are similar enough, a workaround to keep the code in the same place would be to create a login function that accepts 3 parameters, 2 of which are optional.

function logIn(user, contract = null, portal = null){
   // do your single step stuff here
}

Given(/^I log in as ([\w-]+)$/,(user)=>{
   return logIn(user);
});

Given(/^I log in as ([\w-]+) with the contract ([\w-]+)$/, (user, contract) => {
  return logIn(user, contract);
});

Given(/^I log in as ([\w-]+) with the contract ([\w-]+) for portal ([\w-]+)$/, (user, contract, portal)=>{
  return logIn(user, contract, portal);
});

Upvotes: 1

Related Questions