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

Error: function uses multiple asynchronous interfaces: callback and promise #872

Closed
arjunjh10 opened this issue Jul 3, 2017 · 7 comments

Comments

@arjunjh10
Copy link

arjunjh10 commented Jul 3, 2017

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|
      |xyz@email.com|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.

@charlierudolph
Copy link
Member

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?

@arjunjh10
Copy link
Author

arjunjh10 commented Jul 3, 2017

@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|
      |xyz@email.com|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.

@charlierudolph
Copy link
Member

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

@arjunjh10
Copy link
Author

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.

@arjunjh10
Copy link
Author

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

@charlierudolph
Copy link
Member

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

@lock
Copy link

lock bot commented Oct 25, 2018

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.

@lock lock bot locked as resolved and limited conversation to collaborators Oct 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants