API automation testing using CodeceptJS, TypeScript and Got

Vitalii Sotnichenko
Byborg Engineering
Published in
5 min readMar 3, 2021

API (Application Programming Interface) — an interface that facilitates interaction between applications. In modern client server architecture, web and mobile applications generally use APIs to communicate with servers. Essentially, what happens is a client sends a request with headers and payloads to a server and the server responds with its own headers, payloads, and status codes.

API tests help confirm proper functionality of individual functions.

What are the benefits of API testing over UI testing?

  • Fast test execution — UI tests need a significant amount of time to render components and load pages, but API tests do not. Furthermore, API tests can be developed even while the front end is still under development. We will receive feedback faster with API tests.
  • Doesn’t need browsers — Because API testing usually doesn’t need a working UI, this allows us to conserve resources. Developing and maintaining browser infrastructure is expensive and complex.
  • Reliable — API tests are generally more stable than UI tests, because API tests review business logic, and layout changes don’t impact these tests, helping us to avoid flaky tests and instability
  • Platform independent — API works the same for desktop and mobile applications, which means that API tests only need to be written once because they are the same for both platforms

I will use the following set of tools to demonstrate API testing:

  • CodeceptJS
  • NodeJS
  • Got
  • TypeScript

CodeceptJS is JS based e2e testing framework with a special BDD-style syntax. The tests are written as a linear scenario of the user’s action on a site.

TypeScript is an open-source language based on JavaScript with added static type definitions.

GOT — high-level powerful HTTP client library for NodeJS with a bunch of useful features to help writing API tests. The features include retries, exceptions, redirects, progress events, advanced API, and cookies.

Configuration steps

  1. CodeceptJS initialization
  • npx create-codeceptjs . — to get CodeceptJS and Playwright helper
  • npx codeceptjs init — CodeceptJS initialization to create a config file: codecept.conf.js and package.json file

2. TypeScript configuration:

  • Install TypeScript and ts-node into your project
npm install typescript ts-node
  • Update CodeceptJS configuration adding ts-node/registeras the first line of your config file
require('ts-node/register')
  • add tsconfig.json file to your project and and add the following code to it:

3. Set Up steps.d.ts:

To configure steps.d.ts, just run the command npx codeceptjs def. This command will generate steps.d.ts with the following lines:

/// <reference types='codeceptjs' />
type steps_file = typeof import('./steps_file.js');

declare namespace CodeceptJS {
interface SupportObject { I: I, current: any }
interface Methods extends Playwright {}
interface I extends ReturnType<steps_file> {}
namespace Translation {
interface Actions {}
}
}

4. Install Got

npm i got

Writing tests

I am going to use a pet store API as an example to demonstrate how to write a test — https://petstore.swagger.io/. It will give us a simple way to figure out the output of our requests.

Let’s start with a simple GET request and write a test that lists store orders based on ID.

First, we should create a test file consisting of test scenarios with the .ts extension to cover our feature and import got library.

import got from 'got';

The test contains a got library request that retrieves the base URL and endpoint. The retrieved response should be parsed in JSON format.

Let’s continue expanding the test suite by adding a POST request when creating a new user in our store. First, grab the user model from the swagger endpoint and add it to the separate variable inside the Scenario function, overriding the default values with your own.

const userFields = {
"id": 1,
"username": 'johnSmith',
"firstName": 'John',
"lastName": 'Smith',
"email": 'john@gmail.com',
"password": '123456',
"phone": '324554545',
"userStatus": 0
}

Then, let’s create a response variable that calls our got function excluding URL and HTTP methods (POST method in our case)

const response = await got(`${process.env.BASE_URL}/user`, {
method: 'POST',
json: userFields
})

We need to pass the JSON parameter with our model from swagger to the second header. Simply parse the response body to the next line to add our assertions for our test — validating the status code and message. The complete test looks like this:

For the third test, we will place an order in the store to define the different types of input data listed in the model.

const id: number = 1
const petId: number = 1
const quantity: number = 5
const status: string = 'placed'

Then, put these variables into a JSON object in the header

json: { id, petId, quantity, status }

Let’s look at a full Scenario with TS types passing to the JSON object.

To avoid the manual JSON parsing of the response body and instead rely on the automatic parsing response from the server from string to object, we need to add a new parameter to the got function. This will be called responseType.

responseType: 'json'

Another thing we should add to avoid compiling TypeScript errors related to object errors is to indicate our generic response type as any. That means that our response body can be anything, and we can call on it with any method without compilation errors. The full got request should have the following syntax:

const response = await got<any>(`${process.env.BASE_URL}/store/order`, {
method: 'POST',
json: { id, petId, quantity, status },
responseType: 'json'
})

Let’s take a look at the complete test scenario after all setting the types and response:

Conclusions: API testing using CodeceptJS stack based on TypeScript and Got HTTP client can be set up easily and quickly, allowing us to catch errors on the compilation stage and explicitly assign static data types to describe data.

--

--