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

Missing header in spite of "configure headers" #2539

Open
donholgo opened this issue Mar 28, 2024 · 5 comments
Open

Missing header in spite of "configure headers" #2539

donholgo opened this issue Mar 28, 2024 · 5 comments

Comments

@donholgo
Copy link

To be able to run my tests with an external authentication tool, I have tried to factor out the authentication request into a separate file, but the configure headers in that file does not seem to have any effect in the tests.

The problem can already be reproduced with the attached files (without any real authentication and just a dummy call to example.com):

header.feature

Feature: Header

  Scenario: Set Authorization header
    * karate.log("Header scenario is called")
    * configure headers = { Authorization: 'Basic 123456' }

test.feature

Feature: Test

  Background:
    * url 'http://example.com'
    * karate.callSingle('header.feature')

  Scenario: Some test
    When method GET
    Then status 200

Running

java -classpath ~/karate/karate-1.4.1.jar com.intuit.karate.Main test.feature

shows that header.feature is called properly, but the GET call in test.feature does not have the "Authorization" header that should have been set.

1 > GET http://example.com
1 > Host: example.com
1 > Connection: Keep-Alive
1 > User-Agent: Apache-HttpClient/4.5.14 (Java/21.0.1)
1 > Accept-Encoding: gzip,deflate

testfiles.zip

@dvargas46
Copy link
Contributor

Likely due to no shared scope here. karate.call and karate.callSingle do not default to shared scope. In fact, I don't think callSingle even has an option for that.

Can you try this instead:
* callonce read('header.feature')

@donholgo
Copy link
Author

donholgo commented Apr 2, 2024

That works indeed, at least in the simplified example files. In my real tests I'd like to have the call configurable, though (we have a development mode that doesn't need it), so it really looks like

* if (useAuthentication) karate.callSingle('header.feature', { username: 'myuser' } )

Any idea how I can have that with callonce?

@dvargas46
Copy link
Contributor

Yes, that can be achieved by putting the conditional within the called feature/js instead.

However, this would be arguably less readable since someone would have to check the called file to find out the condition, plus it's a wasted read/call to the file in dev. Tho, maybe that's all you need given that there's no shared scope overload for callSingle.

@ptrthomas , how would you feel about karate.callSingle having an overload for shared scope to be in parity with karate.call ?

@ptrthomas
Copy link
Member

@dvargas46 yes I think that makes sense. interesting why this has not come up before. I was looking at the existing reference example:

  1. https://github.com/karatelabs/karate/blob/03a840805ec0db5ec3f4330754545f1eefbcde0b/karate-demo/src/test/java/karate-config.js
  2. https://github.com/karatelabs/karate/blob/2e73fc38e397cf4e46c38b5256c0d91261ea5920/karate-demo/src/test/java/demo/headers/headers-single.feature

so even the examples, the pattern is - a) callSingle returns some data b) that data is used to configure headers "centrally" in karate-config.js

@dvargas46
Copy link
Contributor

@ptrthomas I think you are right, I believe what you outlined would be the recommended pattern to use here too.

For example, it could looks something like this to set the auth header globally instead using callSingle:

karate-config.js

function fn()  {
  const config = {}
  const headers = {}

  if (karate.env !== 'dev') {
    // configure headers with authentication only in non-dev environments - callSingle only called once
    const results = karate.callSingle('header.feature', {username: 'myUsername'})
    headers.Authorization = results.authHeader
  }

  //
  // any other headers or config variables can also be set ...
  //

  karate.configure('headers', headers)

  return config
}

header.feature

@ignore
Feature: Header

  Scenario: Return Authorization header
    # or perform some operation with the input first, like Base64 encoding of credentials, etc.
    * def authHeader = 'Basic 12345'

test.feature

Feature: Test

  Background:
    * url 'http://example.com'
    # set any scenario specific headers as needed
    * header X-TOKEN = 'token-needed-here'

  Scenario: Some test
    When method GET
    Then status 200

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants