agreed-core
agreed is Consumer Driven Contract tool with JSON mock server.
agreed has 3 features.
- Create contract file as json(json5/yaml/etc) file
- mock server for frontend development.
- test client for backend development
agreed-core
is a library to create test client and mock server. agreed-core
provide the following features.
- json5/yaml require hook, you can write require('foo.json5') / require('bar.yaml') using agreed-core/register.
- server middleware, agreed-core provides express/pure node http middleware.
- test client, agreed-core provides response check.
Install
$ npm install agreed-core --dev
Usage
Usage as Frontend Mock Server
- Create agreed file (this file is used as a contract between frontend and backend)
module.exports = [
{
request: {
path: '/user/:id',
method: 'GET',
query: {
q: '{:someQueryStrings}',
index: '{:index}',
},
values: {
id: 'yosuke',
someQueryStrings: 'bye',
index: 2,
},
},
response: {
headers: {
'x-csrf-token': 'csrf-token',
},
body: {
message: '{:greeting} {:id} {:someQueryStrings}',
image: '{:images[:index]}',
themes: [
{
name: '{:themes.0.name}'
},
'{:themes.1-last}'
],
},
values: {
greeting: 'hello',
images: [
'http://example.com/foo.jpg',
'http://example.com/bar.jpg',
'http://example.com/baz.jpg',
],
themes: [
{
name: 'green',
},
{
name: 'blue',
},
{
name: 'red',
},
]
}
},
},
]
We support express, pure node.js and any other frameworks can use agreed.
'use strinct';
const express = require('express');
const bodyParser = require('body-parser');
const agreed = require('agreed-core');
const app = express();
app.use(bodyParser.json());
app.use(agreed.middleware({
path: './agreed/file/agreed.js',
}));
app.use((err, req, res, next) => {
res.statusCode = 500;
res.send(`Error is occurred : ${err}`);
});
app.listen(3000);
$ node server.js
$ curl http://localhost:3000/user/alice?q=foo
{
"message": "hello alice foo",
"images": [
"http://example.com/foo.jpg",
"http://example.com/bar.jpg"
],
"themes": {
"name": "green",
},
}
Usage as Backend test client
agreed can be test client.
module.exports = [
{
request: {
path: '/user/:id',
method: 'GET',
query: {
q: '{:someQueryStrings}',
},
values: {
id: 'yosuke',
someQueryStrings: 'foo'
},
},
response: {
headers: {
'x-csrf-token': 'csrf-token',
},
body: {
message: '{:greeting} {:id} {:someQueryStrings}',
images: '{:images}',
themes: '{:themes}',
},
values: {
greeting: 'hello',
images: [
'http://example.com/foo.jpg',
'http://example.com/bar.jpg',
],
themes: {
name: 'green',
},
}
},
},
]
'use strinct';
const AgreedClient = require('agreed-core').client;
const client = new AgreedClient({
path: './agreed/file/agreed.js',
host: 'example.com',
port: 12345,
});
const agrees = client.getAgreement();
const responses = client.executeAgreement(agrees);
client.checkResponse(responses, agrees).then((diffs) => {
diffs.forEach((diff) => {
if (Object.keys(diff).length > 0) {
console.error('your request does not matched: ', diff);
}
});
});
APIs
Agreement
how to define API specs
Agreement file can be written in JSON5/YAML/JavaScript format. You can choose your favorite format.
[
{
"request": {
"path": '/hoge/fuga',
"method": 'GET',
"query": {
"q": 'foo',
},
},
response: {
headers: {
'x-csrf-token': 'csrf-token',
},
body: {
message: 'hello world',
},
},
},
{
"request": {
"path": '/users/:id',
"method": 'GET',
},
response: {
body: {
message: 'hello {:id}',
},
},
},
'./hoge/foo.json',
'./foo/bar.yaml',
{
request: './qux/request.json',
response: './qux/response.json',
},
{
request: {
path: '/path/:id',
method: 'POST',
query: {
meta: "{:meta}",
},
body: {
message: "{:message}"
},
values: {
id: 'yosuke',
meta: true,
message: 'foobarbaz'
},
},
response: {
headers: {
'x-csrf-token': 'csrf-token',
},
body: {
message: 'hello {:id}, {:meta}, {:message}',
},
},
},
{
request: {
path: '/images/:id',
method: 'GET',
query: {
q: '{:someQueryStrings}',
},
values: {
id: 'yosuke',
someQueryStrings: 'foo'
},
},
response: {
headers: {
'x-csrf-token': 'csrf-token',
},
body: {
message: '{:greeting} {:id} {:someQueryStrings}',
images: '{:images}',
themes: '{:themes}',
},
values: {
greeting: 'hello',
images: [
'http://example.com/foo.jpg',
'http://example.com/bar.jpg',
],
themes: {
name: 'green',
},
}
},
},
{
request: {
path: '/useschema/:index',
method: 'GET',
values: {
index: 1
}
},
response: {
body: {
result : '{:list[:index]}'
},
schema: {
type: 'object',
properties: {
result: {
type: 'string'
}
},
},
values: {
list: [
'hello',
'hi',
'dunke',
]
}
},
},
]