Just a quick question about this Beta js version 3...
# pact-js
j
Just a quick question about this Beta js version 3. The provider is written in PHP and from what I can see the issue is that because the org uses Doctrine so that many ids are autogenerated and cannot be inserted into Db with unique ids as the DB does this automatically (we cant know the id before hand). To overcome this Timothy suggested that we use the Beta version with the fromProvideState hook in the consumer test to overcome this issue. To better understand this, we still need to set up a provide state end point in the Provider ? So that the data can be inserted in the database and this will be fetched back to the consumer and injected into the consumer via this fromProviderState? Presumably the provider stuff has to be written in php?
t
it depends what you mean by "provider stuff". For php, the easiest thing to do will be to add a state change endpoint (probably written in PHP) that knows how to manipulate the provider state
Alternatively, if you're inserting directly into the DB, you could write your provider verification in anything (eg using pact-js and the state change hooks). But I would not do this because: 1) You're introducing a new language on the provider just for testing 2) It's not best practice for the state change endpoints to know DB insert calls - generally better for them to manipulate the DB though domain objects. This is because it's better for the state to be like
userTenExists = () => users.add(10, {/* whatever user properties */})
, because then: • Your tests use the same language as the domain • Your tests happen to cover some of the repository logic by virtue of needing it for the provider state setup • Your tests aren't assuming particular DB state (if you insert arbitrary stuff into the DB, how do you know the arbitrary stuff is the right arbitrary stuff?)
j
by stuff I mean the whole application is written in php
t
In that case:
we still need to set up a provide state end point in the Provider ?
Yes, or the other approach above if it happens to be easier for you (I would do the state change endpoint though)
j
so bascially write a state change endpoint in php and the consumer testwriten in say js cant still get that info before it runs correct?
t
The consumer test never needs that info
The info is only used during provider verification
so you say something like: This request is
GET /users/$userIdFromProvider
, and when it runs on the consumer test you can say "for example, 10"
j
1. write the consumer test with that getProviderState hook (javascript) 2. write the producer test in php 3. write the state change endpoint in PHP that twill feed back the consumer
t
then the provider verification goes like this: 1) Hey provider, please init the state "a user exists" 2) "Ok, your user ID is 123" 3) Great, here's a request
GET /users/123
j
so basically because we use Doctrine
t
write the state change endpoint in PHP that twill feed back the consumer
No. The provider state change endpoint never sends anything back to the consumer
it sends back data that is used to inform the mock of the consumer that pact runs for you
j
so I created all this using python and got it all working
but the PHP app uses php doctrine which autogenerates the id in the db
so the contract doesnt know the id
and neither does the provider before hand
t
step 3 is: 3. write the state change endpoint in PHP that will tell pact what value to use for the
fromProviderState
bit when mocking the consumer request
so the contract doesnt know the id
Correct
and neither does the provider before hand
Correct But, the provider does know after the state change endpoint has been called. And it can return that info in the response
j
so basically if i have a state change function:
Copy code
def pact_add_expected_user:
  # add the user to the db
  # return the user id to pact
so when the provider contract test is run it will use the returned value from the pact_add_expected_user and both the consumer /provider contract test should be happy
💯 1
t
the consumer test should already be happy, otherwise you won't have a contract to verify
j
yes thats right
t
but otherwise, yes
j
the consumer test seems to be very easy to m,ake
t
it is 🙂
j
....once you have navigated the docs that is LOL
t
so, I can't remember if the response format for the V3 state change endpoint is documented. I remember I had to read the code when we were working on the beta
It would be very useful to split out the docs. If I were still working on pact, that's something I'd like to make a priority
j
yeah i think the docs could be streamlined a lot better
do you meant he response that gets sent back fromt he setup_state_endpoint?
t
yep
j
when i wrote the provider state in python I did somethign. like this:
so it will have a different format to that right
t
Aha, it's at least documented in the intellisense:
Copy code
/**
 * Respond to the state setup event, optionally returning a map of provider
 * values to dynamically inject into the incoming request to test
 */
Copy code
export interface ProviderState {
  action: StateAction;
  params: JsonMap;
  state: string;
}

/**
 * Specifies whether the state handler being setup or shutdown
 */
export type StateAction = 'setup' | 'teardown';
The request is a
ProviderState
object
and pact will tell you if it is a setup or a teardown
you might have problems if you don't check the action to determine whether to setup or teardown
I think V3 allows multiple states
j
thanks for the info Timothy
t
Welcome!
m
🌮 for @Timothy Jones!
thanks for your help!
j
haha taco time
nom 1
I think my team will not use this approach though but instead write their provider tests in JS but use graphql mutation to seed the data into the. db instead. Because no one is comfortable will PHP
my worry with that approach is that your setup phase is using endpoints that maybe are being tested in other contract tests. Do you think my concern is unfounded?
t
Personally I'm not terribly worried about a contract break that happens to break other tests- you’ll still detect the problem. (Pact will tell you if its state change fails)
j
ok thats good to know I though that is kind of an anti pattern to use the endpoint your testing to set up state