Amy Fang
06/07/2022, 1:30 PMdescribe('Pact test', () => {
it('should work', async () => {
const apiPath = '/userprofile/v1/paymentmethods';
const interaction: InteractionObject = {
state: 'Client has submitted a get all payment methods request',
uponReceiving: 'a valid payment methods get body',
withRequest: {
method: 'GET',
path: '/userprofile/v1/paymentmethods',
query: { userId: 11111 },
},
...
When I go to the Provider contract on Pactflow, it shows that the query param is there (in screenshot)
However, when I run the pact test, it gives me the 1st error Could not find key "userId" in empty Hash at $.query
I've tried multiple variations, such as removing the query property and placing it directly in the path and turning the userId into a string. When I change both types into a string, it gives me the 2nd errorIgor Sharfman
06/12/2022, 2:47 PMMatt (pactflow.io / pact-js / pact-go)
Slackbot
06/12/2022, 11:24 PMMatt (pactflow.io / pact-js / pact-go)
Matt (pactflow.io / pact-js / pact-go)
Slackbot
06/12/2022, 11:24 PMChit Chinwah
06/13/2022, 9:28 AMenum value {
optionA
optionB
optionC
}
The response returns the value which was sent in the request like this(assuming ‘optionA’ was sent in the request):
data: {
value: {
selectedValue: 'optionA'
}
}
My question is, what is the best way in pact-js
to verify that only one of the possible 3 values is accepted? is there some sort of way of checking that only one of these values is accepted in the response? Thanks in advance for your help! 🙏🏾🙌🏾.Dave Clissold
06/14/2022, 8:16 AMJohn Williams
06/20/2022, 1:25 AMJohn Williams
06/20/2022, 7:08 AMNon-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?Quinn
06/20/2022, 7:51 PM.willRespondWith({
status: 400,
headers: {
"Content-Type": "application/problem+json",
},
body: {
title: "Bad Request",
detail: regex(
/.*invalid character.*/,
'File name *:|.<>+"...jpg contains invalid character(s)'
),
},
})
However, when I look on the pact broker server, it looks like this:
[redacted] will respond with:
{
"status": 400,
"headers": {
"Content-Type": "application/problem+json"
},
"body": {
"detail": "File name *:|.<>+\"...jpg contains invalid character(s)",
"title": "Bad Request"
}
}
is there a reason these don't match? Are they supposed to not match? This is throwing an error in my pipeline preventing me from pushing any changes to my production environment.João Luiz Vieira
06/21/2022, 10:56 PM"@pact-foundation/pact": "^9.17.3"
This is my contract. It is already in the pact broker.
{
"method": "POST",
"path": "/files",
"headers": {
"Content-Type": "application/json"
},
"body": {
"clientId": "2454ad95-0352-4494-9a40-6afb333959e4",
"fileContent": "xxxxofAAABAE=",
}
}
In the provider side, I just created a test and added routes. Until here, everything is ok.
The weird part is that when the verification happens with new Verifier(options).verifyProvider()
, it calls the business logic code without the body. The other properties (baseUrl, method), they are passed to the the code, but not the body.
<http://router.post|router.post>('/', (req, res, next) => {
console.log("req.baseUrl", req.baseUrl)
console.log("req.path", req.path)
console.log("req.method", req.method)
console.log("req.body", req.body)
})
The code above, generate this logs:
req.baseUrl /files
req.path /
req.method POST
req.body undefined
Not sure why the body is now being sent to the endpoint being tested. I have done other contract tests, but all without request body and I never notice this before.
Anyone has any ideas of what I could be doing wrong?Abdurahman Hijazi
06/22/2022, 4:49 PMUser.js
Abdurahman Hijazi
06/22/2022, 4:53 PMexport class User {
constructor({id, name, age}) {
this.id = id;
this.name = name;
this.age = age;
}
}
API.js
const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args));
export class API {
constructor(url) {
if (url === undefined || url === "") {
url = '<http://localhost:3000>';
}
if (url.endsWith("/")) {
url = url.substr(0, url.length - 1)
}
this.url = url
}
fetchUser = async url => {
fetch(url)
.then(res => res.json())
.then(res => console.log(res))
.catch(e => console.log("Error from response: ", e))
}
generateAuthToken() {
return "Bearer " + new Date().toISOString()
}
}
export default new API('<http://localhost:3000>');
test.pact.spec.js
import { Pact } from '@pact-foundation/pact';
import { API } from './API';
import { Matchers } from '@pact-foundation/pact';
import { User } from './User';
const { eachLike, like, regex } = Matchers;
const mockProvider = new Pact({
consumer: 'User-frontend',
provider: 'Nodejs-backend',
port: 1234
});
describe('API Pact test', () => {
beforeAll(() => mockProvider.setup());
afterEach(() => mockProvider.verify());
afterAll(() => mockProvider.finalize());
describe('retrieving a product', () => {
test('ID 10 exists', async () => {
// Arrange
const expectedProduct = { id: '12', name: 'Sally', age: '32'}
await mockProvider.addInteraction({
state: 'a user with ID 12 exists',
uponReceiving: 'a request to get a user',
withRequest: {
method: 'GET',
path: '/user/12',
headers: {
Authorization: like('Bearer 2019-01-14T11:34:18.045Z'),
},
},
willRespondWith: {
status: 200,
headers: {
'Content-Type': regex({generate: 'application/json; charset=utf-8', matcher: 'application/json;?.*'}),
},
body: like(expectedProduct),
},
});
// Act
const api = new API(mockProvider.mockService.baseUrl);
const product = await api.fetchUser('10');
// Assert - did we get the expected response
expect(product).toStrictEqual(new Product(expectedProduct));
});
});
});
How would I run the test locally in my cmd? Any help is appreciatedÉdouard Lopez
06/23/2022, 8:40 AMprovider.verify()
verify exactly? Does it uses information from willRespondWith
? Or simply that the request sent match the withRequest
info?Yousaf Nabi (pactflow.io)
Abdurahman Hijazi
06/24/2022, 10:32 AM1) Pact verification:
TypeError [ERR_INVALID_URL]: Invalid URL
at new NodeError (node:internal/errors:372:5)
at URL.onParseError (node:internal/url:553:9)
at new URL (node:internal/url:629:5)
at Verifier.isLocalVerification (node_modules\@pact-foundation\pact\src\dsl\verifier.js:302:17)
at Verifier.setConfig (node_modules\@pact-foundation\pact\src\dsl\verifier.js:295:23)
at Verifier.verifyProvider (node_modules\@pact-foundation\pact\src\dsl\verifier.js:86:18)
at Context.<anonymous> (test\provider.spec.js:27:25)
at processImmediate (node:internal/timers:466:21
Line 27 is the return line below
return new Verifier(opts).verifyProvider().then(() => {
console.log("Pacts verified and published");
});
Laura Cabantous
06/27/2022, 4:19 PMeachLike(propertyDocumentWithoutTransactions, { min: 2 })
However, I'm having the following warning when running the test:
Pact Binary Error: WARN: Only the first item will be used to match the items in the array at $['body']['addresses']
Can anyone help explain what this means?Harris Lee
06/27/2022, 10:48 PMJohn Williams
06/28/2022, 4:31 AMDany Marques
06/28/2022, 10:07 AMDamian
06/29/2022, 11:51 PMNo matching interaction found
Any idea why the pact test for the GET request w/ a query param would be failing when it's seemingly identical to the other working pact test?Greg Tyler
06/30/2022, 2:22 PMAbhishek
06/30/2022, 6:24 PMHarris Lee
06/30/2022, 11:36 PMapi gateway / service mesh
When services to services interact through api gateway or service mesh, what is the boundary of the consumer test?
I think from consumer <-> api gateway/mesh MOCK
and generate pact then pact <-> api gateway/mesh + Provider
is that right approach? but for me, api gateway / mesh is just one layer to invoke function or other services. how to write contract for that?
for example, most of AWS lambda integrate with API gateway. I can see example of lambda to invoke the function to write contract test, but I am not really sure how to deal with api gateway / service mesh layer boundary. hope it makes a sense lolHarris Lee
07/04/2022, 5:48 AM9.17.2
to 10.0.0-beta.60
it causes GLIBC error
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.25' not found (required by /app/node_modules/@pact-foundation/pact-core/build/Release/libpact_ffi.so)
is there any fix / recommendation to work around that?Zhao Yi
07/04/2022, 5:53 AMjest
for contract testing library. Does anyone know how I can run a single contract test in provider side? It seems every time it runs all contract tests downloaded from the broker. Is there a way to run just one?Artur Neumann
07/04/2022, 10:56 AMPactffiWithBody(arg 2) expected a string
John Williams
07/04/2022, 11:37 PM