Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

It actually works with Codeception (PHP) - But there's a gotcha. #475

Open
Luc45 opened this issue Nov 10, 2023 · 2 comments
Open

It actually works with Codeception (PHP) - But there's a gotcha. #475

Luc45 opened this issue Nov 10, 2023 · 2 comments
Milestone

Comments

@Luc45
Copy link

Luc45 commented Nov 10, 2023

Describe the bug
At first, this extension doesn't seem to work with Codeception, as reported in this issue: #324

It turns out it's just a small Regex gimmick.

I've adapted gserver/src/steps.handler.js's getStepRegExp to run on Developer Tools for easier debugging. You can just copy and paste this on your Developer tools:

//Actually, we dont care what the symbols are before our 'Gherkin' word
//But they shouldn't end with letter
const startPart = '^((?:[^\'"\/]*?[^\\w])|.{0})';

//All the steps should be declared using any gherkin keyword. We should get first 'gherkin' word
const gherkinPart = `(Given|When|Then)`;

//All the symbols, except of symbols, using as step start and letters, could be between gherkin word and our step
const nonStepStartSymbols = `[^\/'"\`\\w]*?`;

// Step part getting
const stepRegExSymbol = '/';
// Step text could be placed between '/' symbols (ex. in JS) or between quotes, like in Java
const stepStart = stepRegExSymbol ? `(${stepRegExSymbol})` : `(\/|'|"|\`)`;
// ref to RegEx Example: https://regex101.com/r/mS1zJ8/1
// Use a RegEx that peeks ahead to ensure escape character can still work, like `\'`.
const stepBody = `((?:(?=(?:\\\\)*)\\\\.|.)*?)`;
//Step should be ended with same symbol it begins
const stepEnd = stepRegExSymbol ? stepRegExSymbol : '\\3';

//Our RegExp will be case-insensitive to support cases like TypeScript (...@when...)
const r = new RegExp(startPart + gherkinPart + nonStepStartSymbols + stepStart + stepBody + stepEnd, 'i');

Then run:

  • '@Then /I should see :arg1/'.match(r); // Match.
  • '@Then I should see :arg1'.match(r); // No Match.

It expects to find the step definition wrapped in JS or Java-style regex delimitators, which are / or backticks. However, Codeception generates the step definition without regex delimitators:

What it expects:

/**
 * @Then /I should see :arg1/
 */

How Codeception generates step definitions:

/**
 * @Then I should see :arg1
 */

Is it possible to update that Regex to accept a step definition without a Regex delimitator? If you're afraid it could lead to false positives, maybe it could be a opt-in setting that those using Codeception should enable?

@Luc45
Copy link
Author

Luc45 commented Nov 10, 2023

This works for me for single-line step definitions:

gserver/src/steps.handler.ts

if (this.settings.cucumberautocomplete.requireDelimiters) {
    // Step part getting
    const { stepRegExSymbol } = this.settings.cucumberautocomplete;
    // Step text could be placed between '/' symbols (ex. in JS) or between quotes, like in Java
    const stepStart = stepRegExSymbol ? `(${stepRegExSymbol})` : `(\/|'|"|\`)`;
    // ref to RegEx Example: https://regex101.com/r/mS1zJ8/1
    // Use a RegEx that peeks ahead to ensure escape character can still work, like `\'`.
    const stepBody = `((?:(?=(?:\\\\)*)\\\\.|.)*?)`;
    //Step should be ended with same symbol it begins
    const stepEnd = stepRegExSymbol ? stepRegExSymbol : '\\3';

    //Our RegExp will be case-insensitive to support cases like TypeScript (...@when...)
    const r = new RegExp(startPart + gherkinPart + nonStepStartSymbols + stepStart + stepBody + stepEnd, 'i');
} else {
    const stepBody = `((?:(?=(?:\\\\)*)\\\\.|.)*?)`;
    // Without delimiters, the step should be ended with a new line.
    const stepEnd = '\n';

    //Our RegExp will be case-insensitive to support cases like TypeScript (...@when...)
    const r = new RegExp(startPart + gherkinPart + nonStepStartSymbols + stepBody + stepEnd, 'i');
}

gserver/src/typings.d.ts

interface Settings {
    cucumberautocomplete: {
        ...
        requireDelimiters?: boolean
    }
}

client/package.json

"cucumberautocomplete.requireDelimiters": {
    "description": "Whether the step definitions should have regex delimiters.",
    "type": "boolean",
    "required": false,
    "default": true
},

If you'd like I could open a PR with this approach. Based on your experience, is it fine to use \n as a delimiter for the step definition, or should it support multi-lines?

@Luc45
Copy link
Author

Luc45 commented Nov 10, 2023

If it's possible to come up with a regex that matches with/without delimiters that'd be ideal, but I'm not sure what are the other use-cases to cover, so I was just playing with it

@alexkrechik alexkrechik added this to the 3.1.0 milestone May 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants