Is there a way to utilize a single app instance across all of my end-to-end tests?

Currently, I am involved in a nestjs project that is structured with separate modules, each of which has its own e2e test. In these tests, an instance of the application is set up within the beforeAll() method as shown below:

const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [
        AppModule,
      ],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();

Upon completion of the test, the app.close() call is made to shut down the app.

I am exploring options to utilize the same app for all my tests and then only close the app at the end. The process of creating and tearing down the entire app for each test is causing delays in the execution of e2e tests, along with issues related to Async timeout errors.

Answer №1

Through numerous attempts, I discovered that achieving this was unattainable due to the following reasons:

Each test operates in its own distinct environment

Allow me to explain further:

1. Attempting to establish an app instance in globalSetup is futile.

Note: Global variables created during globalSetup can only be accessed during globalTeardown. Hence, any globals defined here cannot be retrieved in your test suites.

This results in the impossibility of utilizing a singular global.app variable across multiple test cases. Without the availability of global.app variable sharing, the use of request(app.getHttpServer()), crucial for end-to-end tests, becomes unfeasible.

2. Although it is possible to set up an app instance in setupFiles or setupFilesAfterEnv, these files are executed for every individual test case. This contradicts the original purpose.

Each setupFile will run once per test file. As each test runs independently within its designated environment, these scripts execute within the testing environment before running setupFilesAfterEnv and before the actual test code.

The documentation does not specify that setupFileAfterEnv will run once per test file. Despite this ambiguity, I attempted to implement it, only to find out that it ran repeatedly for each test file.

Answer №2

To set up a Jest configuration for testing an app that listens on a specific port, pass a script to globalSetup. Then, create an agent in your test to make requests to the app using the same port.

  1. Introduce a global variable in your Jest configuration.
import type { Config } from 'jest';

export default async (): Promise<Config> => {
  return {
    ...
    globals: {
      APP_PORT: findOpenTCPPort(), // You can implement this logic yourself or hardcode it
    },
    globalSetup: '<rootDir>/e2e.globalSetup.ts',
    globalTeardown: '<rootDir>/e2e.globalTeardown.ts',
  };
};
  1. Create typings for the new global variable in a .d.ts file. I named my file e2e.types.d.ts and placed it in a types directory.
declare global {
  const APP_PORT: number;
}

export {};
  1. Ensure that the *.d.ts file is recognized by the TypeScript server.
{
    "extends": "../tsconfig.json",
    "compilerOptions": {
        "typeRoots": ["../node_modules/@types/", "./types"]
    }
}
  1. Add the script e2e.globalSetup.ts to create the NestJS app.
import { Test } from '@nestjs/testing';

module.exports = async function globalSetup(_, projectConfig) {
  const module = Test.createTestingModule({ ... })
  const moduleRef = await module.compile();
  const app = moduleRef.createNestApplication();
  await app.init();
  await app.listen(projectConfig.globals.APP_PORT);
  globalThis.APP = app;
};
  1. Include a e2e.globalTeardown.ts script to shut down the app.
module.exports = async function globalTeardown() {
  await globalThis.APP.close();
  process.exit();
};
  1. In your tests, create a supertest agent to interact with the app.
...
import request from 'supertest';
const agent = request(`http://localhost:${APP_PORT}`);

describe('[POST] /some/endpoint', () => {
  it('400 - Missing parameters', async () => {
    const response = await agent.post('/some/endpoint').send({});
    expect(response.statusCode).toBe(HttpStatus.BAD_REQUEST);
  });
});

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

What is the process for running Storybook Jest Tests on an Nx library?

I currently have a monorepo in Nx with multiple Angular libraries. Each library has its own Storybook configuration, following the guidelines outlined in this helpful Nx tutorial. So far, everything has been running smoothly. I've successfully built ...

Adjusting the width of row items in Angular by modifying the CSS styles

I am envisioning a horizontal bar with items that are all the same width and evenly spaced apart. They can expand vertically as needed. Check out the updated version here on StackBlitz https://i.sstatic.net/MFfXd.png Issue: I am struggling to automatica ...

TypeScript does not verify keys within array objects

I am dealing with an issue where my TypeScript does not flag errors when I break an object in an array. The column object is being used for a Knex query. type Test = { id: string; startDate: string; percentDebitCard: number, } const column = { ...

What is the reason behind including types in this JavaScript file and why does it function properly in a React JS application but not in a React TS application?

The JavaScript file contains types and functions as expected in a JavaScript React app. However, when used in a TypeScript React app, it results in a compile error. For reference: https://github.com/OpenGov/react-leaflet-heatmap-layer/blob/master/src/Heat ...

Tips for testing nested subscribe methods in Angular unit testing

FunctionToTest() { this.someService.method1().subscribe((response) => { if (response.Success) { this.someService.method2().subscribe((res) => { this.anotherService.method3(); }) } }); } Consider the following scenario. ...

rxjs - monitoring several observables and triggering a response upon any alteration

Is there a way to watch multiple observables and execute a function whenever any of them change? I am looking for a solution similar to the functionality of zip, but without requiring every observable to update its value. Also, forkJoin isn't suitable ...

What is the best way to implement React ErrorBoundary in conjunction with redux-observable?

When dealing with asynchronous code, React Error Boundaries may not function as expected. In my case, I am using redux-observable and rxjs to retrieve data from an API. To handle errors, I am trying to utilize the catchError function provided by rxjs. I ...

Using Vue to Navigate Through JSON Responses

I am working with an API that provides a JSON response structured like this: { "Thriller": "Thriller books", "Biographical": "Biographical books", "Romance": "Romance books" } My goal ...

Developing Derived Classes in Typescript

I am looking to enhance my service class by creating a subclass where I can define functions with the same name but different implementations. My desired structure is as follows: httpWrapper.get //default is observables. returns observable httpWrapper.pr ...

What are the steps to successfully launch a Node.js / Express application with typescript on heroku?

I attempted to deploy my node.js / express server app on Heroku but encountered some issues. I followed the steps outlined in a blog post, which you can find here. Unfortunately, the deployment did not succeed. Below are snippets of the code from my serve ...

The type "AppRouterInstance" cannot be assigned to type "nextRouter"

Within my Next.js project, a registration form is included as seen below: "use client"; import * as React from "react"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form" ...

Can anyone help me troubleshoot createPortal in NextJS with TypeScript?

Currently, I am working on a toy project using Nextjs and Typescript. However, I have encountered an issue while attempting to create a Modal using createPortal. Whenever I click the button, nothing happens. Upon investigation, it seems that the value ...

Unleashing the power of Typescript enums in conjunction with external modules through browserify

Previously, I utilized TypeScript internal modules and included numerous script tags to initialize my app. Now, I am in the process of transitioning the project to utilize external modules (using browserify), but I have hit a roadblock when it comes to con ...

Receiving the error notification from a 400 Bad Request

I'm having trouble showing the errors returned from an API on my Sign up form when a user submits invalid data. You can check out the error response in the console here: console ss This is my approach in RegisterComponent.ts: onSubmit() { this.u ...

Implementation of a function in Typescript that can be defined with a

I am currently diving into the Typescript specification and I'm facing a challenge in creating a functional implementation for describable functions. https://www.typescriptlang.org/docs/handbook/2/functions.html The provided example lacks completene ...

How can you retrieve the keys of an object that conforms to an interface?

In the following demonstration, we have two objects - KEYS and KEYS2. When importing KEYS in index.ts, autocomplete suggestions are available for K1 and K2 because KEYS does not adhere to an interface. On the other hand, with KEYS2, autocomplete is not pr ...

What is the best way to effectively pass data to a React / NextJS Video component?

I'm currently using a React-based video player that has the following setup: <ReactPlayer playing={true} controls={true} muted={true} loop={true} width="100" height="100" url='videos/330163_SF.mp4' poster="images/ ...

Issue TS7053 occurs when trying to access any index of the target of a React.FormEvent<HTMLFormElement>

I've been working on adapting this tutorial to React and TypeScript. Here is the code snippet I have implemented for handling the onSubmit event: const handleSignUp = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); ...

Utilize a jest mock object and pass it as a method parameter to achieve seamless testing

I am attempting to create a mock object (ColumnApi from ag-grid) using jest and then pass it as a parameter to a function that calls the "getAllColumns" method from ColumnApi. I am not concerned with how the "getAllColumns" method functions, but I want it ...

How is it possible to utilize type assertions with literals like `false`?

When working in TypeScript, I came across an interesting observation when compiling the following code: const x = true as false; Surprisingly, this direct assertion is valid, creating a constant x with the value true and type false. This differs from the ...