Testing the REST API - signavio/workflow-connector GitHub Wiki

You can test the deployment with a local sqlite database to make sure that the RESTful API is behaving properly. Alternatively, you can also use the workflow connector herokuapp at https://workflow-connector-test.herokuapp.com (using the HTTP Basic Authentication credentials, username: wfauser, password: Foobar) if you don't want to test on your own database just yet. The following sections demonstrate how to perform these tests on a local sqlite database.

Since everyone loves coffee

Let's assume we want to create a workflow that can instruct an intern on how to make coffee for the rest of our team. On a high level the intern would need to know what style of coffee we want, what the necessary ingredients are and how to properly use the machines to make the best batch of coffee possible. If we model these requirements in a database we could end up with a similar result as to whats depicted in the following diagramm.

The Example Data Model

Translating this diagramm to plain english would result in the following:

  • A recipe contains instructions for the intern to follow. Making a recipe requires only one piece of equipment. A recipe of course contains many ingredients.
  • A piece of equipment can be used in many different recipes.
  • The database keeps track of the ingredients in stock in the inventory table. When the intern is shown the ingredients necessary for a recipe he or she will also be shown if there is enough of these ingredients in stock.

This database model has been translated one to one in the config/descriptor.json file located in this repository.

Okay now on to the prerequisites

  1. Download and install sqlite
apt-get install sqlite

Populate the database

For testing purposes, we can execute the sqlite migration script provided in the build/migrate-to-sqlite.sh to create our schema and populate it with some example data. The equipment table should end up looking like this:

Equipment

id name acquisition_cost purchase_date
1 Bialetti Moka Express 6 cup 25.95000 2017-12-11 12:00:00
2 Sanremo Café Racer 8477.85000 2017-12-12 12:00:00
3 Buntfink SteelKettle 39.95000 2017-12-12 12:00:00
4 Copper Coffee Pot Cezve 49.95000 2017-12-12 12:00:00

Run the workflow connector

Before running the workflow-connector command, either edit the config.yaml file to include the database connection parameters and other settings, or export these settings as environment variables.

# Export environment variables
#
export PORT=:8080 DATABASE_URL=test.db DATABASE_DRIVER=sqlite3
#
# Run the connector
~/bin/workflow-connector
Listening on :8080

Exercise the REST API

Now we can test the functionality of the connector's REST API either in a new terminal, or using a javascript action in the Signavio Workflow Accelerator. The Workflow Connector's REST API aims to behave as any well crafted RESTful API should. A basic overview of REST can be found here. All HTTP requests are sent using HTTP basic auth with the default username (wfauser) password (Foobar) combination here.

Go ahead and fetch the equipment with id 1 by sending a HTTP GET request to the connector using the curl command (you can apt-get install curl if curl is not yet installed):

curl --verbose --header "Authorization: Basic $(echo -n "wfauser:Foobar" | base64)" --request GET http://localhost:8080/equipment/1
# Response:
## Headers
> GET /equipment/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.55.1
> Accept: */*
> Authorization: Basic d2ZhdXNlcjpGb29iYXI=
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Fri, 23 Mar 2018 21:33:47 GMT
< Content-Length: 595
<
## Data
{
  "acquisitionCost": {
    "amount": 25.95,
    "currency": "EUR"
  },
  "id": "1",
  "name": "Bialetti Moka Express 6 cup",
  "purchaseDate": "2017-12-11T12:00:00.000Z",
  "recipes": []
}

Alternatively the same can be tested in a javascript action within workflow using the following javascript code.

Note: Make sure to replace the host variable with your configuration

const id = '1'
const host = 'http://localhost:8080'
const url = `${host}/equipment/${id}`
const auth = {
  user: 'wfauser',
  pass: 'Foobar'
}
const requestOptions = {auth: auth, url: url}
request.get(requestOptions, (error, response, body) => {
  if (error) {
    console.log(error)
    return
  }
  if (response.statusCode > 399) {
    console.log(new Error('Received an error status code'))
    return
  }
  console.log(body)
})
// console.log output ->
{
  "acquisitionCost": {
    "amount": 25.95,
    "currency": "EUR"
  },
  "id": "1",
  "name": "Bialetti Moka Express 6 cup",
  "purchaseDate": "2017-12-11T12:00:00.000Z",
  "recipes": []
}

Insert a new equipment in the database

You can create a new product by sending a HTTP POST to the appropriate route (here /equipment). You will either receive a response containing the newly inserted equipment or an HTTP success status code 204 No Content.

curl --verbose --header "Authorization: Basic $(echo -n "wfauser:Foobar" | base64)" --request POST --data 'name=Malt+mill+550&acquisitionCost=1270&purchaseDate=2016-09-04T11:00:00.000Z' http://localhost:8080/equipment

# Response:
## Headers
> POST /equipment HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.56.1
> Accept: */*
> Authorization: Basic d2ZhdXNlcjpGb29iYXI=
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 45
>
* upload completely sent off: 45 out of 45 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Fri, 23 Mar 2018 21:33:47 GMT
< Content-Length: 2
<
## Data
{
  "acquistionCost": {
    "amount": 1270,
    "currency": "EUR"
  },
  "id": "5",
  "name": "Malt mill 550",
  "purchaseDate": "2016-09-04T11:00:00.000Z",
  "recipes": []
}

And now using javascript

const host = 'http://localhost:8080'
const url = `${host}/equipment`
const auth = {
  user: 'wfauser',
  pass: 'Foobar'
}
const form = {
  name: 'Malt mill 550',
  acquisitionCost: 1270,
  purchaseDate: '2016-09-04T11:00:00.000Z'
}
const requestOptions = {auth: auth, url: url, form: form}
request.post(requestOptions, (error, response, body) => {
  if (error) {
    console.log(error)
    return
  }
  if (response.statusCode > 399) {
    console.log(new Error('Received an error status code'))
    return
  }
  console.log(body)
})
// console.log output ->
{
  "acquisitionCost": {
    "amount": 1270,
    "currency": "EUR"
  },
  "id": "5",
  "name": "Malt mill 550",
  "purchaseDate": "2016-09-04T11:00:00.000Z",
  "recipes": []
}

Updating an existing product

By sending a HTTP PATCH to /equipment you can change existing entries. Let's go ahead an adjust the name of the malt mill we just added recently.

curl --verbose --header "Authorization: Basic $(echo -n "wfauser:Foobar" | base64)" --request PATCH --data 'name=Malt+mill+400' http://localhost:8080/equipment/5

# Response:
## Headers
> PATCH /equipment/5 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.56.1
> Accept: */*
> Authorization: Basic d2ZhdXNlcjpGb29iYXI=
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 45
>
* upload completely sent off: 45 out of 45 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Fri, 23 Mar 2018 21:33:47 GMT
< Content-Length: 2
<
## Data
{
  "cost": {
    "amount": 1270,
    "currency": "EUR"
  },
  "id": "5",
  "name": "Malt mill 400",
  "purchaseDate": "2016-09-04T11:00:00.000Z"
}

And again using javascript

const id = '5'
const host = 'http://localhost:8080'
const url = `${host}/equipment/${id}`
const auth = {
  user: 'wfauser',
  pass: 'Foobar'
}
const form = {
  name: 'Malt mill 400'
}
const requestOptions = {auth: auth, url: url, form: form}
request.patch(requestOptions, (error, response, body) => {
  if (error) {
    console.log(error)
    return
  }
  if (response.statusCode > 399) {
    console.log(new Error('Received an error status code'))
    return
  }
  console.log(body)
})
// console.log output ->
{
  "acquisitionCost": {
    "amount": 1270,
    "currency": "EUR"
  },
  "id": "5",
  "name": "Malt mill 400",
  "purchaseDate": "2016-09-04T11:00:00.000Z",
  "recipes": []
}

Deleting an existing product

We can delete existing entries in a table by sending a HTTP DELETE to the /equipment/5 entry. We will then receive a 200 OK HTTP status code back.

curl --verbose --header "Authorization: Basic $(echo -n "wfauser:Foobar" | base64)" --request DELETE http://localhost:8080/equipment/5

# Response:
## Headers
> DELETE /equipment/5 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.56.1
> Accept: */*
> Authorization: Basic d2ZhdXNlcjpGb29iYXI=
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 45
>
* upload completely sent off: 45 out of 45 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Fri, 23 Mar 2018 21:33:47 GMT
< Content-Length: 2
<
## Data
{
  "status": {
    "code": 200,
    "description": "Resource with uniqueID '5' successfully deleted from equipment table"
  }
}

And lastly using javascript

const id = '5'
const host = 'http://localhost:8080'
const url = `${host}/equipment/${id}`
const auth = {
  user: 'wfauser',
  pass: 'Foobar'
}
const requestOptions = {auth: auth, url: url}
request.delete(requestOptions, (error, response, body) => {
  if (error) {
    console.log(error)
    return
  }
  if (response.statusCode > 399) {
    console.log(new Error('Received an error status code'))
    return
  }
  console.log(body)
})
// console.log output ->
{
  "status": {
    "code": 200,
    "description": "Resource with uniqueID '4' successfully deleted from equipment table"
  }
}