Ts-jest: Support jest config globalSetup and globalTeardown

Created on 5 Jan 2018  Â·  24Comments  Â·  Source: kulshekhar/ts-jest

  • Feature request

Are there any plans to support the new jest feature globalSetup and globalTeardown?
Those two configuration options are documented here and the PR for the new jest feature here.

Currently an error is thrown by jest, because the .ts files are not transpiled (I guess).

//package.json with jest config
"jest": {
        "transform": {
            "^.+\\.tsx?$": "ts-jest"
        },
        "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
        "moduleFileExtensions": [
            "ts",
            "tsx",
            "js",
            "jsx",
            "json"
        ],
        "testResultsProcessor": "jest-junit",
        "globals": {
            "ts-jest": {
                "skipBabel": true
            }
        },
        "globalSetup": "./src/test/global-setup.ts"
    }
//src/test/global-setup.ts
export default async () => {
    console.log('JEST global setup');
}
cross-env NODE_ENV=testing jest --runInBand

<path>src/test/global-setup.ts:1
(function (exports, require, module, __filename, __dirname) { export default async () => {
                                                              ^^^^^^

SyntaxError: Unexpected token export

My currently installed packages are

  • jest 22.0.4
  • ts-jest 22.0.0

Most helpful comment

why is this closed, has this been solved?

All 24 comments

There's an issue opened to do that on jest repository by using _transform_ (see here). And if I correctly understand Jest behavior, ts-jest cannot manage this issue thanks to Jest architecture.

Is there some ts-jest mainteners who can confirm that ?

Update : I take a look to Jest source code, and the problem seems to come from this line.

@yss14 this looks like an issue whose solution lies outside ts-jest (as @AamuLumi pointed out)

All ts-jest (or any transformer) does is take in code and return the transpiled code. Jest would need to use the transformer when doing global setup and teardown to support this use case.

I'm closing this issue but if I'm wrong and there's something we need to do here, it can be reopened again.

Instead of waiting a fix, you can simulate globalSetup and globalTeardown by this way :

import * as jest from 'jest';

// globalSetup
async function init() {
    console.log('Initialization');

    // Do all your initialization stuff 
    // I use a setTimeout to simulate true async
    return new Promise<void>((resolve, reject) => {
        setTimeout(() => {
            console.log('Init finished');
            resolve();        
        }, 1000)
    });
}

// globalTeardown
async function afterTests() {
    console.log('End of tests - Execute something');
}

init()
    .then(jest.run)
    .then(afterTests)
    .catch((e) => console.error(e));

Output :

> ts-node ./testInit.ts 
Initialization
Init finished
 PASS  ./test1.test.ts
  Tests
    ✓ Async test (1009ms)
    ✓ Sync test (1ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        2.036s
Ran all test suites.
End of tests - Execute something

I hope this gonna help you ! :)

@AamuLumi Thanks man! This is really what I'm looking for :) Will try this on monday! ;)

@AamuLumi Which version do you use? For me jest.run does not exist and I also cannot import * as jest from 'jest' because it's only exporting a namespace.

"dependencies": {
    "@types/jest": "^22.0.1",
    "@types/node": "^8.5.7",
    "jest": "^22.0.4",
    "ts-jest": "^22.0.0",
    "typescript": "^2.6.2"
  }

Normally, typescript verification will not find jest, because programmatic use is not defined in types. But it should works at execution. Do you have installed jest locally instead of globally ?

You can take a look at source code for explanation.

@AamuLumi Can we set global variables that will be available in the tests with the workaround you have provided?

I don't know. I saw tests are launched in vm for Node.js testing, so I'm not sure global variables are shared between startup code and test code. You can give it a try and tell us if that works or not. :)

If anyone using typescript stumbles upon all of this with a naive question how would you hook it all up and invoke your typescript code out of this jest handler, I've described the exact sequence of steps in https://github.com/facebook/jest/issues/5164#issuecomment-376006851.

why is this closed, has this been solved?

FYI, the upstream issue with Jest is here: https://github.com/facebook/jest/issues/5164

I spent a few hours struggling with the same issue.
I ended up creating a test-runner file that imports all of my tests from all my test files (one file = one test suite) and then run them.
This way the beforeAll event will take place for all of your test files, same goes for the afterAll.
And 0 worries about transpilling ts to js...

Hopefully it can save some time for someone else.
```js
// tests/conversation.ts
export const conversationModule = function () {
test('create a conversation', async (done) => {
const user1: User = await AuthenticationService.registerUser('user1', 'test1', '[email protected]');
const user2: User = await AuthenticationService.registerUser('user2', 'test2', '[email protected]');

    const conversation: Conversation = await ConversationService.createConversation(user1.id, user2.id);

    expect(conversation.id).not.toBeNull();
    done();
});

// ...

};

// tests/test-runner.ts
import { conversationModule } from './conversation';
import { authenticationModule } from './authentication';

beforeAll(async done => {
const connection = await createConnection('testing');

User.useConnection(connection);
Conversation.useConnection(connection);
Message.useConnection(connection);

done();

});

describe('Conversation module', conversationModule);
describe('Authentication module', authenticationModule);

afterAll(async (done: Function) => {
const connection = getConnection('testing');
await connection.close();

done();

});

With Jest 24, this is finally supported ;)
https://github.com/facebook/jest/pull/7562

@yss14 Can you show usage example?

I'm trying to setup:
"jest": "24.9.0",
"ts-jest": "24.1.0"

jest.config.js:

module.exports = {
globals: {
        'ts-jest': {
            tsConfig: path.resolve(rootDir, 'src', 'tsconfig.spec.json'),
            diagnostics: false,
        },
},
globalSetup: './jest.setup.ts',
}

jest.setup.ts:

export default async function () {
    (global as any).testMy = 'Spartaaaa!';
}

*.spec.ts:

it ('test', () => {
...
console.log((global as any).testMy);
});

shows me 'undefined'

@viT-1 See the jest docs.

Note: Any global variables that are defined through globalSetup can only be read in globalTeardown. You cannot retrieve globals defined here in your test suites.

@phikes hmm then how are we able to get those variables inside test suites? even typeorm getConnection don't work inside testsuites but works fine on teardown :(

@hugo-dlb but if we have multiple tests we need to write all these for all tests file . We can create function but still we need to write beforeAll and afterAll. And the worst thing is with this way we need to open and close database connection everytime which has performance cost .Hmm what might be the best solution :(?

@shirshak55 I did just that in our test suite. Just use beforeAll to set up your typeorm connection. Has the benefit of being verbose.

@phikes but i have like 20 test suites :( and doing same repetition is really sad and I am frequently stopping and starting connection which makes tests too slow :(

Does setupFileAfterEnv help ?

OT, but I propose you look into how to run these in parallel, possibly each in a transaction and set your connection pool high enough.

@ahnpnl setupFiles helps removing the duplication :)

@phikes yes thats the problem i have test that can run parallel using transaction in database but don't know how to setup it properly in jest? By the i mean only one time creation of connection pool and one time close after all test suites finish

Figured this out today, just write your setup and teardown modules in Javascript and then import your Typescript modules, they will be transpiled on the fly.

Example:

sequelize.ts

import { Sequelize } from 'sequelize';

export default new Sequelize(process.DATABASE_URL);

setup.js

require('dotenv').config();

const sequelize = require('./sequelize');
// remember importing your models so sequelize know about them.
const models = require('./models');

module.export = async () => {
  await sequelize.sync();
};

Figured this out today, just write your setup and teardown modules in Javascript and then import your Typescript modules, they will be transpiled on the fly.

This works, thanks so much.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

japhar81 picture japhar81  Â·  3Comments

ozum picture ozum  Â·  4Comments

remcohaszing picture remcohaszing  Â·  4Comments

stangerjm picture stangerjm  Â·  4Comments

Vinnl picture Vinnl  Â·  3Comments