javascriptkarate

Karate test feature file does not handle string concatenation for JS function call


I have a karate test feature file like below and I am doing a string concatenation in the first column of scenario examples. This works fine in all my other feature files.

But when I try to pass the concatenated string URL to a JS function it fails, it always passes literals. The Page and AssetType value get passed fine to Javascript, only the concatenated Url does not.

I tried various approaches already, e.g. passing concatUrl directly, using an explicit def for the concatenated string, using the Karate.get url function, no difference.

It seems the concatenation is not evaluated before the JS function is called?

How can I pass the value of concatUrl to the check_hashes.js function?

Feature: Asset Hash Validation

  Background:
    * def envConfig = karate.read('classpath:envs.json')[karate.env]
    * def baseUrl = envConfig['base_domain']
    * def basePort = envConfig['base_port']


  Scenario Outline: JS and CSS assets have hashes in their URLs
    Given url <concatUrl>
    Given path <Page>
    * def fullUrl = karate.get('url')
    * def params = { url: <fullUrl>, path: <Page>, assetType: <AssetType> }
    * def noHashCount = call read('check_hashes.js') params
    When method get
    Then status 200
    And match noHashCount == 0

    Examples:
      | concatUrl        | Page       | AssetType |
      | baseUrl + 'fr' + basePort  | '/fr/home' | 'css'       |
      | baseUrl + 'fr' + basePort  | '/fr/home' | 'js'        |
      | baseUrl + 'com' + basePort | '/en/home' | 'all'       |

Note: base_domain will be something like "http://www.example.", and base_port will be something like ":8080" - I want to be able to handle multiple toplevel domains in my tests and also have different ports for different environments, etc.


Solution

  • I found a way to make it work.

    I dropped the string concatenation (for other reasons as well) and in my envs.json now have

    "full_com_url": "http://www.example.com:8080",
    "full_fr_url": "http://www.example.fr:8080",
    

    I also drop the Background section (not needed), and then do

    Feature: Asset Hash Validation
    
      Scenario Outline: JS and CSS assets have hashes in their URLs
        Given url <fullUrl>
        Given path <Page>
        * def params = { url: '#(<fullUrl>)', path: <Page>, assetType: <AssetType> }
        * def noHashCount = call read('check_hashes.js') params
        When method get
        Then status 200
        And match noHashCount == 0
    
        Examples:
          | fullUrl      | Page       | AssetType |
          | full_fr_url  | '/fr/home' | 'css'     |
          | full_fr_url  | '/fr/home' | 'js'      |
          | full_com_url | '/en/home' | 'all'     |
    

    This will pass the actual value of fullUrl to the Javascript function instead of the literal string "fullUrl", which is what I needed.
    I can still keep the Examples table as I have different scenarios, and could even add another column to set an integer value for the noHashCount to check against.