Skip to content

Commit

Permalink
feat(jest-core): add support for globalSetup and globalTeardown w…
Browse files Browse the repository at this point in the history
…ritten in ESM (#11267)
  • Loading branch information
aledalgrande committed Apr 15, 2021
1 parent 7d7f937 commit 1be8d73
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -16,6 +16,7 @@
- `[jest-core]` Run failed tests interactively the same way we do with snapshots ([#10858](https://github.com/facebook/jest/pull/10858))
- `[jest-core]` more `TestSequencer` methods can be async ([#10980](https://github.com/facebook/jest/pull/10980))
- `[jest-core]` Add support for `testSequencer` written in ESM ([#11207](https://github.com/facebook/jest/pull/11207))
- `[jest-core]` Add support for `globalSetup` and `globalTeardown` written in ESM ([#11267](https://github.com/facebook/jest/pull/11267))
- `[jest-environment-node]` Add AbortController to globals ([#11182](https://github.com/facebook/jest/pull/11182))
- `[@jest/fake-timers]` Update to `@sinonjs/fake-timers` to v7 ([#11198](https://github.com/facebook/jest/pull/11198))
- `[jest-haste-map]` Handle injected scm clocks ([#10966](https://github.com/facebook/jest/pull/10966))
Expand Down
11 changes: 11 additions & 0 deletions e2e/__tests__/globalSetup.test.ts
Expand Up @@ -8,6 +8,7 @@
import {tmpdir} from 'os';
import * as path from 'path';
import * as fs from 'graceful-fs';
import {onNodeVersions} from '@jest/test-utils';
import {
cleanup,
createEmptyPackage,
Expand Down Expand Up @@ -192,3 +193,13 @@ test('properly handle rejections', () => {
expect(stderr).toContain('Error: Jest: Got error running globalSetup');
expect(stderr).toContain('reason: undefined');
});

onNodeVersions('^12.17.0 || >=13.2.0', () => {
test('globalSetup works with ESM modules', () => {
const {exitCode} = runJest('global-setup-esm', [`--no-cache`], {
nodeOptions: '--experimental-vm-modules --no-warnings',
});

expect(exitCode).toBe(0);
});
});
11 changes: 11 additions & 0 deletions e2e/__tests__/globalTeardown.test.ts
Expand Up @@ -8,6 +8,7 @@
import {tmpdir} from 'os';
import * as path from 'path';
import * as fs from 'graceful-fs';
import {onNodeVersions} from '@jest/test-utils';
import {createDirectory} from 'jest-util';
import {cleanup, runYarnInstall} from '../Utils';
import runJest, {json as runWithJson} from '../runJest';
Expand Down Expand Up @@ -131,3 +132,13 @@ test('globalTeardown throws with named export', () => {
`globalTeardown file must export a function at ${teardownPath}`,
);
});

onNodeVersions('^12.17.0 || >=13.2.0', () => {
test('globalTeardown works with ESM modules', () => {
const {exitCode} = runJest('global-teardown-esm', [`--no-cache`], {
nodeOptions: '--experimental-vm-modules --no-warnings',
});

expect(exitCode).toBe(0);
});
});
20 changes: 20 additions & 0 deletions e2e/global-setup-esm/__tests__/test.js
@@ -0,0 +1,20 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import os from 'os';
import path from 'path';
import fs from 'graceful-fs';
import greeting from '../';

const DIR = path.join(os.tmpdir(), 'jest-global-setup-esm');

test('should exist setup file', () => {
const files = fs.readdirSync(DIR);
expect(files).toHaveLength(1);
const setup = fs.readFileSync(path.join(DIR, files[0]), 'utf8');
expect(setup).toBe('setup');
});
8 changes: 8 additions & 0 deletions e2e/global-setup-esm/index.js
@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

export default 'hello!';
8 changes: 8 additions & 0 deletions e2e/global-setup-esm/package.json
@@ -0,0 +1,8 @@
{
"type": "module",
"jest": {
"testEnvironment": "node",
"globalSetup": "<rootDir>/setup.js",
"transform": {}
}
}
24 changes: 24 additions & 0 deletions e2e/global-setup-esm/setup.js
@@ -0,0 +1,24 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import crypto from 'crypto';
import os from 'os';
import path from 'path';
import fs from 'graceful-fs';
import jestUtil from 'jest-util';

const {createDirectory} = jestUtil;

const DIR = path.join(os.tmpdir(), 'jest-global-setup-esm');

export default function () {
return new Promise(resolve => {
createDirectory(DIR);
const fileId = crypto.randomBytes(20).toString('hex');
fs.writeFileSync(path.join(DIR, fileId), 'setup');
resolve();
});
}
17 changes: 17 additions & 0 deletions e2e/global-teardown-esm/__tests__/test.js
@@ -0,0 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import os from 'os';
import path from 'path';
import fs from 'graceful-fs';
import greeting from '../';

const DIR = path.join(os.tmpdir(), 'jest-global-teardown-esm');

test('should not exist teardown file', () => {
expect(fs.existsSync(DIR)).toBe(false);
});
8 changes: 8 additions & 0 deletions e2e/global-teardown-esm/index.js
@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

export default 'hello!';
8 changes: 8 additions & 0 deletions e2e/global-teardown-esm/package.json
@@ -0,0 +1,8 @@
{
"type": "module",
"jest": {
"testEnvironment": "node",
"globalTeardown": "<rootDir>/teardown.js",
"transform": {}
}
}
24 changes: 24 additions & 0 deletions e2e/global-teardown-esm/teardown.js
@@ -0,0 +1,24 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import crypto from 'crypto';
import os from 'os';
import path from 'path';
import fs from 'graceful-fs';
import jestUtil from 'jest-util';

const {createDirectory} = jestUtil;

const DIR = path.join(os.tmpdir(), 'jest-global-teardown-esm');

export default function () {
return new Promise(resolve => {
createDirectory(DIR);
const fileId = crypto.randomBytes(20).toString('hex');
fs.writeFileSync(path.join(DIR, fileId), 'teardown');
resolve();
});
}
44 changes: 34 additions & 10 deletions packages/jest-core/src/runGlobalHook.ts
Expand Up @@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import {pathToFileURL} from 'url';
import * as util from 'util';
import pEachSeries = require('p-each-series');
import {createScriptTransformer} from '@jest/transform';
Expand Down Expand Up @@ -60,18 +61,41 @@ export default async ({
await globalModule(globalConfig);
});
} catch (error) {
if (util.types.isNativeError(error)) {
error.message = `Jest: Got error running ${moduleName} - ${modulePath}, reason: ${error.message}`;
if (error && error.code === 'ERR_REQUIRE_ESM') {
const configUrl = pathToFileURL(modulePath);

throw error;
}
// node `import()` supports URL, but TypeScript doesn't know that
const importedConfig = await import(configUrl.href);

if (!importedConfig.default) {
throw new Error(
`Jest: Failed to load ESM transformer at ${modulePath} - did you use a default export?`,
);
}

const globalModule = importedConfig.default;

if (typeof globalModule !== 'function') {
throw new TypeError(
`${moduleName} file must export a function at ${modulePath}`,
);
}

await globalModule(globalConfig);
} else {
if (util.types.isNativeError(error)) {
error.message = `Jest: Got error running ${moduleName} - ${modulePath}, reason: ${error.message}`;

throw error;
}

throw new Error(
`Jest: Got error running ${moduleName} - ${modulePath}, reason: ${prettyFormat(
error,
{maxDepth: 3},
)}`,
);
throw new Error(
`Jest: Got error running ${moduleName} - ${modulePath}, reason: ${prettyFormat(
error,
{maxDepth: 3},
)}`,
);
}
}
});
}
Expand Down

0 comments on commit 1be8d73

Please sign in to comment.