Skip to content

Commit

Permalink
Provide require.main property (#5618)
Browse files Browse the repository at this point in the history
* feat: provide `require.main` property

In tests `require.main` will be set to module from which the test are being executed.

* add integration test case

* use cross-platform regex in integration test

* update CHANGELOG.md

* remove unused imports
  • Loading branch information
zamotany authored and cpojer committed Feb 20, 2018
1 parent acb7f64 commit 4576dd4
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 7 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## master

### Features

* `[jest-runtime]` Provide `require.main` property set to module with test suite
([#5618](https://github.com/facebook/jest/pull/5618))

## 22.4.0

### Fixes
Expand Down
18 changes: 18 additions & 0 deletions integration-tests/__tests__/require_main.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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.
*
* @flow
*/

'use strict';

const runJest = require('../runJest');

test('provides `require.main` set to test suite module', () => {
const {stderr, stdout} = runJest('require-main');
expect(stdout).not.toMatch('No tests found');
expect(stderr).toMatch(/PASS __tests__(\/|\\+)loader\.test\.js/);
});
13 changes: 13 additions & 0 deletions integration-tests/require-main/__tests__/loader.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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.
*/
'use strict';

const loader = require('../loader');

test('loader should load a module', () => {
expect(loader('../example.js')).toBeTruthy();
});
8 changes: 8 additions & 0 deletions integration-tests/require-main/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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.
*/

module.exports = true;
11 changes: 11 additions & 0 deletions integration-tests/require-main/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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.
*/
const path = require('path');

module.exports = function load(moduleId) {
return require(path.join(path.dirname(require.main.filename), moduleId));
};
5 changes: 5 additions & 0 deletions integration-tests/require-main/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"jest": {
"testEnvironment": "node"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,14 @@ describe('Runtime', () => {
expect(exports.isManualMockModule).toBe(true);
});
});
it('provides `require.main` in mock', () =>
createRuntime(__filename).then(runtime => {
runtime._moduleRegistry[__filename] = module;
runtime.setMock(__filename, 'export_main', () => require.main, {
virtual: true,
});
const mainModule = runtime.requireMock(__filename, 'export_main');
expect(mainModule).toBe(module);
}));
});
});
11 changes: 11 additions & 0 deletions packages/jest-runtime/src/__tests__/runtime_require_module.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,17 @@ describe('Runtime requireModule', () => {
});
});
});
it('provides `require.main` to modules', () =>
createRuntime(__filename).then(runtime => {
runtime._moduleRegistry[__filename] = module;
[
'./test_root/modules_with_main/export_main.js',
'./test_root/modules_with_main/re_export_main.js',
].forEach(modulePath => {
const mainModule = runtime.requireModule(__filename, modulePath);
expect(mainModule).toBe(module);
});
}));

it('throws on non-existent @providesModule modules', () =>
createRuntime(__filename).then(runtime => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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.
*/

'use strict';

module.exports = require.main;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. 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.
*/

'use strict';

module.exports = require('./export_main');
34 changes: 27 additions & 7 deletions packages/jest-runtime/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ class Runtime {

localModule.paths = this._resolver.getModulePaths(dirname);
Object.defineProperty(localModule, 'require', {
value: this._createRequireImplementation(filename, options),
value: this._createRequireImplementation(localModule, options),
});

const transformedFile = this._scriptTransformer.transform(
Expand Down Expand Up @@ -678,18 +678,38 @@ class Runtime {
}

_createRequireImplementation(
from: Path,
from: Module,
options: ?InternalModuleOptions,
): LocalModuleRequire {
const moduleRequire =
options && options.isInternalModule
? (moduleName: string) => this.requireInternalModule(from, moduleName)
: this.requireModuleOrMock.bind(this, from);
? (moduleName: string) =>
this.requireInternalModule(from.filename, moduleName)
: this.requireModuleOrMock.bind(this, from.filename);
moduleRequire.cache = Object.create(null);
moduleRequire.extensions = Object.create(null);
moduleRequire.requireActual = this.requireModule.bind(this, from);
moduleRequire.requireMock = this.requireMock.bind(this, from);
moduleRequire.resolve = moduleName => this._resolveModule(from, moduleName);
moduleRequire.requireActual = this.requireModule.bind(this, from.filename);
moduleRequire.requireMock = this.requireMock.bind(this, from.filename);
moduleRequire.resolve = moduleName =>
this._resolveModule(from.filename, moduleName);
Object.defineProperty(
moduleRequire,
'main',
({
enumerable: true,
get() {
let mainModule = from.parent;
while (
mainModule &&
mainModule.parent &&
mainModule.id !== mainModule.parent.id
) {
mainModule = mainModule.parent;
}
return mainModule;
},
}: Object),
);
return moduleRequire;
}

Expand Down

0 comments on commit 4576dd4

Please sign in to comment.