Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support jest config globalSetup and globalTeardown #411

Closed
yss14 opened this issue Jan 5, 2018 · 32 comments
Closed

Support jest config globalSetup and globalTeardown #411

yss14 opened this issue Jan 5, 2018 · 32 comments

Comments

@yss14
Copy link

yss14 commented Jan 5, 2018

  • 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
@AamuLumi
Copy link

AamuLumi commented Jan 5, 2018

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.

@kulshekhar
Copy link
Owner

@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.

@AamuLumi
Copy link

AamuLumi commented Jan 6, 2018

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 ! :)

@yss14
Copy link
Author

yss14 commented Jan 6, 2018

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

@yss14
Copy link
Author

yss14 commented Jan 8, 2018

@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.

@AamuLumi
Copy link

AamuLumi commented Jan 8, 2018

"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.

@ssbarbee
Copy link

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

@AamuLumi
Copy link

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. :)

@WillAvudim
Copy link

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 jestjs/jest#5164 (comment).

@chanlito
Copy link

why is this closed, has this been solved?

@timshannon
Copy link

FYI, the upstream issue with Jest is here: jestjs/jest#5164

@hugo-dlb
Copy link

hugo-dlb commented Jan 12, 2019

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.

// tests/conversation.ts
export const conversationModule = function () {
    test('create a conversation', async (done) => {
        const user1: User = await AuthenticationService.registerUser('user1', 'test1', 'user1@gmail.com');
        const user2: User = await AuthenticationService.registerUser('user2', 'test2', 'user2@gmail.com');

        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();
});

@yss14
Copy link
Author

yss14 commented Feb 6, 2019

With Jest 24, this is finally supported ;)
jestjs/jest#7562

@viT-1
Copy link

viT-1 commented Oct 31, 2019

@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'

@phikes
Copy link

phikes commented Nov 13, 2019

@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.

@shirshak55
Copy link

@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 :(

@shirshak55
Copy link

shirshak55 commented Jan 7, 2020

@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 :(?

@phikes
Copy link

phikes commented Jan 10, 2020

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

@shirshak55
Copy link

@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 :(

@ahnpnl
Copy link
Collaborator

ahnpnl commented Jan 10, 2020

Does setupFileAfterEnv help ?

@phikes
Copy link

phikes commented Jan 10, 2020

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.

@shirshak55
Copy link

@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

@renatoalencar
Copy link

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();
};

@gengjiawen
Copy link

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.

@douglas-treadwell
Copy link

douglas-treadwell commented May 30, 2021

Hmm. I'm not sure why this worked for you and not for me, @renatoalencar. I'm doing pretty much the same thing, but rather than transpiling the require'd modules on the fly, ts-jest just complains SyntaxError: Unexpected token 'export'. It seems it is not transpiling the require'd modules in my case.

    "jest": "^27.0.3",
    "ts-jest": "^27.0.1",
    "ts-node": "^9.1.1",

@douglas-treadwell
Copy link

douglas-treadwell commented May 30, 2021

Thanks to @Ericnr's comment in jestjs/jest#5164, it seems the fix for me was to add this as the first line in globalSetup.js:

require('ts-node').register({ transpileOnly: true });

Update: the line above fixed the compilation error, but for some reason the test code was still acting as if the global setup and teardown had not executed. So I kept looking and found @ecklf's suggestion on #1391. Using setupFilesAfterEnv works without needing to use ts-node/register, the setup file can be written in TypeScript, and my test code appears to be working as expected with the global environment configured as expected.

This StackOverflow question may also be interesting to others here: https://stackoverflow.com/questions/62470047/typeorm-connection-default-was-not-found-when-connection-is-created-in-jest-gl.

If the setup/teardown of the database creates significant performance problems, a solution mentioned in the StackOverflow page is to create a test file that imports all the other tests, establishes the DB connection once and tears it down once. That's basically the approach @hugo-dlb mentioned here previously.

@renatoalencar
Copy link

Hmm. I'm not sure why this worked for you and not for me, @renatoalencar. I'm doing pretty much the same thing, but rather than transpiling the require'd modules on the fly, ts-jest just complains SyntaxError: Unexpected token 'export'. It seems it is not transpiling the require'd modules in my case.

    "jest": "^27.0.3",
    "ts-jest": "^27.0.1",
    "ts-node": "^9.1.1",

That's probably because of the new major release. Glad you found another solution.

@clintonmedbery
Copy link

Adding my two cents. I used setUpFilesAfterEnv but also had to add a jest timeout to make it work:

beforeAll(async () => {
  // This timeout need to be here otherwise jest moves on after a few seconds and does not
  // await the TestServer with no warning.
  jest.setTimeout(20000);
  await new TestServer();
});

@daweimau
Copy link

daweimau commented Feb 6, 2022

it seems the fix for me was to add this as the first line in globalSetup.js:

Amazingly, this works for me-- but only for globalSetup, not for globalTeardown. More crappy errors on the latter.

setupFilesAfterEnv seems the wrong direction to me, but who knows where this journey will end

@ranshemt
Copy link

ranshemt commented Oct 26, 2022

For globalSetup only, registering ts-node helped.
But when I added globalTeardown, the teardown didn't work with a similar issue.

For some reason, if I add the ts-node only in globalTeardown - both files work.
If you use absolute imports, add tsconfig-paths register in both files.

https://stackoverflow.com/a/74206721/11136074

@elijaholmos
Copy link

can this be reopened? still no native support

@ahnpnl
Copy link
Collaborator

ahnpnl commented Dec 12, 2022

This issue is not in the scope of this repo. This repo is only performing code transpilation. If jest doesn’t ask ts-jest to transform codes, you will run into issues. You need to check your Jest config, and also you can ask in Jest Discord for help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests