Easily create and update your Joule

Every Joule takes some input and returns an output. This tutorial will teach you how you can make changes and see the result without having to commit, push or deploy your code.

Learn how to debug your deployed Joule.

Your events.json

Every Joule should come with a file named events.json-sample located in the src folder. You'll rename this file to events.json and use it to specify all of the inputs to your Joule. You can specify environment variables, HTTP methods and parameters your Joule expects.

Here's what a basic events.json file looks like.

{
  "env": {
    "MY_SECRET": "_some_secret_"
  },
  "events": {
    "GET": {
      "/": [
        {"input1":"value1"},
        {"input1":"another input"}
      ],
      "/pathParam1/pathParam2": [
        {}
      ],
      "/?name1=value1": [
        {}
      ]
    }
  }
}

Environment variables

The env section specifies values for the environment variables you have declared in your .joule.yml file. Since your environment variables often contain secrets you'll want to make sure that your events.json never gets checked in. There should be a line in your .gitignore file that came with your Joule which ignores events.json but you should double check. In the same way that it's helpful for you if someone provided a comprehensive events.json-sample file for your Joule it would be helpful to others if you keep that updated to include any changes you make as well.

Events data

The first thing you'll want specify under events are your HTTP methods. You can have an array of input objects to simulate each method you want to test and pass in any permutation of parameters. The inputs can contain path parameters, query string parameters and anything in a JSON postbody. Let's look at an example.

To simulate GET requests to the root of your Joule you'll want something like this under events.

    "GET": [
      "/": [
        {"body": "sample body"},
        {"body": ""}
        {}
      ]
    ]

Every object in the GET array represents a call to a specific Joule endpoint. Within the endpoint array you can include any number of objects; each represents a call you'll test. These calls simulate the following calls.

  1. curl -X GET "https://api.joule.run/user/joule?body=sample%20body"
  2. curl -X GET "https://api.joule.run/user/joule?body="
  3. curl -X GET "https://api.joule.run/user/joule"

The POST request can be tested similarly.

    "POST": [
      "/": [
        {"user_id": "123abc"},
        {"user_id": ""}
        {}
      ]
    ]

This simulates and tests the following calls.

  1. curl -X POST -F 'user_id=123abc' "https://api.joule.run/user/joule"
  2. curl -X POST -F 'user_id=' "https://api.joule.run/user/joule"
  3. curl -X POST "https://api.joule.run/user/joule"

POST requests work with application/x-www-form-urlencoded and application/json. Here's what the curl call would look like for application/json.

  1. curl -X POST -H 'Content-Type: application/json' -d '{"user_id":"123abc"}' "https://api.joule.run/user/joule"
  2. curl -X POST -H 'Content-Type: application/json' -d '{"user_id":""}' "https://api.joule.run/user/joule"
  3. curl -X POST -H 'Content-Type: application/json' -d '{}' "https://api.joule.run/user/joule"

Run your Joule locally

Running your Joule locally and seeing its output is simple.

The first thing you'll need to do is to install your Joule's dependencies from your src folder.

npm install

Once your dependencies have been installed you can begin running your Joule.

npm test

You will see a response for each method and request combo from your events.json file.

GET /username/joule {"Body":"message"}
{ headers: { Status: '200 OK', 'Content-Type': 'application/json' },
  data: { httpMethod: 'GET', path: [], query: { Body: 'message' } } }

GET /username/joule/myParam {}
{ headers: { Status: '200 OK', 'Content-Type': 'application/json' },
  data: { httpMethod: 'GET', path: [], query: {} } }

GET /username/joule?name1=value1&name2=value2 {}
{ headers: { Status: '200 OK', 'Content-Type': 'application/json' },
  data:
   { httpMethod: 'GET',
     path: [],
     query: { name1: 'value1', name2: 'value2' } } }

POST /username/joule {"Body":"message"}
{ headers: { Status: '200 OK', 'Content-Type': 'application/json' },
  data:
   { httpMethod: 'POST',
     post: { Body: 'message' },
     path: [],
     query: {} } }

Each response includes a headers and data attribute. The headers indicate the HTTP headers which would be returned in the call. The data contains the body of the response which would be sent to the caller.