Nested feature calls causing context errors in Karate

Viewed 215

I am using Karate for UI Automation. In one of my scenarios, part of the flow involves polling an account search in the UI of an application (Oracle Sales Cloud). We search a few times to compensate for delays in integration with other applications.

For that polling functionality, we created a flow like this:

  1. a search scenario - has the UI functionality for searching once
  2. a polling scenario - has a karate.repeat() to call the search scenario multiple times until it finds the account. This scenario also has other validations and prints for business reports, so we can't just get rid of it. We keep the polling as a separate component to avoid getting too repetitive, as lots of scenarios use it.

So the final flow looks something along these lines:

@searchAcctOnce Scenario: Do a single search account

  • (UI steps for search)

@pollAccount Scenario: poll account

  • ...
  • def searchAcct = function(i) { karate.call(@searchAcctOnce) }
  • karate.repeat(10, searchAcct)
  • ...

Scenario: Find account then do stuff

  • call read (@pollAccount)
  • ...
  • ...

As far as that goes, it works fine. The problem is when we're using general functions from a callSingle in karate-config.js:

After calling the nested @searchAcctOnce and returning to the scope of @pollAccount, something seems to change in the context, and we get the following error:

The value 'DynamicObject<JSFunction>@16e99306' cannot be passed from one context to another. The current context is 0x6f9ab79d and the argument value originates from context 0x54af3cb9.

To exemplify, I created this sample project that does basically the same: https://github.com/JVRD270/nestedCallsKarate

In it, we have the karate-config.js:

function fn() {
    var config = {};
    //var driverConfig={ type: 'chrome', showDriverLog: false, start: true, addOptions:['--disable-extensions','--disable-infobar', '--incognito'] };
    var driverConfig={
        type: 'msedgedriver', executable: "./msedgedriver.exe", webDriverSession: { capabilities: { browserName: 'edge' } }
       }
    karate.configure('driver', driverConfig);
    karate.configure('report', {showLog: true, showAllSteps: false, showRequest: true, showResponse: true});
    config.util = karate.callSingle('util.feature');
    return config;
}

Then a feature called nestedCalls.feature:

Feature: web-browser automation
    for help, see: https://github.com/intuit/karate/wiki/ZIP-Release

        Background:
        * configure driver = { type: 'chrome' }

        Scenario: Test nested calls context change
        * driver 'https://www.youtube.com/'
        * def search = call read("search.feature@pollAccount")

search.feature:

Feature:

        @pollAccount
        Scenario: Poll Account
        * def karateVideo = "//*[text()='Shotokan Karate Follow Along Class - 9th Kyu White Belt - Class #1']"
        * def searchOnce = function(i) { karate.call('search.feature@searchOnce') }
        * karate.repeat(5, searchOnce)
        * if(exists(karateVideo)) util.printSomething()

        @searchOnce
        Scenario: Search Once
        * def karateVideo = "//*[text()='Shotokan Karate Follow Along Class - 9th Kyu White Belt - Class #1']"
        * delay(5000)
        * if(!exists(karateVideo)) input('/html/body/ytd-app/div/div/ytd-masthead/div[3]/div[2]/ytd-searchbox/form/div[1]/div[1]/input', "karate")
        * if(!exists(karateVideo)) delay(5000)
        * if(!exists(karateVideo)) click('/html/body/ytd-app/div/div/ytd-masthead/div[3]/div[2]/ytd-searchbox/button')

and util.feature:

Feature: Utilities

        Scenario: Test nested calls
        * def printSomething = function() {karate.log("something")}

When you try to run this, the flow is

nestedCalls.feature -> search.feature@pollAccount -> search.feature@searchOnce -> search.feature@pollAccount (at which point it calls util.printSomething())

Then it fails with

The value 'DynamicObject<JSFunction>@16e99306' cannot be passed from one context to another. The current context is 0x6f9ab79d and the argument value originates from context 0x54af3cb9.

Also I'd like to point out that this happens not only with karate.repeat(), if we changed the repeat to a single call, that would also happen.

Is this a bug? What could be the work around?

Thanks for the help!

1 Answers

I hope this is fixed in this issue: https://github.com/karatelabs/karate/issues/1725

And you should be able to verify if you upgrade to 1.2.0.RC1

Else, we indeed have had a lot of trouble with callSingle() and a particular quirk in the JS engine. Please open an issue, I haven't looked at your example project yet or your question (too complex) - but I would recommend that it be as simple and minimalistic as possible if not already. This is the process we request you follow: https://github.com/karatelabs/karate/wiki/How-to-Submit-an-Issue

Related