hello all, what’s the JS equivalent of `queryParam...
# pact-js
u
hello all, what’s the JS equivalent of
queryParameterFromProviderState
from java-land?
m
I think it’s just
fromProviderState
, which can be used where matchers are used, in this case on the
query
property
u
right! That’s what I thought. Any examples I can take a look at by any chance? We can’t get it to work 😞
m
Let me see
u
right, that’s what we’re doing. And this is what I quite don’t understand:
Copy code
"query": {
            "$.entityVersion[0]": {
              "expression": "${v2Version}",
              "type": "ProviderState"
            }
          }
that’s what ends up in the contract. Will that result in a
POST /path/to/entity?entityVersion=${v2Version}
or
entityVersion=[${v2Version}]
?
context: we’re trying to debug why these contracts are failing and the first thing we noticed is that versions were either not passed or hardcoded to the unit test’s UUID, now verifications are failing with a 500 (still haven’t tried turning logging levels higher on the provider side because java+logging is a mess and I actively try to avoid that)
m
hmm good question. It depends on the query “array” syntax used by the core - I actually don’t remember which style it uses (repeated fields or
entityVersion[]=
style). I believe it will store the parameters as an array though in the contract
Probably if you enable verbose/debug level logging in the verification, you’ll see the request the verifier fires at your service
u
I’ll give it a go. Thanks!
m
@uglyog is the above ^^ related to https://github.com/pact-foundation/pact-reference/issues/355 at all? The related issue mentions headers, but the serialised query looks similar
u
interesting; the contract in principle is fine if what happened then while sending the request didn’t look like this:
Copy code
{
  "version": [
    "741ffe00-8c59-4275-bdd5-385b8249b992"
  ]
}
and more like
Copy code
{
  "version": "741ffe00-8c59-4275-bdd5-385b8249b992"
}
instead
because when you have query parameters, one way to send an array is to repeat
param=value&param=value…
right?
m
Yes exactly. There are many ways to encode arrays (or indeed, objects) in query strings. Unfortunately there is no standard. We might need to have a way to tell the contract the serialisation mechanism (see e.g. https://swagger.io/docs/specification/describing-parameters/). The implementation looks ambiguous at the moment. @uglyog do we have any definitive statement on handling query strings anywhere?
r
The fix for #355 is for both headers and query parameters
thankyou 1
m
Thanks Ron. On query strings, do we have any statements on what format they take during verification?
r
I don't recall any statements, but there may be some in the specs
m
It only mentions serialisation, and not how the request is sent by the verifier
r
The verifier uses the reqwest HTTP client. That will be responsible for serialising the query parameters
👍 1
u
‘Calling
.query(&[("foo", "a"), ("foo", "b")])
gives
"foo=a&foo=b"
’ seems to imply that
Copy code
"query": {
            "$.entityVersion[0]": {
              "expression": "${v2Version}",
              "type": "ProviderState"
            }
          }
should result in requests which end with
?entityVersion=UUID_HERE
, or am I misreading?
m
That's how I read it also
FYI a fix for the query and header generators in the pact file went out today. You might need to re-install the latest Pact or do an update on the
@pact-foundation/pact-core
dependency
u
ah, cool, thanks for the heads up, we’ll give it a go 👍
👍 1
m
hey! following up on this, someone knows when will pact-js library update its pact-core dependency to have that last fix? we mostly use pact-js to generate our tests
m
Can you please run this command:
Copy code
npm list @pact-foundation/pact-core
in the project that’s not working?
m
sure
thankyou 1
oh, we still have a previous pact-js version which was fixed on core 13, thats why it didn't change when we upgraded the core one. changing this one first , hopefully not many changes will be needed
m
ohh right. Which version of Pact JS are you on?
m
10.4.1
m
oh, yes, that’s a few major versions behind.
m
we dont have many tests though. the js side has started recently. so ill try the update
👍 1
m
Actually, the major change was 9 -> 10
I think probably it won’t be anything major
Oh yeah, see: https://github.com/pact-foundation/pact-js/blob/master/CHANGELOG.md One was making the node version minimum 16 and another was a minor change to
MessageStateHandlers
m
great 🙂
yeah, just made a small edit and now its working. trying now our pipeline after the change 🙂
🎉 1
seems like its still working as before. the variable injected in the query is still the example value and not the one that should come from the provider 😕
m
Ah, this thread is so long I think we’re talking across purposes. The problem (or potential problem) we were discussing was the serialisation in the pact file, but there was a “problem” that wasn’t articulated. So the problem is clearer (ish) now. Are you using JS on both sides? Is the verification JS or Java? Can you please also share the contract (or relevant bits)?
m
No, we have Js on the consumer and Java on the Provider The publish and can-i-deploy are done with JS
👍 1
m
So just for reference, the fix was actually for a different issue, but it looked like it might also be affecting the query string serialisation. So we have a few things we’ll need to check off to confirm where the problem may lie
👍 1
m
regarding the contract its what Ulisses shared above. We're trying to add a variable in the query path that is being added with the array.. but using the default value insstead of one that should come from the provider state
👍 1
m
thanks, has the serialisation changed since Ulisses first shared it or is it exactly the same?
m
👍 1
which in the code is coming from:
query: {basketVersion: fromProviderState('${basketV2Version}', v2Version)},
inside the provider.withRequest
m
thx, can you please show the matching rules/generators section?
m
Copy code
"query": {
      "$.basketVersion[0]": {
        "expression": "${basketV2Version}",
        "type": "ProviderState"
      }
    }
this part?
👍 1
m
thanks. It looks the same as the above to me. That may or may not be correct. What does the provider verification setup look like for this?
m
so when they set the state from the provider state?
1
u
that’s us, it’s a java app, and in the state method we have something like
Copy code
state.put("basketV2Version", internalBasketV2.getBasketVersionUUID());
👍 1
for another consumer (using pact-jvm) this works just fine, which is why we’re trying to figure if this is 1) a pact-js bug 2) pact-js misuse 3) both
m
do you happen to have a contract for a working one?
u
I can probably get it, 1sec
m
thx. No hurries, I’ll be heading to bed any moment
Rest assured this thread will occupy my nightmares 😉
1
u
Copy code
"query": {
            "basketVersion": {
              "dataType": "STRING",
              "expression": "basketVersion",
              "type": "ProviderState"
            }
          }
managed — right before your bedtime!
😆 1
m
what spec version is that? (and is it different to the JS one?)
u
it’s V3 according to the test itself:
Copy code
@PactTestFor(pactMethod = "updateBasketPutAsyncV2", pactVersion = PactSpecVersion.V3)
👍 1
m
in js we have this
const mockProvider = new PactV3({
so think it should be the same. (btw, im new here, seeing all of this for the first time)
👍 1
m
I might need somebody with a higher pay grade to look at this tomorrow. But thanks, I think we might have enough to at least get to the next stage.
🙌 1
m
thank you very much for the help till now 🙂
🙌 1
m
You’re welcome folks
@rholshausen I could do with your eyes on this. It’s is quite a long thread so I will try to summarise: The JS DSL is producing this generator for a query string (they’re on the latest version):
Copy code
"query": {
      "$.basketVersion[0]": {
        "expression": "${basketV2Version}",
        "type": "ProviderState"
      }
    }
It comes via this call in the JS client:
Copy code
query: {basketVersion: fromProviderState('${basketV2Version}', v2Version)}, inside the provider.withRequest (edited)
On the provider side, when verifying, they use this to inject the parameter:
Copy code
state.put("basketV2Version", internalBasketV2.getBasketVersionUUID());
However, the value in the contract is still used. When looking at another test that does work (generated by Java), the generator in the contract looks different:
Copy code
"query": {
            "basketVersion": {
              "dataType": "STRING",
              "expression": "basketVersion",
              "type": "ProviderState"
            }
          }
It’s curious that both the expression is different (no
$
business) and there is also no path to
basketVersion
in this contract. Both are version 3 contracts, apparently.
r
Firstly, this is wrong:
$.basketVersion[0]
, that is what the fix I released addressed. I.e., with this expression, the generator won't match the proper query string value, it will try create a query string like
?%24.basketVersion%5B0%5D=VALUE
and not
?basketVersion=VALUE
👍 1
Secondly, you can use either an expression or just the key name. So,
"expression": "basketVersion"
and
"expression": "${basketVersion}"
are equivalent
👍 2
m
ok cool, thanks
r
I don't think this
Copy code
"query": {
      "$.basketVersion[0]": {
        "expression": "${basketV2Version}",
        "type": "ProviderState"
      }
    }
will do anything. I'm pretty sure the process works by going through the query parameters and looks for a matching query parameter
👍 1
m
Thanks. I’ll try a repro on the latest version.
r
So unless the actual query parameter is
$.basketVersion[0]
it will never get applied
m
Yeah, pretty sure it’s not
@Miguel Heitor I think maybe you’re not on the latest
pact-core
version. After an
npm update @pact-foundation/pact-core
in a test project and then creating a version, I get the fixed generator:
Copy code
"generators": {
          "query": {
            "basketVersion": {
              "expression": "${basketV2Version}",
              "type": "ProviderState"
            }
          }
Thanks for confirming Ron.
u
just to add/confirm: it’s the wrong matcher that’s tripping us up, not the value, etc. because for pact-jvm it all works as expected
m
You could probably test it locally, by downloading/acquiring the (currently broken) contract, modifying the
generators
section with the correct one and running the Java test with it. If that passes, we know it’s an issue with the contract serialisation
just to add/confirm: it’s the wrong matcher that’s tripping us up, not the value, etc. because for pact-jvm it all works as expected
you use the word “matcher” here, and not generator. Just want to make sure we’re on the same page too! I haven’t looked at the matcher for this either, but the generator was definitely wrong. The generator is what’s used during provider verification, where a value is generated dynamically. In this case, the generator gets the dynamic value from
state.put(..)
expression. my understanding is that this expression is having no effect, so the default value in the contract is being used. Is that correct?
👌 1
I’ve just checked, and not surprisingly both the matcher and generator definition were incorrect:
Copy code
"generators": {
          "query": {
            "$.basketVersion[0]": {
              "expression": "${basketV2Version}",
              "type": "ProviderState"
            }
          }
        },
        "matchingRules": {
          "query": {
            "$.basketVersion[0]": {
              "combine": "AND",
              "matchers": [
                {
                  "match": "type"
                }
              ]
            }
          }
        },
but are fixed in the latest:
Copy code
"generators": {
          "query": {
            "basketVersion": {
              "expression": "${basketV2Version}",
              "type": "ProviderState"
            }
          }
        },
        "matchingRules": {
          "query": {
            "basketVersion": {
              "combine": "AND",
              "matchers": [
                {
                  "match": "type"
                }
              ]
            }
          }
        }
u
you use the word “matcher” here, and not generator. Just want to make sure we’re on the same page too!
sorry, still learning the terminology 🙂
🙈 1
good to see that it should be fixed in the latest version too (thanks for confirming) ❤️
m
No worries!
If you/Miguel can confirm the version of `@pact-foundation/pact`/ (+
pact-core
) is in the project that would help
u
that’s @Miguel Heitor, we’ll confirm the versions (and upgrades) as the day progresses (still early morning here)
👍 1
m
Yep I thought you were up early (in fact, you seem to be an early bird given our overlap 😉 )
m
hey hey! 🙂 checking the versions here in the project:
Copy code
➜  bash git:(antripathi/CT-basketversion2) npm list @pact-foundation/pact-core
nodejs@0.0.1 /Users/mheitor/git_tree/nodejs
├── @pact-foundation/pact-core@14.0.6
└─┬ @pact-foundation/pact@12.1.2
  └── @pact-foundation/pact-core@14.0.6 deduped

➜  bash git:(antripathi/CT-basketversion2) npm list @pact-foundation/pact
nodejs@0.0.1 /Users/mheitor/git_tree/nodejs
└── @pact-foundation/pact@12.1.2
seems like there is a new core version from 15hrs ago, going to update to that one first and then recreate the pact files
pact-core: ├─ @pact-foundation/pact-core@14.1.0 └─ @pact-foundation/pact@12.1.2 └─ @pact-foundation/pact-core@14.0.6 pact-js: └─ @pact-foundation/pact@12.1.2
ive just generated the pacts file and the generators are the same as before 😕
well, last update.. i removed the node_modules, updated to last version from both dependencies and made sure that pact-js was with the correct pact-core last version. now this seems to be finally working 🙂
Copy code
"generators": {
  "path": {
    "expression": "/v2/${basketV2Id}/item/${insuranceItemId}",
    "type": "ProviderState"
  },
  "query": {
    "basketVersion": {
      "expression": "${basketV2Version}",
      "type": "ProviderState"
    }
  }
},
no more [0] in there
🙌 1
🎉 1
trying to fix now the issues after the upgrade and will come back later when i see that the value is being correctly injected
m
Awesome - looks much better!
m
If the pact file is correct now, this value that shows up here in the UI, should still be the one that i give as example?
i would expect it to be a different one, coming from the set state on the provider. the test keeps failing and im wondering about that value
u
that’s a red-herring, this is from a contract that works/is verified today (all jvm based)
m
and that one is the one added by the consumer?
u
yes
this is the important bit
m
oh..thats not helpful 😕 would be better if it had the injected value
u
I wonder why
dataType
is missing thinking2
m
indeed..was thinking of trying to fill it in myself and push just to see if something changes in the result
m
The injected value is dynamic, so the contract doesn't show it. But it would be cool if we showed what the provider did inject So I assume it's still not working?
👍 1
u
we’ve gone past the hurdle of query-params thanks to the latest patch, now we need to iron out actual issues with the contract, thanks for checking in
🙌 1
m
Great! No worries