codeceptjs / CodeceptJS

Supercharged End 2 End Testing Framework for NodeJS
http://codecept.io
MIT License
4.07k stars 720 forks source link

How to use custom_steps.js in gherkin steps? #1353

Open vitoo opened 5 years ago

vitoo commented 5 years ago

Hello,

i've made a custom fonction to extend the I

custom_steps.js

'use strict';
module.exports = function () {
    return actor({
        waitForLoading: function (seconds = 10) {
            this.waitForInvisible('div.loading', seconds);
        }
    });
}

codecept.json "include": { "I": "./custom_steps.js" },

loginSteps.js

Given('i login with username {string} and password{string}', (username, password) => {
    I.amOnPage('/');
    I.fillField('input#username', username);
    I.fillField('input#password', password);
    I.click('#login-btn');
    I.waitForLoading();
});

I got : I.waitForLoading is not a function

It work when i do a classic scenario :

login_test.js

Feature('Toast');
Scenario('test something', (I) => {
    I.amOnPage('/');
    I.fillField('input#username', 'eeee');
    I.fillField('input#password', 'xxxx');
    I.click('#login-btn');
    I.waitForLoading();
});

How can i make it work in gherkin steps ? Thank you !

Details

ManuGowda commented 5 years ago

Thank you @vitoo for posting this issue, I am also doing something similar in my project where I am using Codeception for testing APIs using BDD. I tried creating the custom_steps for BDD, looks like at the moment it only works for classic scenarios.

It will be really helpful if someone has any input or feedback on the same.

AdamOakman commented 5 years ago

I worked it around by including customSteps at the top of step definition file (in your case loginSteps.js):

const customSteps = require('../custom_steps.js');
const I = customSteps();

But in this case Gherkin steps are not displayed in console (and also in allure report) after running: codeceptjs run --features --steps which is not really cool.

Please advise.

vitoo commented 5 years ago

do you have this steps report with gherkin scenario @AdamOakman ? http://puu.sh/CcO9v/139820f048.png

even without your work arround the report fail for me

but at least it works with the customSteps, thanks !

austinmehmet commented 5 years ago

Might be able to write a helper instead

class WaitForLoadingHelper extends Helper {
  waitForLoading(seconds = 10) {
      // code goes here
  }
}

module.exports = WaitForLoadingHelper
{
"helpers": {
    "Puppeteer": {},
    "WaitForLoadingHelper": {
      "require": "./path/to/your/helper"
    },
    "Mochawesome": {}
  },
}

Because it is a helper and defined as such, it will automatically be added to the actors functions so you can directly call I.waitForLoading() in your step definitions

GSasu commented 5 years ago

I worked it around by including customSteps at the top of step definition file (in your case loginSteps.js):

const customSteps = require('../custom_steps.js');
const I = customSteps();

But in this case Gherkin steps are not displayed in console (and also in allure report) after running: codeceptjs run --features --steps which is not really cool.

Please advise.

Good solution though you could make this perfect by doing the following:

const I = actor();
const U = customSteps();

In your test you would then have

I.doSomethingCodeceptCanDoByDefault()
U.doSomeCustomActionsYouBuilt()

This way you would be able to have all steps shown as needed.

Let me know if you have problems with and will look for alternative solutions.

kaievns commented 5 years ago

this was a frustrating few hours of poking at the thing only to realise that none of the dependency injection features work in the BDD mode :(

you could at least mention that in the docs

lewimuchiri commented 1 month ago

This also seems to work, though it feels wrong. Not sure why it doesn't result in a cyclic reference yet I'm referecing I directly within the steps file:

//steps_file.ts
const I = actor();

export = function() {
  return actor({
    test: () => {
      I.say("HELLO WORD");
    }
  });
}
// feature file
  Scenario: Test actor
    Given test extend I object
//test.ts
Given("test extend I object", () => {
    return recorder.add(() => {
      I.test();
    });
  });

The code executes successfully and displays this:

   Given test extend I object ""
   HELLO WORD
  √ OK in 1138ms

  OK  | 1 passed   // 2s

I'm using this for the time being since everything seems to work.