So I'm trying to have some global variables to use easily in my test files so I researched a lot and managed to make a jest setup file that runs before all my test files to initialize the global variables and this is the setup.ts
file
import app from'../src/express';
import request from 'supertest';
//Set Express app as global
global.app = request(app);
//TODO: Add global data
It's working fine but the autocomplete isn't working in my test files so after searching for the problem I found out I had to merge my new added variables to NodeJS.Global
and ended up doing so in a file called global.d.ts
declare global {
namespace NodeJS {
interface Global {
app: import('supertest').SuperTest<import('supertest').Test>;
}
}
}
but still, nothing is working tried other solutions but none worked.
Note
ts.config
"target": "es2019",
"moduleResolution": "node",
"module": "commonjs",
"lib": ["es2019"],
"sourceMap": true,
"outDir": "dist",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitThis": true,
"resolveJsonModule": true,
"alwaysStrict": true,
"removeComments": true,
"noImplicitReturns": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"allowJs": true /* Allow javascript files to be compiled. */,
"typeRoots": [
"./types",
"node_modules/@types",
] /* List of folders to include type definitions from. */,
"types": [ "node","jest"],
},
"include": ["./src/**/*", "./utils/**/*", "localization", "./tests/**/*"],
"exclude": ["./seeds/**/*"]
jest.config.ts
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/
export default {
clearMocks: true,
coverageProvider: "v8",
coverageDirectory: "coverage",
collectCoverage: true,
setupFiles: ["<rootDir>/tests/setup.ts"],
testMatch: [
"<rootDir>/tests/**/*.test.ts"
],
};
If you want to use it like app
(instead of global.app
), then declare it globally:
declare global {
const app: import('supertest').SuperTest<import('supertest').Test>;
}
I had a similar usecase, where I needed a safeSubscribe
helper available globally in all my tests.
This function would perform the subscription and then do the unsubscription in a general afterEach
hook, executed after any test.
Here is how I achieved that:
// test/setup/safe-subscribe.ts
import { Observable, Subscription } from 'rxjs';
const subscriptions: Subscription[] = [];
const safeSubscribeFn = <T>(source: Observable<T>): T[] => {
const res: T[] = [];
const subscription = source.subscribe((value) => {
res.push(value);
});
subscriptions.push(subscription);
return res;
};
global.safeSubscribe = safeSubscribeFn; // Add helper implementation
global.afterEach(() => {
while (subscriptions.length > 0) {
const subscription = subscriptions.pop();
subscription?.unsubscribe();
}
});
declare global {
// See: https://stackoverflow.com/a/68328575/12292636
var safeSubscribe: typeof safeSubscribeFn;
}
// jest.config.js
module.exports = {
...,
setupFilesAfterEnv: [
...,
'./test/setup/safe-subscribe.ts', // Import your setup in jest config
],
};
// tsconfig.spec.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"module": "commonjs",
"types": ["jest", "node"],
"resolveJsonModule": true,
"esModuleInterop": true,
},
"files": ["src/polyfills.ts", "test/setup/*.ts"], // Add it there
"include": ["src/**/*.d.ts", "src/**/*.spec.ts", "test/setup/*.ts"] // And also there
}
Now, it is possible to use the globally-defined safeSubscribe
in the tests:
// foo.spec.ts
it('should emit value', () => {
// Given
const outputs = safeSubscribe(service.myObservable$); // global import with typescript stuff ✔️
// When
actions$.next(action);
// Then
expect(outputs).toHaveLength(1);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With