Skip to content

Just-API Features

Request Specification

A typical request specification includes request method, path, headers, query params, path params, and payload (if applicable).

Request Methods

Just-API supports following HTTP request methods. You can have a request specification with any of these HTTP methods.

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE
  • HEAD
  • OPTIONS

Specifying Headers, Cookies, Query params, Path params

Specify Request headers to headers key as a list of name, value pairs.
Specify Request cookies to cookies key as a list of name, value pairs.
Specify Request Query params to query_params key as a list of name, value pairs.
Specify Request Path params to path_params key as a list of name, value pairs.

A sample test specification with method, headers, cookies, query params and path params:

  - name: A sample test
    request:
       path: /user/{userId}/posts/{postId}
       method: get
       headers:
         - name: Accept
           value: application/json
       cookies:
         - name: uid
           value: 399do284kds32odh28 
       path_params:
          - name: userId
            value: 12876
          - name: postId
            value: 2
       query_params:
          - name: limit
            value: 10
    response:
       status_code: 200

Request Body Specification

When you need to send request body for POST, PUT and PATCH requests, you can specify the body to payload key.

You will need to specify content-type header and body type as shown below Here's how to send JSON body with a POST request

  - name: create a new user
    request: 
      path: /users
      method: post
      headers:
        - name: content-type
          value: application/json
      payload:
          body:
            type: json
            content:
              firstName: john
              lastName: doe
    response:
      status_code: 201

You can also send binary data as body from a file as shown below.

  - name: post binary data (file) as body
    request:
      path: /uploadImage
      method: post
      headers:
        - name: content-type
          value: image/png
      payload:
          body:
            type: binary 
            content: static/assets/image.png # Image path
    response:
      status_code: 200

Note that the image path should be relative to Node process's current working directory or relative to suite's path if you set locate_files_relative to true in meta section of the suite.

Checkout more examples on how to specify request body here

x-www-form-urlencoded, Multipart requests, file uploads

Just-API supports x-www-form-urlencoded and multipart/form-data requests, using which you can upload files and perform tests on complex requests.

specify x-www-form-urlencoded request

To create a x-www-form-urlencoded request test, you will need to specify the content-type header and form body like below:

Note that payload should have a key form and it should contain form data in key value pairs.

  - name: Authenticate a user
    request:
      path: /authenticate
      method: post
      headers:
        - name: content-type
          value: application/x-www-form-urlencoded
      payload:
          form:
            userName: john.doe
            password: john.doe.password
    response:
      status_code: 200

More examples on x-www-form-urlencoded tests can be found here

specify multipart/form-data request

Here's how you can specify a multipart request.

Note that payload should have a key form_data and it should contain list of form data fields.

  - name: post multipart form data - single file and field
    request:
      path: /imageNText
      method: post
      headers:
        - name: content-type
          value: multipart/form-data
      payload:
          form_data:
            - name: image_name
              content: static/assets/logo.png # file path
              type: file
            - name: field1
              content: value1
              type: text
    response:
      status_code: 200

More examples on multipart/form-data tests can be found here

Response Validation

Just-API allows you to validate response without writing any code, you can validate following in a response by specifying what to validate.

  • Status code
  • Headers
  • Cookies
  • JSON schema
  • JSON body

You can also have a custom validator function that implements your custom validation logic.

Status code validation

Provide status_code attribute in response and Just-API matches Response's Status code against the specification. Test will fail when Actual response's status code does not match with specified value.

A sample:

  - name: get users
    request:
      path: /users
      method: get
    response:
      status_code: 400

Headers validation

When you specify headers in response, Just-API will validate response headers against your specification.

A sample on how to write headers validation.

  - name: get users
    request:
      path: /users
      method: get
    response:
      headers:
        - name: content-type
          value: application/json

You can even match header against a regex instead of exact value, like below:

Following response specification would check if response header content-type matches with regex pattern 'json'.

  - name: get users
    request:
      path: /users
      method: get
    response:
      headers:
        - name: content-type
          value: !!js/regexp /json/

More examples on response header validation can be found here

Cookies validation

When you specify cookies in response, Just-API will validate response cookies against your specification.

A sample on how to write cookies validation.

  - name: get users
    request:
      path: /users
      method: get
    response:
      cookies:
        - name: uid
          value: xxxxxx

You can even match cookie value against a regex instead of exact value, like below:

Following response specification would check if response cookie uid matches with regex pattern /[0-9]+/.

  - name: get users
    request:
      path: /users
      method: get
    response:
      cookies:
        - name: uid
          value: !!js/regexp /[0-9]+/

More examples on response cookie validation can be found here

Response JSON schema validation

Sometimes you may want to validate the schema of JSON received in response's body, which will allow you to ensure that server is sending data exactly what you are expecting.

with Just-API, you can validate the response JSON schema by specifying the json_schema attribute in response.

Following sample shows how to read expected schema from a file and validate response JSON body against it. Here json_schema has two fields, type key can be either file or inline. When type is file, you need to provide the relative path to schema file to $ref key.

  - name: get users
    request: 
      path: /users
      method: get
    response:
      json_schema:
          type: file
          $ref: static/schema/expected_schema_for_users.json #path to the expected schema file

You can also specify expected JSON schema in YAML by setting type as inline and assigning a string to $ref like below:

  - name: get users
    request: 
      path: /users
      method: get
    response:
      json_schema:
          type: inline
          $ref: >
                {
                  "$id": "http://example.com/example.json",
                  "type": "object",
                  "$schema": "http://json-schema.org/draft-06/schema#",
                  "properties": {
                    "firstName": {
                      "$id": "/properties/firstName",
                      "type": "string"
                    }
                  }
                }

If you are not sure about JSON schema standard, Please refer to JSON schema

More examples on response JSON schema validation can be found here

Response JSON body validation

When you want to validate one or many fields of response JSON, you can do so by providing json_data as part of response specification.

json_data should have a list of pairs of path & value, where path tells Just-API how to locate the field, and value is the expected value for that field.

Following sample shows that.

  - name: get users
    request: 
      path: /users
      method: get
    response:
      json_data:
        - path: $.[0].firstName
          value: john

If you are not sure on how to generate JSON path, Please refer to JSON path

More examples on response JSON data validation can be found here

User defined custom response validator functions

When you need to validate a response using your custom logic, you can do so by providing a inline or module custom javascript function to custom_validator attribute.

Just-API will invoke the custom function by passing the response to function's context, so you can access the response using this.response.

When you need more details from response, this.response will also have following properties.

  • body
  • statusCode
  • statusMessage
  • headers
  • body
  • duration

Here's a sample on how to specify a custom inline Javascript function to validate the response

  - name: get users
    request:
      path: /users
      method: get
    response:
      status_code: 200
      custom_validator:
        run_type: inline
        inline:
          function: !!js/function >
            function() {
              var body = JSON.parse(this.response.body);

              if (body.users[0].firstName !== 'john')
                  throw new Error("first user's name is not john");
            }

You can also specify a custom function defined & exported in a module by providing run_type as module and module path like below.

  - name: get users
    request:
      path: /users
      method: get
    response:
      status_code: 200
      custom_validator:
        run_type: module
        module:
          module_path: modules/custom_module.js # module path
          function_name: validateUsersResponse

More examples on validating response using custom functions can be found here

Custom Javascript functions

Just-API allows users to specify custom Javascript functions for (hooks and custom validator).

These custom Javascript functions can be inline or defined in a module. They can be synchronous or asynchronous (defined with async keyword).

Cutom inline and module functions

custom inline function

An inline synchronous function is defined as below.

  custom_validator:
    run_type: inline
    inline:
      function: !!js/function >
        function() {
          // some custom code here...
        }

Note that run_type is inline and function is mapped to function key of inline attribute. Tagging with !!js/function is how you tell Just-API parser to consider it as a custom synchronous function.

custom module function

A module synchronous function is specified as below.

 custom_validator:
   run_type: module
   module:
     module_path: modules/custom_module.js
     function_name: customFunctionName

Note that run_type is module and function details are mapped to module attribute. module_path has the relative path to the JS file from Node's process's current working directory or relative to suite's path if you set locate_files_relative to true in meta section of the suite. The JS file is expected to be a standard Node.js module. function_name is the function exported in the module.

Async support for custom functions with promises

Just-API does not support callback mechanism, Wrap async opeartions with promises and return a promise.

Custom functions can be asynchronous defined with async keyword, Just-API waits until the promise returned by the async function is resolved or rejected.

An inline asynchronous function is defined as below.

  custom_validator:
    run_type: inline
    inline:
      function: !js/asyncFunction >
        async function() {
          // some custom asynchrounous code here...
        }

Note that run_type is inline and function is mapped to function key of inline attribute. Tagging with !js/asyncFunction is how you tell Just-API parser to consider it as a custom asynchronous function.

A module asynchronous function is specified as below.

 custom_validator:
   run_type: module
   module:
     module_path: modules/custom_module.js
     function_name: customAsyncFunctionName

Note that run_type is module and function details are mapped to module attribute. module_path has the relative path to the JS file from Node's process's current working directory or relative to suite's path if you set locate_files_relative to true in meta section of the suite. The JS file is expected to be a standard Node.js module. function_name is the async function defined with async keyword and exported in the module.

Suite configuration

When you are running tests, you would want to configure API host, port etc, according to the environment you are testing.

In order to facilitate this, Just-API provides a configuration section in each suite, where you can have a custom_configuration attribute and provide a custom JS function to set suite configuration.

Here's an example to do that with an inline custom JS function.

configuration:
  scheme: https
  custom_configuration:
    run_type: inline
    inline:
      function: !!js/function >
        function() {
          if (process.env.TEST_ENVIRONMENT === 'Dev') {
             this.host = 'dev-host.com';
          }

          if (process.env.TEST_ENVIRONMENT === 'QA') { 
            this.host = 'qa-host.com';
          }
        }

you can also have a module based custom JS function to configure a suite.

Note that custom_configuration is optional. you can always specify static suite configuration if test environment details does not change for you.

configuration:
  scheme: https
  host: testhost.com
  port: 8000
  base_path: /api

See More examples here

Hooks

Just-API supports following hooks so it's easy to manage tests.

Suite specific hooks

These can be specified as part of hooks attribute.

  • Before all (runs before all specs in a suite)
  • After all (runs after all specs in a suite)
  • Before each (runs before each spec in a suite )
  • After each (runs after each passed spec in a suite )

Test specific hooks

These can be specified for each test as required.

  • Before test (runs before the spec, you can use this hook to setup test pre-requisites )
  • After test (runs after the spec if spec passes, you can use this hook to teardown/clear any test specific data )

Check out some samples of hooks here

Dynamic request construction

Static specification of a request is not possible all the time. Sometimes a test depends on data returned by another request, where you would want to run the dependency spec first and fetch required data from it and pass it on to current test request. To handle usecases like this, Just-API provides a before_test hook for every test. Using this hook you can run test pre-requisites and update request data for actual test.

Typically we need to build dynamic requests when a request depends on the data received from another request. In such cases, you can run the dependency spec in before_test hook and use the response to build the actual request for test.

Headers

Updating or overriding request headers in before test hook:

  - name: send headers specified in before test hook
    before_test:
      run_type: inline
      inline:
        function: !!js/function >
          function() {
            this.test.headers = { Authorization: 'some token' };
          }
    request:
      path: /users
      method: get
    response:
      status_code: 200

Cookies

Updating or overriding request cookies in before test hook:

  - name: send cookies specified in before test hook
    before_test:
      run_type: inline
      inline:
        function: !!js/function >
          function() {
            this.test.cookies = { uid: 'some token' };
          }
    request:
      path: /users
      method: get
    response:
      status_code: 200

Query params

Updating or overriding request query params in before test hook:

  - name: Query params added in hook
    before_test:
      run_type: inline
      inline:
        function: !!js/function >
          function() {
            this.test.query_params = { limit: 10 };
          }
    request:
       path: /users
       method: get
    response:
       status_code: 200

Path params

Updating or overriding request Path params in before test hook:

  - name: path params added in hook
    before_test:
      run_type: inline
      inline:
        function: !!js/function >
          function() {
            this.test.path_params = { id: 1 };
          }
    request:
       path: /user/{id}
       method: get
    response:
       status_code: 200

Body

You can also define request payload at runtime using hook like below:

  - name: Payload defined in hook
    before_test:
      run_type: inline
      inline:
        function: !!js/function >
          function() {
            this.test.payload = { body: {type: 'json', content: { firstName: 'john',
             lastName: 'doe'}} };
          }
    request:
       path: /users
       method: post
       headers:
         - name: content-type
           value: application/json
    response:
       status_code: 201

Custom context

You will have access to suite context and test context in hooks, So you can use them as a way to store custom data to use in later hooks.

Suite context can be accessed in hooks using this.suite. Test context can be accessed in test specific hooks using 'this.test'.

Storing suite & test data in context for reuse

When you have some data that you want to use later in some tests, you can store the data in suite context in before_all hook.

  before_all:
    run_type: inline
    inline:
      function: !!js/function >
        function() {
           this.suite.serviceSecret = 'secret';
        }

and later when you need the secret in a test, you can access it in before_test hook.

  - name: using suite context in before test hook
    before_test:
      run_type: inline
      inline:
        function: !!js/function >
          function() {
              this.test.headers = { Authorization: this.suite.serviceSecret };
          }
    request:
      path: /users
      method: get
    response: 
      status_code: 200

Similarly you can set test context in before_test hook using this.test and access it using `this.test' in after_test hook.

Spec dependencies

Just-API allows testing APIs in a flow, where one request depends on response data from another request. This is really useful when you are testing complex transaction APIs.

Running dependencies

Running pre-requisite requests can be done using hooks. There is before_each and before_test hooks.

If you have a dependency specific to a test, then you might want to use before_test hook to run the dependecy spec.

There is support for 2 types of dependencies, Intrasuite & Intersuite spec.

Intrasuite spec dependencies

Intrasuite dependency is when you have a dependency that is specified in the same suite. You can then run the dependency by using this.runSpec() in a hook. runSpec function takes 2 arguments. First argument is the name of your dependency spec and second argument is an object with additional information you want to pass to the request such as headers, query params, path params, and body.

Following set of specs show how to run dependencies as part of a test and use the data for subsequent requests.

specs:
  - name: this is the dependency spec
    enabled: false
    request:
      path: /token
      method: get
    response:
      status_code: 200

  - name: actual test spec
    before_test:
      run_type: inline
      inline:
        function: !js/asyncFunction >
          async function() {
            var response = await this.runSpec('this is the dependency spec');
            var tokenResponse = JSON.parse(response.body);
            this.test.headers = { Authorization:  tokenResponse.token };
          }
    request:
      path: /users
      method: get
    response:
      status_code: 200

Intersuite spec dependencies

Intersuite dependency is when you have a dependency that is specified in another suite but you import it using spec_dependencies construct.

Running Intersuite dependency is similar to running Intrasuite dependency.

You can import specs defined in another suite by providing the path of the suite to spec_dependencies.

spec_dependencies:
  - suites/anothersuite.yml 

Path is relative to current working directory of Node process or relative to suite's path if you set locate_files_relative to true in meta section of the suite.

You can import specs from one or more suites by listing their paths.

Note that these imported specs will only be available when you run them using this.runSpec.

Please find some examples on dependencies here

Skipping

You can explicitly skip suites and tests with specification.

Skipping a suite

When you have a suite in a directory, but want to skip running it for some reason, you can do so by providing false as value for enabled key of meta section in a suite, Just-API will skip the suite.

 meta:
  name: Disabled suite
  enabled: false
configuration:
  scheme: http
  host: 127.0.0.1
specs:
  - name: get users
    request:
      path: /users
      method: get
    response:
      status_code: 200

Note that if any error occurs before Just-API reads meta info of the suite, then suite will be marked as failure.

Skipping a test

When you have a set of specs in a suite, but want to skip a spec, you can do so by providing false as value for enabled key of the spec.

  - name: disabled spec
    enabled: false
    request:
      path: /
      method: get
    response:
      status_code: 200

Just-API will mark the spec as a skipped test.

reusing test specification

Apart from readability, an awesome thing about YAML is that you can reuse parts of the specification.

Refer to dry to see how you can reuse stuff in YAML.

you can see how response specification is being reused below with & and *

meta:
  name: suite name
configuration:
  scheme: http
  host: example.com
specs:
  - name: get user1
    request:
      path: /users/1
      method: get
    response: &default_response
      status_code: 200

  - name: get user2
    request: &default_request
      path: /users/1
      method: get
    response: *default_response

Retrying failed tests

Sometimes a resource takes a bit of time to get to a state you expect, for instance when you are polling a job status and it goes to completed state after a while. In such cases, you would want to retry hitting the same request few times.

If you see below sample, response specification says expect 200 status code. If the response validation fails then Just-API attempts to retry the request if you have specified a retry attribute. Here the request will be attempted 3 times denoted by count with 10ms wait before each attempt.

wait_before_each is an optional attribute to specify how many milliseconds you want to wait before each attempt.

  - name: retry example
    request:
      path: /retryPath
      method: get
    retry:
      count: 3
      wait_before_each: 10
    response:
      status_code: 200

Looping

You can use the loop construct to loop through a list of items, each item generating a test.

The list of items can be specified in spec beforehand or you can specify a custom JS function which returns a list of items.

Here's how a static loop is specified, type is static and loop list is mapped to static field as list of items. You will have access to that item in before_test hook by accessing this.loopItem.

  - name: static loop test
    loop:
      type: static
      static:
        - 2
        - 3
    before_test:
      run_type: inline
      inline:
        function: !!js/function >
          function() {
            this.test.query_params = { limit : this.loopItem };
          }
    request:
      path: /users
      method: get
    response:
      status_code: 200

There's another way to provide a list of items, with dynamic type and a custom JS function.

  - name: dynamic loop test
    loop:
      type: dynamic
      dynamic:
        run_type: inline
        inline:
          function: !!js/function  >
            function() {
              return [2, 3];
            }           
    before_test:
      run_type: inline
      inline:
        function: !!js/function >
          function() {
            this.test.query_params = { limit : this.loopItem };
          }           
    request:
      path: /users
      method: get
    response:
      status_code: 200

Note that if your loop has a list of n items, n tests will be generated at runtime.

Additional features

Following are some additional features offered by Just-API.

reports test duration

Just-API reports duration of each test run in all formats of reports.

running only tests matching with a given pattern/text

If you want to run only specs matches with a given text or pattern, you can do so by using --grep option.

Following invocation will run all specs whose name matches with 'user' string.

./node_modules/.bin/just-api --grep user specs

Additional request options

Following additional request options are supported.

  • followRedirect - follow HTTP 3xx responses as redirects.
  • followAllRedirects - follow non-GET HTTP 3xx responses as redirects.
  • followOriginalHttpMethod - by default we redirect to HTTP method GET. you can enable this property to redirect to the original HTTP method (default: false)
  • encoding - encoding to be used on setEncoding of response data. If null, the body is returned as a Buffer. Anything else (including the default value of undefined) will be passed as the encoding parameter to toString() (meaning this is effectively utf8 by default). (Note: if you expect binary data, you should set encoding: null.)
  • gzip - if true, adds an Accept-Encoding header to request compressed content encodings from the server (if not already present) and decodes supported content encodings in the response.

A sample spec on how to specify these options:

  - name: spec with redirection disabled
    request: 
      path: /home
      method: get
      additional_options:
        followRedirect: false
        gzip: true
    response:
      status_code: 200

Finding suites recursively

When you want to run suites stored in a directory hierarchy spanning more than one nested level, you can invoke the Just-API with --recursive option.

./node_modules/.bin/just-api --recursive specs

Proper error reporting

When a test or suite fails, Just-API provides the correct error, that caused the failure in reports.

Exit code for CI support

Just-API exits with proper exit code, so you can use it in CI to determine the status of your tests.

Usually exit code is equal to number of failed suites unless some unexpected error occurs.

Logging HTTP request/response data for failed tests

When a test with multiple dependencies fails it's hard to track which request has failed. To make failure tracking easy, Just-API allows you to ask for HTTP call details for failed tests. You would be able to see all HTTP calls made for a failed test in HTML or JSON report.

To enable this feature you need to invoke Just-API with --reporter-options logRequests

./node_modules/.bin/just-api --reporter html --reporter-options logRequests specs

No callbacks

You might have observed that there is no mention of callbacks anywhere. yes, Just-API does not support callback mechanism when running custom JS functions. This is to encourage usage of promises for asynchronous operations.

When you are dealing with asynchronous tasks, wrap them in a async function and return a promise.

Running suites in parallel

See page

Reporters

See page