Configuring Jest with TypeScript: A guide to setting up and running tests across multiple files

Currently, I am diving into the world of TDD and attempting to create a basic test suite for my Node Express API.

My project directory has the following structure:

.
└── root/
    ├── src/
    │   ├── services/
    │   │   └── MyService.ts
    │   └── Server.ts
    └── tests/
        ├── services/
        │   └── MyService.spec.ts
        └── SetupTests.spec.ts

My goal is to have JEST execute the "SetupTests.spec.ts" first, followed by the "MyService.spec.ts" tests. In my "SetupTests.spec.ts" file, I have the following code:

import Server from '../src/Server'
import axios, { AxiosInstance } from 'axios'

let testAxios: AxiosInstance = axios.create({ baseURL: 'http://localhost:3000' })
let testServer: Server = new Server()

beforeAll(() => {  
  return testServer.bootstrap() //It returns the 'app.listen()' object
})

afterAll(() => {
  return testServer.shutdown()
})

//I'm wondering if it's possible to include other *.spec.ts test files here - is it possible?

However, when I run "npx jest", it attempts to execute "MyService.spec.ts" before "SetupTests.spec.ts", leading to failures since the Server is not listening yet.

What steps can I take to resolve this issue?

Alternatively, should I include the "beforeAll" and "afterAll" calls in every *.spec.ts file? Is this considered a best practice?

Thank you for your assistance!

Answer №1

I successfully achieved my goal by following these steps:

I divided the setup into two separate files with the extensions "**.setup.ts" (without ".spec.ts" or ".test.ts") each containing specific content:

Content of "env.setup.ts" file:

import dotenv from 'dotenv'
console.log("=========== ENV SETUP LOADING ===========")
dotenv.config()
console.log("=========== ENV SETUP LOADED! ===========")

Content of "server.setup.ts" file:

import Server from '../common/Server'

const server = new Server()

beforeAll(() => {
  console.log("=========== TEST SERVER STARTING ===========")
  server.bootstrap()
  console.log("=========== TEST SERVER STARTED! ===========")
})

afterAll(() => {
  console.log("=========== TEST SERVER STOPPING! ===========")
  server.shutdown()
  console.log("=========== TEST SERVER STOPPED ===========")
})

I also utilized the "jest.config.ts" file to reference the setup files:

import type { JestConfigWithTsJest } from 'ts-jest'

const jestConfig: JestConfigWithTsJest = {
  preset: 'ts-jest',
  setupFiles: [
    "./tests/env.setup.ts"
  ],
  setupFilesAfterEnv: [
    "./tests/server.setup.ts"
  ]
}

export default jestConfig

To create a test suite for a specific file, I generated a file named "MyServiceClass.test.ts" with the following logic:

import axios, { AxiosError, AxiosResponse } from "axios"

describe("Test my simple api", () => {
  const testAxios = axios.create({ baseURL: 'http://localhost:3000' })
  test("my test 1", () => {
    // return axios. [...]
  })

  test("my test 2", () => {
    // return axios. [...]
  })
}

By implementing this setup, everything is now functioning as intended!

I raised this query as I could not find a suitable structure for this initial setup, rather than having everything in one file.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular's ngRoute is causing a redirect to a malformed URL

Currently, I am in the process of developing a single-page application using AngularJS along with NodeJS and Express to serve as both the API and web server. While testing locally, everything was working perfectly fine. However, after cloning the repositor ...

ensuring case sensitivity in URLs using node.js with express

Is there a way to make URL's case sensitive in my code? app.get() app.get('/([a-z]{2}/)api*', function(request, response){}); In the current setup, this app.get() function matches both /EN/api and /eN/api. How can I modify it to only match ...

Converting less files to css using expressjs 4.x

I am having trouble compiling the less file in the public folder of my expressjs application. These are the dependencies that I am using: "devDependencies": { "ejs": "^2.3.1", "express": "^4.10.6", "mysql": "^2.5.4" }, "dependencies": { ...

Encountered a 404 Error when attempting to store data in mongoDb using node.js and express

Currently, I am facing an issue while trying to save data from Bootstrap input fields into my MongoDB database. Every time I attempt to do so, I encounter the error insertMovie:1 POST http://localhost:3000/insertMovie 404 (Not Found). Despite my efforts to ...

Using NodeJS to perform asynchronous tasks with setImmediate while also incorporating private class

Today marks my first time experimenting with setImmediate. I've come to realize that it may not be able to run private class methods. Can someone shed some light on this? Why is that the case? Not Functioning Properly When trying to use a private cl ...

Ways to modify the access control to permit origin on a specific API URL in React

https://i.stack.imgur.com/tqQwO.png Is there a way to modify the access control allow origin for a URL API? I keep encountering error 500 whenever I try to load the page. After logging in, I included this code snippet: const options = { header ...

Display a semantic-ui-react popup in React utilizing Typescript, without the need for a button or anchor tag to trigger it

Is there a way to trigger a popup that displays "No Data Found" if the backend API returns no data? I've been trying to implement this feature without success. Any assistance would be greatly appreciated. I'm currently making a fetch call to retr ...

The error message "result.subscribe is not a function" indicates that there was a problem

I encountered an issue with the following error message: Uncaught TypeError: result.subscribe is not a function Here's a screenshot of the error for reference: https://i.sstatic.net/yfhy0.png Despite attempting to handle the error, I'm still s ...

When using Express.js for file uploading, it is important to first verify that a file has been sent, set a maximum file size limit, and ensure

After working with expressjs for a month, I've encountered some issues with file uploads. Despite researching on Google and various blogs, I haven't been able to find answers to the following three questions: What do I need to do or what setting ...

Typescript implementation for a website featuring a single overarching file alongside separate files for each individual webpage

Although I've never ventured into the realm of Typescript before, I am intrigued by its concept of "stricter JS". My knowledge on the subject is currently very limited as I am just starting to experiment with it. Essentially, I have developed my own ...

Apply a border to the div that has been selected

I have a tool for storing information and I am using *ngFor to display each instance in a line. Is there a way to add a border when clicking on a line? The border should only appear on the clicked line, disappearing from the previous one if another line i ...

In TypeScript, it can be challenging to determine the equality between a value and an enum

I am encountering an issue with my simple code: enum Color { BLUE, RED } class Brush { color: Color constructor(values) { this.color = values.color } } let JSON_RESPONSE = `{"color": "BLUE"}` let brush = new Brush(JSON.parse(JSON ...

NodeJS MySQL failing to retrieve the most updated data post-write

I'm struggling to solve an issue where after performing data operations (create, update, delete) and then querying for the data afterwards, I receive the previous version of the data rather than the updated version. For example: Let's say I hav ...

Iterating through an array of MongoDB document IDs, querying each ID and then storing the results in a new array results in an empty array

Having trouble with the following code: const users = [] event.registeredUsers.forEach(userId => { User.findOne({ _id: userId }).then(user => { console.log(user) // displays a valid user users.push ...

The type '{ children: Element[]; }' does not include the properties 'location' and 'navigator' that are present in the 'RouterProps' type

Struggling to implement React Router V6 with TypeScript, encountering a type error when including Routes within the `<Router />` component. The error message indicates that the children property passed to the Router is of an incorrect type, despite u ...

Angular: Unable to locate route declaration in the specified path /src/app/app-routing.module.ts

Whenever I attempt to set up automatic routing for components that have been created using the command below ng generate module orders --route orders --module app.module I encounter the following error message The requested URL /src/app/app-routing.mod ...

Step-by-step guide on using nodemon on a web hosting server

I am currently designing a website that includes a login form and I am in the process of uploading it to a web hosting service In order to activate my login form, I have to use node index Is there a way to change the destination of this tag: <li class ...

Establishing a Link to Mongodb-Native-Driver within an express.js Application

In my express.js app, I am utilizing the mongodb-native-driver. With a total of 6 collections in the database, I have created 6 separate JavaScript files, each containing a collection as a JavaScript object defined by a function (e.g function collection(){ ...

When working with Typescript, NextAuth throws errors while embedding

When attempting to implement NextAuth into my Typescript application, I encounter two errors: one with NextAuth and the other with NextAuthOptions. import NextAuth from "next-auth" import { NextAuthOptions } from "next-auth" import Go ...

How can we improve our handling of cyclic requires and EventEmitter in our code?

My user service code looks like this: 'use strict'; let events = require('services/events'); module.exports = { create: function (data) { doCreate(data).then(user => { events.emit('user.create'); ...