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

global beforeAll #3832

Closed
shai32 opened this issue Jun 15, 2017 · 37 comments
Closed

global beforeAll #3832

shai32 opened this issue Jun 15, 2017 · 37 comments

Comments

@shai32
Copy link

shai32 commented Jun 15, 2017

is there any way for a global beforeAll?

I can define beforeAll in each test file but this will run the beforeAll once for each test file.

is there any global beforeAll that will be run once and finishes before the first test start?

@ashtonsix
Copy link
Contributor

ashtonsix commented Jun 15, 2017

Have you seen setupFiles?

For reference my project uses setupFiles like this:

package.json

{
  "jest": {
    "setupFiles": [
      "./private/mocks/runtime.js"
    ]
  }
}

./private/mocks/runtime.js

global.__meteor_runtime_config__ = {ROOT_URL: 'localhost'};

FYI Stack Overflow might be a better place for this kind of question. (question about usage instead of a bug report / feature request).

Also I've unsubscribed from this issue so won't get any notifications if you reply.

@cpojer cpojer closed this as completed Jun 15, 2017
@shai32
Copy link
Author

shai32 commented Jun 15, 2017

I am using create-react-app.
and setupFiles run again for each test file.

giving an answer that isn't correct and closing an issue after it. bravo!

@Negan1911
Copy link

@cpojer @ashtonsix I don't think that this should be closed and the answer is not correct, both setupFiles or setupTestFrameworkScriptFile runs for each test suite, so there is not a "global" beforeAll where we can set thinks like cleaning a test db before testing on

@SimenB
Copy link
Member

SimenB commented Jun 27, 2017

You can have a pretest in package.json?

@ashtonsix
Copy link
Contributor

ashtonsix commented Jun 27, 2017

@Negan1911 - maybe, but it's difficult to tell what's meant in the OP. You could consider creating a second issue if you think it's a useful feature & want to bring more clarity to this feature request?

@v1adko
Copy link

v1adko commented Aug 22, 2017

@cpojer @ashtonsix If I understand it correctly, currently it's not possible to have global setup and teardown like discussed here in Mocha.
The use-case that I (and probably the OP) have is that I want to run a server and only then all of my integration tests (and probably after all of them have run drop the test DB).
Do you have any advice or best-practices for doing this?
What I've found is people mostly telling to startup a server and close it for each test suite in "local" beforeAll/afterAll, e.g. here by @kentcdodds, but implies a lot of duplication, no?

@joaomilho
Copy link

+1 on having a global setup, in my use case I wanna run a proxy server as well

@danpalmer
Copy link

@ashtonsix for what it’s worth, the OP was clear in my opinion. I’d like this issue to be re-opened.

@cpojer
Copy link
Member

cpojer commented Sep 1, 2017

You can create a custom jest-environment, see jest-environment-node or jest-environment-jsdom and subclass it. It should allow you to set up the environment in any way you like. We discussed adding an async hook for this also, and I'm happy to accept PRs for it.

@wubzz
Copy link

wubzz commented Sep 8, 2017

+1 Wanted to try jest coming from mocha and was impressed with the ease of jest-codemods and the docs, up until I got stuck with this same issue.

Every first describe of each seperate file was taking surprisingly long to execute. Turns out the setup was - as explained by previous comments - run once per file, resulting in tons of unecessary time consuming operations such as DROP DATABASE, CREATE DATABASE, and more.

Unfortunately there's no workaround in the docs (which in turn brought me here) except to run node setup.js && jest which is not ideal..

@tuomash
Copy link

tuomash commented Sep 11, 2017

+1 for global setup. Like other users, I'd like to setup and tear down the app/DB only once.

@RaulTsc
Copy link

RaulTsc commented Dec 13, 2017

+1

@SimenB
Copy link
Member

SimenB commented Dec 13, 2017

Fixed in #4506

@btav
Copy link

btav commented Dec 14, 2017

There are the following jest options globalSetup and globalTeardown. https://facebook.github.io/jest/docs/en/configuration.html#globalsetup-string

I have tried using globalSetup, however I keep on getting the following error.. I think this option might do the trick @shai32. However, I can't seem to get it working 🤣 ...

"jest": "^21.2.1"
 "jest": {
    "globalSetup": "./jest-config.js"
  }
  
● Validation Warning:

  Unknown option "globalSetup" with value "./jest-setup.js" was found.
  This is probably a typing mistake. Fixing it will remove this message.

  Configuration Documentation:
  https://facebook.github.io/jest/docs/configuration.html

@SimenB
Copy link
Member

SimenB commented Dec 14, 2017

It has not been released yet. Jest 22 incoming any day now 🙂

@mathieumg
Copy link
Contributor

Fixed in #4506

I know it's linked therein, but for anyone looking: #4716

@xfumihiro
Copy link
Contributor

@btav that's 2 bugs 😓

  1. you have to use absolute path for now, or ("../../../~ root ~")
  2. the validation warnings are false positive

see here
also #5093

@xfumihiro
Copy link
Contributor

bugs should be fixed with #5095 #5096

@zwhitchcox
Copy link

zwhitchcox commented Feb 6, 2018

Can this be used to set a global variable? I tried, but it doesn't work....is this by design?

My use case is I have a custom log function that I want to set globally. I tried _setup.test.js, but my global variables aren't transferred.

@thymikee
Copy link
Collaborator

thymikee commented Feb 6, 2018

@tdenovan
Copy link

Sometimes it might be useful to share a global variable that is setup via an async function. For example, it would be useful to setup the puppeteer browser once in globalSetup and then spawn a new page in each test / test suite.

@pyrossh
Copy link

pyrossh commented Feb 14, 2018

@tdenovan Thats exactly what I'm trying to do right now. But it doesn't seem to work. I've done this in mocha before and it was a breeze, but with jest I think I need to find out other ways.
This is my jest config

"jest": {
    "verbose": true,
    "testEnvironment": "node",
    "globalSetup": "<rootDir>/scripts/testSetup.js",
    "globalTeardown": "<rootDir>/scripts/testTeardown.js"
  },
// globalSetup.js
module.exports = async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  bot = Bot(browser, page);
  await bot.goto(bot.baseUrl);
  global.bot = bot;
}

But I'm not able to access bot in my test cases.

@pyrossh
Copy link

pyrossh commented Feb 14, 2018

GGWP! Just solved it.

"e2e": "jest --testRegex '.*.e2e.js'"
// globalTeardown.js
module.exports = async () => {
  if (process.testSetup) {
    process.testSetup.bot.close();
  }
}
 process.testSetup = { bot };
// and then im my tests
const { bot } = process.testSetup;

and anyone is wondering what bot is,

const Bot = (browser, page) => ({
  browser: browser,
  page: page,
  baseUrl: 'http://localhost:4000',
  user: {
    name: faker.name.findName(),
    email: faker.internet.email(),
    password: 'Test@123',
  },
  oldUser: {
    email: 'test1@mailinator.com',
    password: 'Test@123',
  },
  clearSession: async () => {
    await page.evaluate(() => sessionStorage.clear());
  },
  goto: async (url) => {
    await page.goto(url);
  },
  clickButton: async (id) => {
    await page.waitForSelector(id);
    await page.click(id);
  },
  checkText: async (expect, id, text) => {
    await page.waitForSelector(id);
    const elText = await page.$eval(id, el => el.innerHTML);
    expect(elText).toContain(text);
  },
  type: async (id, text) => {
    await page.waitForSelector(id);
    await page.$eval(id, el => el.value = '');
    await page.type(id, text);
  },
  wait: async () => {
    await page.waitForNavigation();
  },
  close: () => {
    browser.close();
  },
});

@SimenB
Copy link
Member

SimenB commented Feb 14, 2018

There is a guide for puppeteer on the website: https://facebook.github.io/jest/docs/en/puppeteer.html

@tdenovan
Copy link

Yep but that suggests that setting a global in the globalSetup async method is possible, which per the above it doesn’t seem to be b

@pyrossh
Copy link

pyrossh commented Feb 14, 2018

@SimenB ahh.. man... I was trying to figure this out and also was in the jest docs for quite a long time and never noticed that section. Waste of my time.

@ovidiu-lapadus
Copy link

ovidiu-lapadus commented Mar 6, 2018

I have an issue where the global objects I set in globalSetup are not available if there are multiple test suites ran in parallel (this is by default). Running a single suite test the objects are available or if I set --runInBand to run tests serially. How can I get access to the variables I set in globalSetup if tests run in parallel?
I tried the example used above (using process object) and I also tried the version where I am using a custom TestEnvironment but with no luck:

const PuppeteerJsdomEnvironment = require('jest-puppe-shots/lib/jsdom-environment');

class JestPuppeShotsEnv extends PuppeteerJsdomEnvironment {

  async setup(config) {
    await super.setup(config);
    const { allThemesCss } = global;

    // make the allThemesCss object available in test suites
    Object.assign(this.global, {
      allThemesCss
    });
  }
}

module.exports = JestPuppeShotsEnv;

This is getting the allThemesCss from the globalSetup.js and is making sure it is passing down to test suites.

@cellis
Copy link

cellis commented Mar 12, 2018

@ovidiu-lapadus I was able to get globalSetup working by using process instead of global. It works with and without --runInBand. E.g.

// globalSetup.js
module.exports = async () => {
  process.FOOT = 'BALL';
};
// globalTeardown.js
module.exports = async () => {
  console.log(process.FOOT) // BALL 
};
// some.test.js
it('expects 1 to be 1', () => {
    expect(1).toBe(1);
     console.log(process.FOOT); // BALL
});

And to the jest team, I'm not sure why globals are undefined in tests ( babel-jest 22.2.2 ), but defined in the globalTeardown.js. Perhaps it's a bug. For now I'll just use process. Cheers!

@kalutheo
Copy link

Thanks @cellis you saved my day ! I've been banging my head against a wall trying to understand why global.FOO was not working. process.FOO does the trick :-)

@cellis
Copy link

cellis commented Mar 23, 2018

@kalutheo There are a couple caveats to using process.FOO. First, I don't think you can do deeply nested variables on process or process.env. I figured out an even better way to get globals working, but was I waiting to post it. What I've done, is use the jest-environment package to create my own dbEnvironment. In there, I check for global dbs to be defined and if not, I redefine them. The database environment is only run for db tests, I have another config for frontend only tests. That way, I don't waste time running db tests for every frontend change. Secondly, I have a way of setting up multiple "replica" dbs that are always hot -- you don't need to migrate or dump them on every jest run, as I migrate them along with the dev db ( you can see glimpses of this in the gist I've shared ), which allows the tests to run even faster. I setup a pool of these replicas so I can get maximum parellelism in the tests. It is kind of documented in the jest documentation, but not explained well enough. Anyways, here's the gist: https://gist.github.com/cellis/08cc332dacf9a548005e8cf35d4b16e2

@cellis
Copy link

cellis commented Mar 23, 2018

@ovidiu-lapadus Upon closer inspection I think perhaps your problem is that you called super.setup() before assigning your globals. Please see the gist I posted above for a working solution.

@kalutheo
Copy link

@cellis thanks for these valuable informations. I will try with a custom environment like you described

@deser
Copy link

deser commented Jul 31, 2018

Guys, isn't globalSetup supposed to include here all heave tasks like babel-polyfill, combine with chai, require jest-extended ?
Seems that globalSetup works far differently than setupTestFrameworkScriptFile and what worked there doesn't work in globalSetup.
I know, that every jest test case is run in his snadboxed environment but doin't things in setupTestFrameworkScriptFile makes test to run veeeeeeeeeeery slow.

Mocha: 9s
Jest: 60s, in watch mode: 170s-200s

@deser

This comment has been minimized.

@SimenB
Copy link
Member

SimenB commented Oct 17, 2018

Using process is a hack that will probably break (it's a bug).

You probably want to follow #7184

@evandrocoan
Copy link

evandrocoan commented Apr 16, 2020

This is no global beforeAll() all as asked on the question, but with this, you easily avoid code duplication. You can create a node environment, which will be setup for all your tests files: https://stackoverflow.com/a/61260044/4934640


Update

I just find out I can set an environment variable on globalSetup, meaning I can share the server address between the tests cases/suites/files: #7184 (comment)

@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.
Labels
None yet
Projects
None yet
Development

No branches or pull requests