Le tl; dr est:
1) Comment puis-je demander à Jest d'utiliser la fonction native require
pour charger tous les modules de mes tests n'importe où.
2) Où/comment pourrais-je modifier (c'est-à-dire le remplacer par le chargeur esm) https://github.com/standard-things/esm la fonction require en un seul endroit, avant l'exécution des tests, donc tous les tests utiliseront le requis modifié.
Je voudrais utiliser esm-loader avec mes fichiers de test Jest. Pour ce faire, je dois patcher la fonction require globalement, avant l'exécution de tout code de test, avec quelque chose comme
require = require("@std/esm")(module, { esm: "js", cjs: true });
Comment dire à Jest d'exécuter ce code avant de toucher ou de demander quoi que ce soit d'autre?
J'ai essayé de pointer à la fois setupTestFrameworkScriptFile
et une entrée de tableau setupFiles
vers un fichier contenant celui-ci, mais aucun n'a fonctionné (même si j'ai confirmé que les deux s'exécutaient).
Alternativement, je lance ces tests avec un script npm
"scripts": {
"test": "jest"
}
Existe-t-il une magie CLI par laquelle je peux simplement charger un module puis exécuter jest
?
Modifier - les options testEnvironment
et resolver
me font me demander si cela utilise même la fonction Node require
pour charger des modules, ou à la place en utilisant son propre module de chargement. Si c'est le cas, je me demande si c'est encore possible.
Donc celui-ci était un peu difficile à mettre en place. La solution est assez simple mais il m'a fallu un certain temps pour la faire fonctionner. Le problème est que chaque fois que vous utilisez un module en plaisantant
Ils sont tous chargés ci-dessous
({"Object.": Function (module, exports, require, __ dirname, __ filename, global, jest) {/* Code du module à l'intérieur */} });
Si vous regardez node_modules/jest-runtime/build/index.js:495:510
const dirname = (_path || _load_path()).default.dirname(filename);
localModule.children = [];
localModule.parent = mockParentModule;
localModule.paths = this._resolver.getModulePaths(dirname);
localModule.require = this._createRequireImplementation(filename, options);
const transformedFile = this._scriptTransformer.transform(
filename,
{
collectCoverage: this._coverageOptions.collectCoverage,
collectCoverageFrom: this._coverageOptions.collectCoverageFrom,
collectCoverageOnlyFrom: this._coverageOptions.collectCoverageOnlyFrom,
isInternalModule,
mapCoverage: this._coverageOptions.mapCoverage },
this._cacheFS[filename]);
this._createRequireImplementation(filename, options);
donne à chaque module un objet require personnalisé. Donc, en tant que tel, vous n'obtenez pas du tout la fonction native native, n'importe où. Une fois que jest a démarré, chaque module chargé à partir de là aura la fonction require
personnalisée de jest.
Lorsque nous chargeons un module, les méthodes requireModule
du jest-runtime
Sont appelées. Ci-dessous est un extrait du même
moduleRegistry[modulePath] = localModule;
if ((_path || _load_path()).default.extname(modulePath) === '.json') {
localModule.exports = this._environment.global.JSON.parse(
(0, (_stripBom || _load_stripBom()).default)((_gracefulFs || _load_gracefulFs()).default.readFileSync(modulePath, 'utf8')));
} else if ((_path || _load_path()).default.extname(modulePath) === '.node') {
// $FlowFixMe
localModule.exports = require(modulePath);
} else {
this._execModule(localModule, options);
}
Comme vous pouvez voir si l'extension du fichier est .node
, Il charge directement le module, sinon il appelle le _execModule
. Cette fonction est le même code que j'ai posté plus tôt qui fait la transformation de code
const isInternalModule = !!(options && options.isInternalModule);
const filename = localModule.filename;
const lastExecutingModulePath = this._currentlyExecutingModulePath;
this._currentlyExecutingModulePath = filename;
const origCurrExecutingManualMock = this._isCurrentlyExecutingManualMock;
this._isCurrentlyExecutingManualMock = filename;
const dirname = (_path || _load_path()).default.dirname(filename);
localModule.children = [];
localModule.parent = mockParentModule;
localModule.paths = this._resolver.getModulePaths(dirname);
localModule.require = this._createRequireImplementation(filename, options);
Maintenant, quand nous voulons modifier la fonction require
pour notre test, nous avons besoin de _execModule
Pour exporter notre code directement. Le code devrait donc être similaire au chargement d'un module .node
} else if ((_path || _load_path()).default.extname(modulePath) === '.mjs') {
// $FlowFixMe
require = require("@std/esm")(localModule);
localModule.exports = require(modulePath);
} else {
Mais cela signifierait patcher le code, ce que nous voulons éviter. Donc, ce que nous faisons à la place, c'est d'éviter d'utiliser directement la commande jest et de créer notre propre jestload.js
Et de l'exécuter. Le code pour charger la plaisanterie est simple
#!/usr/bin/env node
/**
* 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.
*/
cli = require('jest/bin/jest');
Maintenant, nous voulons modifier le _execModule
Avant le chargement du cli. Nous ajoutons donc ci-dessous le code
const jestRuntime = require("jest-runtime");
oldexecModule = jestRuntime.prototype._execModule;
jestRuntime.prototype._execModule = function (localModule, options) {
if (localModule.id.indexOf(".mjs") > 0) {
localModule.exports = require("@std/esm")(localModule)(localModule.id);
return localModule;
}
return oldexecModule.apply(this, [localModule, options]);
};
cli = require('jest/bin/jest');
Il est maintenant temps pour un test
//__test__/sum.test.js
sum = require('../sum.mjs').sum;
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
test('adds 2 + 3 to equal 5', () => {
expect(sum(3, 2)).toBe(5);
});
Et un fichier sum.mjs
export function sum (x, y) { return x + y }
Maintenant, nous exécutons le test
La solution est disponible sur le repo ci-dessous
https://github.com/tarunlalwani/jest-overriding-require-function-stackoverflow
Vous pouvez cloner et tester la solution en exécutant npm test
.