paint-brush
TypeScript vs JavaScript in REST API Automated Testby@bormando
3,329 reads
3,329 reads

TypeScript vs JavaScript in REST API Automated Test

by Dmitrii BormotovAugust 4th, 2023
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

TypeScript is a programming language which is presented as a package in Node.js ecosystem. By using this package, you can: 1. Make concise (absolute) imports in your project. 2. Create custom types for your request & response payloads. 3. Use intellisense & type checking features to make less syntax mistakes in your code. Custom types also act as a documentation for your payload data - you won't have to check with your external collections/tools for this anymore!
featured image - TypeScript vs JavaScript in REST API Automated Test
Dmitrii Bormotov HackerNoon profile picture

Hello everyone!


I was inspired to write this article by my students and mentees. I often recommend they learn TypeScript as soon as they get comfortable with the test automation process on JavaScript. Let’s see what the traits of using TypeScript in your test automation framework in terms of REST API testing are…


You can find the full code of a test project here.

TypeScript

Let’s not get too deep into what TypeScript is and how it is different than JavaScript and state the important thing - it’s the programming language. But, quite important too - it depends on JavaScript (Node.js platform) directly.


TypeScript is presented as a Node.js package, so I look at this just as JavaScript with some cool features.


To learn more about the language itself and what it has to offer - please visit the official website while we are going to talk about its features in terms of test automation…

Project setup

Let’s go through the test automation project creation process on TypeScript:


  1. Create a Node.js project.

    npm init -y

  2. Install the TypeScript package.

    npm i typescript

  3. Generate a default TypeScript configuration for the project - tsconfig.json.

    npx tsc --init


The command above will generate a default config file, but I recommend shortening it a lot to something like this:


{
  "compilerOptions": {
    "baseUrl": "./",
    "module": "esnext",
    "target": "esnext",
    "sourceMap": false,
    "moduleResolution": "node",
    "allowJs": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "paths": {
      "*": ["./*"]
    }
  }
}


This config contains the required minimum:


  • uses the latest EcmaScript version,
  • makes JSON imports available,
  • lets you use absolute path in imports.


You can extend your config using official documentation.


Tools selection

You can use any tool that the Node.js ecosystem has to offer, but in my experience - most of the engineers who work with TypeScript choose Jest for a couple of good reasons:


  • great community support (updates, answers, docs, code examples),
  • flexible configuration.


Previously, I had fun using Mocha + Chai to set up the core of the project, but now I'm sticking to Jest, too, as it contains both a test runner & assertion library.


Axios seems to be the most popular HTTP client, so I suggest this is your pick too.


Can't say that you are forced to use this for your setup, but I'm saying that it's the usual thing when you look through the projects.


Now, simply install these packages as dependencies:

npm i jest axios

Type collections

Some packages (like Axios) contain TypeScript types inside, but Jest & Mocha don't. Also, Jest requires a ts-jest package along with @types/jest to work properly - the first one enables TypeScript features & second lets you use IntelliSense.


So keep in mind - if you don't have autocomplete feature when you're trying to use some of the packages - you're probably missing type declarations.


Let's install TypeScript-related extensions (packages) as well:

npm i ts-jest @types/jest

Configuration

Jest requires a ts-jest config preset, so you must declare it in your config (or package.json) file:


{
  "jest": {
    "preset": "ts-jest"
  }
}


If you're planning to use absolute path within a project, you'd need to adjust your config as well:


{
  "jest": {
    "preset": "ts-jest",
    "moduleDirectories": [
      "node_modules",
      "<rootDir>"
    ]
  }
}


This config allows you to run tests with a simple command... jest


So, configure your test script in package.json to be:


{
  "scripts": {
    "test": "jest"
  }
}


And then run your tests any time with npm test or npm run test command.


Running tests


I also recommend you install a Jest Runner extension if you are a Visual Studio Code user - it allows you run/debug desired tests/suites with just one click. In WebStorm, it's a built-in feature.


Run & debug tests with one click!

Custom types

The main feature that TypeScript introduces into REST API testing is... types, of course!


You can declare what your request & response body should look like, i.e., key names, value types and etc.


Let's take a Paysis server as an example - we can write down its request body payload for /auth endpoint as a type:


export type AuthRequestBody = {
  login: string
  password: string
}


And same for the response body - what server should send to our request:


export type AuthResponseBody = {
  token?: string
  message?: string
}


Since there'd be a different payload for success/failure scenarios - you can mark keys as "optional" via the “?” character.


Once it's done - you can use these types to compose requests and verifications in your tests...

Request

In Axios, you can say what body you are sending via the request config:


const payload: AxiosRequestConfig<AuthRequestBody> = {
  method: 'post',
  url: '/auth',
  data: {
    login: process.env.USERNAME,
    password: process.env.PASSWORD,
  },
}


AuthRequestBody in AxiosRequestConfig<AuthRequestBody> means exactly that ☝️

It means you'll be forced to use the payload that matches the provided type AuthRequestBody in data object. If you forget to set some required fields or set some excessive ones - you'll see an error.

Response

The same thing can be done about response as well:


const response: AxiosResponse<AuthResponseBody> = await client.request(payload)


It will add autocomplete to the response.data object, so you'd be able to reach response.data.token or response.data.message fields.

Advanced tools

Apart from the simple stuff above, it's also possible to generate a JSON schema from your custom types. It lets you not check every single key in a response body to see if it matches the schema but check the whole payload.


So the idea is:


  1. Generate a JSON schema from custom types.
  2. Use a custom matcher toMatchSchema to validate the response body.


Pretty cool stuff, but keep in mind that your tests might become flaky after these changes - it happens when some additional fields appear, so you'd need to update the schema regularly.

Conclusion

TypeScript setup might be tricky, especially if it's your first time, but it's worth it!


If you cover your input & output data with types - there’s no way you’d make a typo or some other syntax error when you parse these objects. It saves you from simple mistakes and lets you see the structure of your requests right in your code, so you don’t have to open any HTTP collection (like Postman) and look for the request you need to see what body it request/responds with.


Let me know about your experience and what you think about it.