vitalets / playwright-bdd

BDD testing with Playwright runner
https://vitalets.github.io/playwright-bdd/
MIT License
319 stars 40 forks source link

Feature: call step from step #110

Closed adamwood-novafori closed 8 months ago

adamwood-novafori commented 8 months ago

Hey, is there a way to reuse steps within other steps like you can in cypress cucumber preprocessor?

https://github.com/badeball/cypress-cucumber-preprocessor/blob/master/docs/cucumber-basics.md#nested-steps

vitalets commented 8 months ago

Currently it is not supported. We should think about it.

From one hand, it could be an easy way for people to re-use code without defining extra helpers. Some examples are in https://github.com/badeball/cypress-cucumber-preprocessor/issues/170. It is also exists in official Cucumber-ruby package.

From the other, calling steps from steps is considered anti-pattern in Cucumber docs:

In Cucumber-js calling steps from step definitions is not supported; this is by design.

There are several discussions in Cucumber repo with reasonable concerns about steps nesting:

In fact, playwright-bdd already supports calling step from step when using decorators syntax:

export @Fixture('todoPage') class TodoPage {
  constructor(public page: Page) { }

  @When('I create todo {string}')
  async createTodo(text: string) {
    // ...
  }

  @When('I create 2 todos {string} and {string}')
  async createTodos(text1: string, text2: string) {
    await this.createTodo(text1);
    await this.createTodo(text2);
  }

I like this approach most of all, b/c it's very native and relies on the code, not step titles. Feel free to share your thoughts on that.

adamwood-novafori commented 8 months ago

For the decorator approach can you have the decorators in the step files instead of the page objects? Then it would be very similar to SpecFlow in C# or cucumber java.

vitalets commented 8 months ago

For the decorator approach can you have the decorators in the step files instead of the page objects? Then it would be very similar to SpecFlow in C# or cucumber java.

Current JavaScript syntax does not allow decorators on functions, there is a proposal for that, but not very active.

I thought more about it and have another idea: When creating step definitions we can return a function that can call this step. It allows to re-use the step without extracting a helper function and avoids dependency on step title. For example:

const createTodo = When('I create todo {string}', async ({}, text: string) => {
  // ...
});

When('I create 2 todos {string} and {string}', async ({}, text1: string, text2: string) => {
  await createTodo(text1);
  await createTodo(text2);
});

What do you think?

adamwood-novafori commented 8 months ago

Ah, I see!

That could be a nice option, would you still be able to pass fixtures through the parameters also?

vitalets commented 8 months ago

would you still be able to pass fixtures through the parameters also?

I think no. Step implementation should have all needed fixtures inside, to be able to run the step in a usual way from gherkin. When some logic depends on fixtures, I guess it's a case for helper function.

adamwood-novafori commented 8 months ago

Cool, I like that way it looks clean, can we do that now or would you have to make a change?

vitalets commented 8 months ago

Will add this feature to the nearest release. Lets keep this issue open for that.

vitalets commented 8 months ago

That could be a nice option, would you still be able to pass fixtures through the parameters also?

After deeper investigation I've realized that we need to pass fixtures as parameters when calling steps. Otherwise Playwright will not know from outer step that these fixtures should be created.

Here is the updated syntax of calling steps:


const createTodo = When('I create todo {string}', async ({ page, myFixture }, text: string) => {
  // ...
});

When('I create 2 todos {string} and {string}', async ({ page, myFixture }, text1: string, text2: string) => {
  await createTodo({ page, myFixture }, text1);
  await createTodo({ page, myFixture }, text2);
});
adamwood-novafori commented 8 months ago

Sweet! I had a feeling it would need that. Nice work!

vitalets commented 8 months ago

Released in v6.1.0. See Call step from step in docs. Please re-check on your side and re-open in case of any issues.