chore: update readme
[demos/example-siren] / README.md
1 # Example Pact + Siren project
2 Example project using [Siren](https://github.com/kevinswiber/siren) for hypermedia entities and testing with Pact.
3
4 This project has two sub-projects, a provider springboot project which is using `spring-hateoas-siren` to provide Siren
5 responses and a Javascript consumer project `ketting` to parse and navigate the Siren responses. 
6
7 ## Provider Project
8
9 The provider project is a springboot application with Siren support provided by `spring-hateoas-siren`. It has two
10 resources, a root resource which provides links to the other resources and an order resource for dealing with orders
11 in the system.
12
13 ### Root Resource
14
15 This just provides the links to the other resources.
16
17 `GET /`:
18
19  ```json
20 {
21   "class": [
22     "representation"
23   ],
24   "links": [
25     {
26       "rel": [
27         "orders"
28       ],
29       "href": "http://localhost:8080/orders"
30     }
31   ]
32 }
33 ```
34
35 ### Order Resource
36
37 This provides all the CRUD operations on Orders: fetch all orders, fetch an order by ID, update a resource or delete one.
38
39 `GET /orders`
40
41 ```json
42 {
43   "class": [
44     "entity"
45   ],
46   "entities": [
47     {
48       "class": [
49         "entity"
50       ],
51       "rel": [
52         "item"
53       ],
54       "properties": {
55         "id": 1234
56       },
57       "links": [
58         {
59           "rel": [
60             "self"
61           ],
62           "href": "http://localhost:8080/orders/1234"
63         }
64       ],
65       "actions": [
66         {
67           "name": "update",
68           "method": "PUT",
69           "href": "http://localhost:8080/orders/1234"
70         },
71         {
72           "name": "delete",
73           "method": "DELETE",
74           "href": "http://localhost:8080/orders/1234"
75         }
76       ]
77     }
78   ],
79   "links": [
80     {
81       "rel": [
82         "self"
83       ],
84       "href": "http://localhost:8080/orders"
85     }
86   ]
87 }
88 ```
89
90 ## Consumer Project
91
92 This is a simple Javascript application that uses [Ketting](https://github.com/badgateway/ketting) which is a 
93 hypermedia client for javascript. It has a single function in `consumer/src/consumer.js` that navigates the links from the provider to find the
94 orders resource, get all the orders, find the first one and execute the delete action.
95
96 The consumer does the following:
97
98 1. Get the root resource
99 2. Find the orders relation
100 3. Execute a GET to the URL of the orders relation
101 4. Extract the first order entity from the embedded entities
102 5. Find the delete action for that order
103 6. Execute the action (which executes a DELETE to the URL of the action) 
104
105 ## Pact Tests
106
107 The problem with using normal Pact tests to test this scenario is that Siren responses contain URLs to the resources and
108 actions. The URLs when running the consumer test will be different than those when verifying the provider. This will 
109 result in a verification failure.
110
111 To get round this problem, we use the `url` matcher function from the consumer Pact DSL. This function takes a base URL,
112 and a list of path fragments. The path fragments can be either plain strings or regular expressions. It then constructs
113 the actual URL to use in the consumer test, and a regular expression matcher that can match the URLs in the provider
114 verification test.
115
116 To show this working, the consumer Pact test has the mock server running on port 9000, while the provider will be running on port 8080.