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

Make "globalSetup" and "globalTeardown" work together with "transform" #5164

Closed
opasno opened this issue Dec 23, 2017 · 39 comments · Fixed by #7562
Closed

Make "globalSetup" and "globalTeardown" work together with "transform" #5164

opasno opened this issue Dec 23, 2017 · 39 comments · Fixed by #7562

Comments

@opasno
Copy link

opasno commented Dec 23, 2017

Do you want to request a feature or report a bug?
Feature

What is the current behavior?
Modules defined in globalSetup and globalTeardown are not being transformed as defined in transform configuration entry.

What is the expected behavior?
Modules should be transformed.

Please provide your exact Jest configuration and mention your Jest, node,
yarn/npm version and operating system.

"jest": {
        "globalSetup": "<rootDir>/test/setup.ts",
        "globalTeardown": "<rootDir>/test/teardown.ts",
        "collectCoverage": true,
        "mapCoverage": true,
        "transform": {
            "^.+\\.ts?$": "ts-jest"
        },
        "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$",
        "moduleFileExtensions": [
            "ts",
            "js",
            "json",
            "node"
        ]
    }

jest 22.0.4
ts-jest 22.0.0
node 8.9.2
npm 5.5.1
OS Windows 10

@SimenB
Copy link
Member

SimenB commented Dec 23, 2017

I'm not sure we can do this, since the whole point of global{Setup,Teardown} is that it runs before we create a runtime (which is what contains our require which passes stuff through the transforms).

@cpojer thoughts on this?

@cpojer
Copy link
Member

cpojer commented Dec 24, 2017

I think we should transform it if we can, but I’m not sure right now what code changes that would entail. It may make sense to split the transformer into a separate package, something I wanted to do for a while.

@glasser
Copy link

glasser commented Feb 6, 2018

Is there a workaround here? I'd like to be able to load some support code in globalSetup that uses ES6 modules and I'd prefer to not have to rewrite all of it back to requires/exports.

@SimenB
Copy link
Member

SimenB commented Feb 6, 2018

No current workaround that I know of, sorry. PR welcome here, though 🙂

@sourcec0de
Copy link

@glasser I'm currently working around this issue by using babel-register and babel-pollyfill at the top of my jest.config.js.

yarn add babel-register babel-pollyfil
const { readFileSync } = require('fs')
const babelConfig = JSON.parse(readFileSync('./.babelrc', 'utf8'))

require('babel-register')(babelConfig)
require('babel-polyfill')

const { join } = require('path')

const ROOT = process.cwd()
// const TESTS = join(ROOT, '__tests__')
const JEST_ENV = join(ROOT, '__jest_env__')

module.exports = {
  verbose: true,
  transform: {
    '^.+\\.jsx?$': 'babel-jest'
  },
  globalSetup: join(JEST_ENV, 'setup.js'),
  globalTeardown: join(JEST_ENV, 'teardown.js'),
  testEnvironment: join(JEST_ENV, 'server-environment.js')
}

@keroxp
Copy link

keroxp commented Feb 28, 2018

@opasno You seem to be using typescript, so try this method. In my case, I could easily solve the problem. I do not know if this method is useful in all cases, but I did the following things.

  • write setup/teardown code by pure js that is compatible with your runtime even if you are using another altjs language.
  • require suitable register code that you are using (e.g. like babel/register, ts-node/register

code will be like this:
__tests__/globalSetup.js, db/index.ts

require("ts-node/register");
const {db} = require("../db");
module.exports = async function () {
  return db.setup();
};

Note that entire setup/teardown codes will be executed in non-jest environment, so all modules and objects related to Jest can not be referred while setup/teardown. However, It is enough to do setup/teardown.

@isaachinman
Copy link

Is anybody working on a PR for this already? Just encountered this issue and took me awhile to realise what was happening and track down this issue. At the very least, maybe the docs could be updated to indicate that transforms will not take place on globalSetup due to it being outside a jest runtime.

@WillAvudim
Copy link

WillAvudim commented Mar 25, 2018

If anyone runs into this, you can trivially work around by performing these two steps.

  1. Specify in jest.json:
"globalSetup": "<rootDir>/test_setup/global_setup_hook.js"
  1. Create a .js file 'global_setup_hook.js' and invoke your typescript code from there:
require("ts-node/register");

// If you want to reference other typescript modules, do it via require:
const my_typescript_module = require('my_typescript_module');

module.exports = async function () {
  // Call your initialization methods here.
  await my_typescript_module.Initialize();
  return null;
};

This assumes that you have "ts-node": "^5.0.1" in your package.json. No changes required in jest or ts-jest for this to work.

@KhaledSakr
Copy link

If anyone is working on a PR for this, keep in mind that testEnvironment files are not transpiled either.

@tachang
Copy link

tachang commented May 9, 2018

Is this the same with setupTestFrameworkScriptFile? It is not transpiled?

@isaachinman
Copy link

@tachang Most likely. It would be extremely easy to test, why don't you do that yourself?

@aljazerzen
Copy link

@WillAvudim your solution works greatly :) I have shortened it to a two-liner file:

setup_hook.js:

require("ts-node/register");
module.exports = require('./setup').default;

This works, because I have the setup file declared with default export function:

setup.ts:

import { anything } from 'you-want';

export default async function() {
  // do all the setup you want in TypeScript
}

I hope someone finds this useful.

@SimenB
Copy link
Member

SimenB commented Aug 14, 2018

@tachang setupTestFrameworkScriptFile should work as it's required through the runtime: https://github.com/facebook/jest/blob/b60f44a9829b51bc4bc387dbef8d7d37de3cc7e6/packages/jest-jasmine2/src/index.js#L129-L131 & https://github.com/facebook/jest/blob/b60f44a9829b51bc4bc387dbef8d7d37de3cc7e6/packages/jest-circus/src/legacy_code_todo_rewrite/jest_adapter.js#L76-L78


I'm still not sure how to solve this. One thing is to transpile the setup file itself (that can be done pretty easily), but to also transpile files required from it forces us to implement require or hook into node's own require. The first is difficult since it's part of jest-runtime which is not created yet. The second since we should use something like https://www.npmjs.com/package/pirates (which is what babel-register uses) which feels... invasive. Might be the correct solution though.

Anybody wanna create a PoC using https://www.npmjs.com/package/pirates?

@SimenB
Copy link
Member

SimenB commented Aug 14, 2018

We could also print a pretty error if we get a syntax error saying we don't transform. That's probably better than what we have now

@binygal
Copy link
Contributor

binygal commented Aug 20, 2018

Should we always bail if there's a syntax error in the global setup, or should we respect bail flag in the config?

@kelly-tock
Copy link

would love to see this. I am using both babel and typescript, and not being able to use es6 for some global setup in test files in a centralized manner kind of sucks. is another workaround just importing the function in the tests you need as well? not as convenient but it would be transpiled right?

@binygal
Copy link
Contributor

binygal commented Sep 12, 2018

@SimenB What is the approach we decided to go with?

@riglar
Copy link

riglar commented Oct 20, 2018

I amended @WillAvudim example to support tsconfig-paths

yarn add --dev tsconfig-paths

require("ts-node/register");
require('tsconfig-paths/register');

// If you want to reference other typescript modules, do it via require:
const my_typescript_module = require('my_typescript_module');

module.exports = async function () {
  // Call your initialization methods here.
  await my_typescript_module.Initialize();
  return null;
};

@shai32
Copy link

shai32 commented Nov 4, 2018

I don't use typescript, is there another solution?

@ezze
Copy link

ezze commented Nov 4, 2018

@shai32, you can do the same with @babel/register and @babel/polyfill:

require('@babel/register');
require('@babel/polyfill');
module.exports = require('./setup').default;

@SimenB SimenB added this to the Jest 24 milestone Jan 18, 2019
@SimenB
Copy link
Member

SimenB commented Jan 29, 2019

This is available in Jest 24

@donedgardo
Copy link

Are https://jestjs.io/docs/en/configuration.html#modulenamemapper-object-string-string concidered if using global setup with typescript

@SimenB
Copy link
Member

SimenB commented Apr 6, 2019

No, jest does not control the resolution algorithm in this case

@AlvSovereign
Copy link

AlvSovereign commented May 7, 2019

@glasser I'm currently working around this issue by using babel-register and babel-pollyfill at the top of my jest.config.js.

yarn add babel-register babel-pollyfil
const { readFileSync } = require('fs')
const babelConfig = JSON.parse(readFileSync('./.babelrc', 'utf8'))

require('babel-register')(babelConfig)
require('babel-polyfill')

const { join } = require('path')

const ROOT = process.cwd()
// const TESTS = join(ROOT, '__tests__')
const JEST_ENV = join(ROOT, '__jest_env__')

module.exports = {
  verbose: true,
  transform: {
    '^.+\\.jsx?$': 'babel-jest'
  },
  globalSetup: join(JEST_ENV, 'setup.js'),
  globalTeardown: join(JEST_ENV, 'teardown.js'),
  testEnvironment: join(JEST_ENV, 'server-environment.js')
}

Small typo here on your yarn commands.

yarn add babel-register babel-polyfill

@MichaelBitard
Copy link

MichaelBitard commented Jul 8, 2019

Based on @AlvSovereign and @sourcec0de work, adding

const { readFileSync } = require('fs');
const babelConfig = require('./babel.config.js');
require('@babel/register')(babelConfig);

in your jest.config.js worked for me

@SimenB
Copy link
Member

SimenB commented Jul 8, 2019

No need for workarounds, the feature has been implemented

@MichaelBitard
Copy link

You said it was implemented in jest 24, but we are using jest 24.8.0 and if I don't do that, it does not work. Am i missing something?

Also, in the documentation, this is still present:

Note: While code transformation is applied to the linked setup-file, Jest will not transform any code in node_modules. This is due to the need to load the actual transformers (e.g. babel or typescript) to perform transformation.

@SimenB
Copy link
Member

SimenB commented Jul 8, 2019

Transforming node_modules is not the same as Make "globalSetup" and "globalTeardown" work together with "transform", which is what this issue is about.

EDIT: We also transform everything not ignore via transformIgnorePatterns since 24.6: #8143. It should have updated the docs, though

@MichaelBitard
Copy link

Thanks.
Indeed these 2 subjects got mixed in this issue, that's why I replied in it, sorry.

I was not able to make it work using transformIgnorePatterns: []. I'll try some other things and if I can't find a solution, maybe I'll open a new issue.

@lanistor
Copy link

Variable added to global in global{Setup,Teardown} cannot be used in test cases?
I add a key to global in globalSetup file, but i cannot get it from my test cases.
And it seems that, there're two different globals, the first one is instanceof NodeJS.Global, howere the second one is Window.

// globalSetup.ts
module.exports = async () => {
  (global as any).aaa = 111;
}

// testcase.test.ts
console.log('>>global', typeof global, (global as any).aaa);

@jeysal
Copy link
Contributor

jeysal commented Aug 21, 2019

@vifird that is correct, each test runs in its own sandboxed environment.

@lanistor
Copy link

lanistor commented Aug 21, 2019

@jeysal So is there a way to add global settings? except "globals" field in jest's configuration.

@SimenB
Copy link
Member

SimenB commented Aug 21, 2019

Correct. We might add a way to send variables from globalSetup to tests (there are some issues about it, but I'm currently on mobile) but that's not in place yet

@hereiscasio
Copy link

@SimenB
i still can't use the import statement like import vue from 'vue' in the file which globalSetup point to

i have an error on my terminal without any extra information

Determining test suites to run...

SyntaxError: Unexpected identifier

Did i missing something ?
And what are u meaning about "This is available in Jest 24" ?
i thought i don't need to config anything and i can have such feature


below is my jest.config.js

module.exports = {
	globalSetup: './tests/unit/run-once-before-all-files.js',

	moduleFileExtensions: [
		'js',
		'jsx',
		'json',
		'vue'
	],
	transform: {
		'^.+\\.vue$': 'vue-jest',
		'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
		'^.+\\.jsx?$': 'babel-jest'
	},

	transformIgnorePatterns: [
		'/node_modules/',
		'/public/',
		'/__mocks__/',
		'/api/',
		'/src/assets/',
		'tests/e2e/'
	],
	moduleNameMapper: {
		'^@/(.*)$': '<rootDir>/src/$1'
	},
	snapshotSerializers: [
		'jest-serializer-vue'
	],
	testMatch: [
		'**/tests/unit/**/*.test.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
	],
	testURL: 'http://localhost/',
	watchPlugins: [
		'jest-watch-typeahead/filename',
		'jest-watch-typeahead/testname'
	],
	'setupFiles': ['jest-canvas-mock']
}

@Ericnr
Copy link

Ericnr commented Oct 5, 2019

using Jest 24.9 and had to require('ts-node/register) to get it working too. I don't understand how this is available in Jest 24

@dmasterstempus
Copy link

I can confirm this is not working in 24.9. As a matter of fact, it only works up to 24.1 for me.

Related: #9041

@SimenB
Copy link
Member

SimenB commented Jan 14, 2020

Please open up new issues (with reproductions) if you have a regression to report - this old issue is not the place for it

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.