Cucumber-js: Error: function uses multiple asynchronous interfaces: callback and promise

Created on 3 Jul 2017  ·  7Comments  ·  Source: cucumber/cucumber-js

Hello Everyone,
I have a case where I am unable to use async in the step definitions.
I have a simple scenario where in am logging in through the api interface of my application to fetch auth token
My feature file is:

Feature: Login
  Scenario: Login using api
    Given I login to my account with my username and password
    Then I should get an authorization token
      |username|password|
      |[email protected]|dev|

my steps are :

defineSupportCode(({ Given, Then, setDefaultTimeout }) => {
  const timeOut = 30000;
  const baseSteps: BaseSteps = new BaseSteps();
  setDefaultTimeout(timeOut);

  // tslint:disable-next-line:only-arrow-functions
  Given(/^I login to my account with my username and password$/, async (table: TableDefinition) => {
   const userData = table.hashes();

    const loginResponse =  await baseSteps.loginUser(userData[0].username, userData[0].password);


    console.log('Login response is ', loginResponse);
    const statusCode = 302;

    expect(await loginResponse.status).to.equal(statusCode);
  });

   Then(/^I should get an authorization token$/, async () => {
    const authorizationHeader = await baseSteps.getAuthorizationHeader();
    console.log('Auth Header', authorizationHeader);
    expect(authorizationHeader).to.not.equal(null);

    const orders = await fetch('url',
      {
        method: 'GET', headers: {
          authorization: authorizationHeader
        }
      });

    // tslint:disable-next-line:no-console
    console.log(await orders.json());
  });
});

And my helper functions in the BaseSteps.ts are as follows:

 async loginUser(userName: string, password: string): Promise<Response> {
    const getSignInFormResponse = await fetch(this.getInitialRequestUrl(),
      {
        method: 'GET'
      });

    const form = <some-form-data>;

    const loginResponse = await fetch(getSignInFormResponse.url,
      {
        method: 'POST',
        headers: {
          'content-type': 'application/x-www-form-urlencoded'
        },
        body: form,
        redirect: 'manual'
      });

      return loginResponse;
  }

async getAuthorizationHeader() {
    const tokenResponse = await fetch(this.getInitialRequestUrl(),
      {
        method: 'GET',
        redirect: 'manual'
      });

    const tokenInfo = qs.parse(tokenResponse.headers.get('location'));
    const authorizationHeader = `${tokenInfo.token_type} ${tokenInfo.access_token}`;

    return authorizationHeader;
  }

When i run my scenario it fails with the following error:

Error: function uses multiple asynchronous interfaces: callback and promise

on the line where my Given starts

Please help me fix this error.

Most helpful comment

Your Given step definition has a table argument while in your feature file, it does not have a table. Cucumber-js determines if you are using the callback interface based on the number of arguments in your step definition. If the number is one more than the number of arguments that are passed in, then it assumes you are using the callback interface. Since you are also returning a promise, it determines you are using the promise interface. Only one interface at a time can be used.

Thoughts on updating the error message to include something about the fact that the callback interface is assumed because the step definition has X number of arguments?

All 7 comments

Your Given step definition has a table argument while in your feature file, it does not have a table. Cucumber-js determines if you are using the callback interface based on the number of arguments in your step definition. If the number is one more than the number of arguments that are passed in, then it assumes you are using the callback interface. Since you are also returning a promise, it determines you are using the promise interface. Only one interface at a time can be used.

Thoughts on updating the error message to include something about the fact that the callback interface is assumed because the step definition has X number of arguments?

@charlierudolph Hey mate thanks for your reply, but I didnt quite understand why you said that my feature file does not have a table in it?

  Given I login to my account with my username and password
    Then I should get an authorization token
      |username|password|
      |[email protected]|dev|

isnt how we pass the table in the feature file?
Took inspiration from here https://github.com/cucumber/cucumber-js/blob/master/features/data_tables.feature

Yeah the error message could be a bit more clearer..
Thanks again.

I meant that in your feature file, your Then step has a table but your Given step does not.

Uhh damn.. Yeah you are right.. I mistook table to be an example sorry for the confusion. I guess it would be alright now. If the problem persists i shall come back to ask questions again.

Closing the issue as @charlierudolph helped me figure out my own coding error in the feature file.

Glad its working for you. I'll open a separate issue for updating the error message to hopefully make this easier to figure out in the future

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings