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

karate.eval fails if there is nothing for it to do #2046

Closed
keithdtyler opened this issue Jun 30, 2022 · 6 comments
Closed

karate.eval fails if there is nothing for it to do #2046

keithdtyler opened this issue Jun 30, 2022 · 6 comments
Labels

Comments

@keithdtyler
Copy link

keithdtyler commented Jun 30, 2022

Ran into this trying to use def variables in Examples: tables for scenario outlines.

It seems that if karate.eval() has nothing to actually do in the passed value, it will throw an exception:

org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (eval) on com.intuit.karate.core.ScenarioBridge@4f4c789f failed due to: Cannot convert '...'(language: Java, type: com.intuit.karate.graal.JsMap) to Java type 'java.lang.String': Invalid or lossy primitive coercion.

The issue seems to arise when passing a JSON object that does not contains variables to expand (at least).

In my case I wanted to put variables (defined, say, in Background) in a JSON object in the examples table, for use in populating scenario values in the feature (in practice this would not be a fixed value, but, say, a timestamp):

Background: test
  * def value = 123
  
Scenario Outline: scenario
  * karate.set(karate.eval(example))
  * print foo
  * print bar
Examples:
  | example! |
  | {foo: value, bar: 0} |
  | {foo: 0, bar: value} |
  | {foo: 0, bar: 0} |  

The ! in the examples column header makes sure Karate sees the value as a JSON object, but it seems that examples tables simply do not expand variables within them (I also tried "#(...)" notation). So, the karate.eval() within the scenario re-parses the object to expand the variables (here 'value') in the object.

The first two examples work fine. In both cases, 'value' is replaced with its assigned number, resulting in, respectively:

  • {foo: 123, bar: 0}
  • {foo: 0, bar: 123}

However, in the last example, it blows up with the exception mentioned above. The same values used in the other examples work, but it seems when there is nothing to expand, the eval fails.

The workaround I ended up doing is, amusingly, creating a def called "zero" in my Background, assigned with 0, and using the var name "zero" instead of 0 in at least one of the places in the third example. Which works.

This is using karate-core 1.1.0 under Java 8 on Intel MacOS Monterey.

@ptrthomas
Copy link
Member

@keithdtyler the design is such that no variable resolution is allowed / supported at all in an Examples table. a possible way to work around this is as follows:

Feature:

  Background:
    * def value = 123
    * def data = [{ foo: '#(value)', bar: 0 }]

  Scenario Outline: scenario
    * print foo
    * print bar

    Examples:
      | data |

there is a proposal to make dynamic scenarios play well with Background here: #1905

@ptrthomas
Copy link
Member

just one more thing, if you want a table that supports variables, use table: https://github.com/karatelabs/karate#table

@keithdtyler
Copy link
Author

keithdtyler commented Jul 3, 2022

I don't really think you follow where the problem is here. The problem isn't specifically with examples tables, the problem is with karate.eval(). The use of examples tables is incidental to the issue identified. Not sure where that wasn't pretty fairly explained in my report.

if karate.eval() has nothing to actually do in the passed value, it will throw an exception:

I think I was pretty comprehensive in my explanation... not sure what was missed.

@ptrthomas
Copy link
Member

@keithdtyler then please provide an example that demonstrates the problem without using tables. as of now I still consider this a wontfix

@keithdtyler
Copy link
Author

I looked at it further and it does seem to be related to tables. But it doesn't involve variable resolution in tables (which was not the issue above either), but rather, how the ! modifier on the tables column header is parsing the value in the row.

Scenario Outline: scenario
* def value = 123
* karate.log("received type "+(typeof example)+": |"+example+"|")
* karate.log(karate.eval(example))`

Examples:
  | example! |
  | {foo: value, bar: 0} |
  | {foo: 0, bar: value} |
  | {foo: 0, bar: 0} |

16:31:51.119 [main] INFO com.intuit.karate - received type string: |({foo: value, bar: 0})|
16:31:51.129 [main] INFO com.intuit.karate - {
"foo": 123,
"bar": 0
}

16:31:51.143 [main] INFO com.intuit.karate - received type string: |({foo: 0, bar: value})|
16:31:51.145 [main] INFO com.intuit.karate - {
"foo": 0,
"bar": 123
}

16:31:51.176 [main] INFO com.intuit.karate - received type object: |[object Object]|
16:31:51.180 [main] ERROR com.intuit.karate - src/test/java/features/scte35/eval_test.feature:6

  • karate.log(karate.eval(example))
    js failed:

01: karate.log(karate.eval(example))
<<<<
org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (eval) on com.intuit.karate.core.ScenarioBridge@39109136 failed due to: Cannot convert '{foo=0, bar=0}'(language: Java, type: com.intuit.karate.graal.JsMap) to Java type 'java.lang.String': Invalid or lossy primitive coercion.

  • .:program(Unnamed:1)

For some reason, when the value in the examples table contains a variable, the ! modifier passes the row value as a string. But when the value in the examples table does not contain a variable, it passes it as an object, which fails karate.eval().

So the behavior of the ! is inconsistent based on whether the value in the row contains a variable or not.

@ptrthomas
Copy link
Member

@keithdtyler I have nothing to add to my previous comment. all the code is open-source, you are welcome to attempt a PR / fix against this ticket

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

No branches or pull requests

2 participants