one otehr question, sorry the pact docos are all o...
# pact-js
j
one otehr question, sorry the pact docos are all over the place. The docos say for provider state (presumably when using a language other than ruby?):
Copy code
Non-Ruby applications

To allow the correct data to be set up before each interaction is replayed, you will need to create an HTTP endpoint (which may or may not actually be in the same application as your provider) that accepts a JSON document describing the state. The exact format of this document depends on whether you are using the JVM implementation, or one of the wrapped Ruby implementations (effectively everything that isn't JVM).

The endpoint should set up the given provider state for the given consumer synchronously, and return an error if the provider state is not recognised. Namespacing your provider states within each consumer will avoid clashes if more than one consumer defines the same provider state with different data.

See the pact-provider-verifier documentation for the exact details of implementing a provider-states-setup-url.
my devs are asking what difference in doing this than using a mock graphql server?
m
hmm where are you seeing this? Def doesn’t apply to the JS verifier
t
It can do, though. This is how I do it.
The primary difference is that with a mock graphql server you are marking your own exam - nothing is making sure that the mock server behaves the same as the real server
with pact's mocks, the provider verification step ensures that your real provider behaves the same as the mock that you used at consumer test time.
j
I got to the artical after reading the link that Matt provided, clicking on the Provider State link takes you o a page regarding provider state and then onto the ruby examplke from there the non ruby example
so is it a good practise to set up this http endpoint and then just return the hardcoded json stuff we need - that was in the original consumer request?
t
I think there might be a confusion here - the http endpoint that is mentioned there is for provider state change
during provider verification, pact needs a way to say "hey, please set up this state"
j
ah this is such a headache, but let me try to explain
t
The idea is that you run your real provider in a given named/known state
j
the devs they created a consumer test in one repo and have some data in that request for their graphql query. That data isnt in our monolith appilcation
they originally were unsure how to provceed as the tests kept failing so they created htis mock appolo server
to bypass that they cant add those records to the monolith
t
With pact-js, there are two ways to do this: 1) With the state change endpoint 2) With the state change functions In option 1, you need to handle starting and stopping your provider (with this additional endpoint running) outside your verification test. With option 2, you usually run the provider inside your verification test, and the state change functions reach into it and change the state
That data isnt in our monolith appilcation
What do you mean by "isn't in the application"? If the consumer test is expecting a structure that isn't implemented, then verification will (correctly) fail. If you mean the monolith doesn't come with that data pre-setup, then yes - this is what the state change endpoints or functions are for
the idea is that the state change sets up that state
j
let me give you an example
Copy code
export const MUTATION_RESPONSE = {
  status: 200,
  headers: {
    "Content-Type": "application/json; charset=utf-8"
  },
  body: {
    data: {
      signUp: {
        user: {
          username: like("Alice"),
          accounts: eachLike({
            id: like(1),
            uuid: like("0001")
          })
        }
      }
    }
  }
}
i believ they expect something like this
but from they say the info isnt in the database
if either of you have time I can DM you our issue without cloggin up this board
t
Yes, the purpose of the state change endpoint/function is to set that info in the database
j
ok so that will set the information in the database?
t
It's better to answer questions in public here as then others can benefit/contribute to the discussion
Most people commenting here are volunteers
j
can you provide a link to the docos on those 2 methods you mentioned
t
I think Matt linked to it above
I'm on mobile so it's a bit hard to search the docs
providerStatesSetupUrl is the property to set for the endpoint
j
ok ill pass on the info to the devs, maybe we are just confusiong ourselves over this. If it is the case that the provide state you just need to insert the data from our db
like the example:
Copy code
"Has some animals": () => {
      importData()
      return Promise.resolve(`Animals added to the db`)
    },
t
I can't seem to link into the readme, but what you're looking for is the section that starts “API with provider states”
Import the data TO the db
j
yes insert into the db right
👍 1
t
The state change endpoint does not return the data that is expected by the test
It sets up the data expected by the test
j
you would only need to do that with the queries right?
t
Maybe, it depends. For mutations you might need to set up the thing you're mutating
I don't really know a lot about graphql sorry
j
oh have some test data first you mean
yeah i dont know a huge amount about it
t
Yes. Think of provider state as the precondition
It's what allows pact tests to be independent
j
ok let me pass on the info to the devs. Im going to try this out on my own personal project so i'm more across this also
This explains the setup
j
so everything is pretty much set up
just need ot get rid of this mock apollo server on the provider side
t
Yep! Definitely no mock server on the provider side.
You could maybe have one if it's a dependency beyond your provider, but I wouldnt recommend doing it that way
j
So one dev is saying we have a test scenario where they are testing a delete mutation and that has a unique id. In the consumer test he says that he cannot create an object via a graphql mutation to delete (as a test setup prior to the consumer test) as the first time the consumer test is run and the contract is uploaded the contract cannot be updated next time round with the new id? Is that correct?
t
All tests are independent. Remember the pact state change endpoint is not a graphql query
I don't think I understand what he means in the second part, but my guess is no, that's not correct
j
Copy code
For deleteLink graphql mutation, the request param must contains the link id which we want to delete, this id can not be changed after consumer side generate the contract, in provider side, every time contract test running, it must provider a link with the same id.

So we can not create a new link with the same id using graphql mutation every time before running deleteLink test, it just can operate the database to prepare the data.
Copy code
yes, but the id in contract can not be changed in provider side, because pact thinks that if provider can modify the request of contract means that the contract is not trusted.
I meantioned that maybe setup a new link to delete but apparently the provider contract doesnt allow that?
t
In this case you would do something like a state of “a link exists with ID=Foo” or similar
If the IDs cannot be predicted beforehand, you can look at fromProviderState which allows the state setup hook to return an ID (or other arbitrary data) to the consumer test before it runs
There isn't a provider contract, the contract comes from the consumer
fromProviderState is in the next version of pact-js so you would need to use the beta. This may or may not work for you
Usually you use the pact state change to completely mock the repository layer inside your provider- this gives full control of the data within it
👍 1
m
Tim, thanks for your very helpful responses! Zooming out from this detail for a moment so we can get a grasp of the big picture here. Regardless of GraphQL, REST or otherwise, and whether or not it stores all of the data locally or needs to fetch from downstream systems … The challenge most people have with the provider test is that the _consumer (_the originator of the contract) can come up with scenarios that don’t match whatever the provider has in its default state when it comes to verify the provider. The example mentioned here, I think, is that an ID of an entity may not be known in advance. But I think that’s likely an assumption that stems from previous conceptions about how e2e tests would work, where you would “create” an entity, “get” the entity and then update/delete/whatever the entity. i.e. you need the client to perform these steps in sequence. Provider states (as noted) exist to solve this problem. It’s how a consumer can telegraph a condition that must be true for the provider test to run without specifying how. Consumers and provider should discuss these and some coordination is required, but that is how you can achieve a level of decoupling that you can’t do with end-to-end tests. Provider states free us from having to write tests that know about other tests (from the docs):
Each interaction in a pact should be verified in isolation, with no context maintained from the previous interactions. Tests that depend on the outcome of previous tests are brittle and land you back in integration test hell, which is the nasty place you’re trying to escape by using pacts.
💯 1
An assumption Pact makes, is that you have full control over your provider. Usually, you need unit-test level control over the provider, because you’re going to need to be able to mock/stub etc. various systems (database, downstream APIs etc.)
We talked about this in our very first AMA: https://docs.pact.io/help/amas#apac-1
🙌 1
“What are the best practices for mocking provider dependencies?”
j
hey thanks for the response, ill take a read of what you say and try to make sense of it. Sorry i didnt respond yesterday had to put the kids to bed
👍 1
m
No worries - async is good! (I also have small children and the post bed time is the 5 minutes you get to relax before you realise you need to do all of the cleanup operation before another groundhog day 😉 )
t
I only just realised we’re in the same timezone 😅
j
are you in Australia Tim?
t
yes
j
me too Bribane here
🙌 1