The following are passing on 0.9.5:
Feature: match_contains
Scenario: Deeply nested contains used to work in 0.9.5 but in 0.9.6 seems to require all fields to be present
Given def message =
"""
{
"correlationId": "101",
"text": "Hello to everyone",
"data": {
"deeply": {
"nested": "no",
"id": "1010"
}
}
}
"""
Then match message contains { text: "Hello to everyone" }
Then match message contains { data: { deeply: { nested: "no" } } } }
Scenario: Match contains for sublist works even if simple list elements are reversed
Given def message =
"""
{
order_id: 5,
products: [100,101]
}
"""
Then match message contains { order_id: 5, products: [101, 100] }
Scenario: Match contains for sublist works even if complex list elements are reversed
Given def message =
"""
{
order_id: 5,
products: [
{ product_id: 100, name: "bicycle" },
{ product_id: 101, name: "car" }
]
}
"""
Then match message contains
"""
{
order_id: 5,
products: [
{ product_id: 101, name: "car" },
{ product_id: 100, name: "bicycle" }
]
}
"""
0.9.6.RC3 + Latest develop (as of an hour ago or so)
Scenario 1:
match_contains.feature:22 - path: $.data.deeply, actual: {nested=no, id=1010}, expected: {nested=no}, reason: actual value has 1 more key(s) than expected: {id=1010}
Scenario 2:
21:15:30.173 [ForkJoinPool-1-worker-3] ERROR com.intuit.karate - assertion failed: path: $.products[0], actual: 100, expected: 101, reason: [path: $.products[0], actual: 100, expected: 101, reason: not equal (Integer)]
match_contains.feature:29 - path: $.products[0], actual: 100, expected: 101, reason: [path: $.products[0], actual: 100, expected: 101, reason: not equal (Integer)]
Scenario 3 equivalent of 2.
I have reproduced this here: https://github.com/KostasKgr/karate-issues/blob/match_contains_issues/src/test/java/examples/match_contains.feature
The above is with 0.9.5, tried with 0.9.6.RC3 and 2.0.0 which i hopefully built correctly from latest develop.
okay - we have a new contains deep that needs to be documented better thanks to @abhi-rao in #1080 - will keep this ticket open to fix the docs
Then match message contains deep { data: { deeply: { nested: "no" } } } }
can you confirm the rest is also ok ?
Thanks for the prompt response @ptrthomas!
Scenarios 1 & 2 work with contains deep. Scenario 3 seems to match two step definitions and fails, tested on 0.9.6.RC3 and latest (?) develop ( 2f8765b32ade37f8da2ef8b201d890fc7818874c )
I have updated the repo above with the contains deep version.
Scenario: Match contains for sublist works even if complex list elements are reversed
Given def message =
"""
{
order_id: 5,
products: [
{ product_id: 100, name: "bicycle" },
{ product_id: 101, name: "car" }
]
}
"""
Then match message contains deep
"""
{
order_id: 5,
products: [
{ product_id: 101, name: "car" },
{ product_id: 100, name: "bicycle" }
]
}
"""
match_contains.feature:43 - more than one step-definition method matched: match message contains deep - [public void com.intuit.karate.StepActions.match(java.lang.String,java.lang.String,java.lang.String) [message , contains, deep], public void com.intuit.karate.StepActions.matchDocstring(java.lang.String,java.lang.String,java.lang.String) [message contains , deep]]
Was checking out the 2 steps that match, made me wonder why scenario 2 works, if "message contains" ends up being the expression, but it seems the whole string is concatenated again later.
@Override
@When("^match (.+)(=|contains|any|only|deep)( .+)$")
public void match(String expression, String operators, String rhs) {
MatchStep m = new MatchStep(expression + operators + rhs);
context.match(m.type, m.name, m.path, m.expected);
}

@KostasKgr I tried a little bit and am giving up. you can do this in 2 steps:
* def expected =
"""
{
order_id: 5,
products: [
{ product_id: 101, name: "car" },
{ product_id: 100, name: "bicycle" }
]
}
"""
* match message contains deep expected
the regexes need tweaking, maybe you can figure :)

Yeah, was contemplating how to change the regexes, didnt have a good idea yet, because "contains" is a subset of "contains deep"
Are you considering tracking the docstring version of match in a separate issue, and have this one for the deep documentation?
Do "contains any" and "contains only" work with docstring? I suppose they have the same problem? Was it always like this or regressed in 0.9.6?
Cheers
@KostasKgr good news and thanks for the discussion - an alternative simpler approach clicked in my head. feels good to have solved it finally ! yes this was always like this :) very rarely needed though
Oh nice!
I was playing around with regex before i read your last response, ended up with the following for the normal ones:
^match (.*? )(contains deep|contains any|contains all|contains|==)( .*)$
If you remove the dollar it probably works to unify them in one step as you have it in your last commit

I tried out the one you committed earlier, not sure op2 and rhs is what you would expect, since you have only 3 capturing groups, so rhs will probably always be null.

If all you do is concatenate it and pass it to matchstep then it doesnt really matter matching them exactly though
It also matches the following, not sure if you want those either, I would have to check the documentation again:
match mpla deep
match mpla any
match mpla all
match mpla =
But it is interesting to have op2, i hadnt thought of that. Though since any is not valid and only contains any is valid it might work better as one operator. Not sure if java parses regex the same way as https://regex101.com/ , but when i put contains at the end of the alternative match it worked as I wanted it to.
Cheers
@KostasKgr the rhs comes into the picture for the "docstring" variation. it will be null as a capturing group but will be set from karate internals (the stuff between the triple-quotes), I think I'll leave as it is now
Oh! didn't know that rhs works like that! Awesome! :) I will give the latest commit a spin :)
All three scenarios I had posted pass with latest develop, cheers
0.9.6 released
Most helpful comment
@KostasKgr the rhs comes into the picture for the "docstring" variation. it will be null as a capturing group but will be set from karate internals (the stuff between the triple-quotes), I think I'll leave as it is now