Jest: Meta: Native Unterstützung für ES-Module

Erstellt am 19. Jan. 2020  ·  131Kommentare  ·  Quelle: facebook/jest

EDIT: Kurzanleitung für den Einstieg: https://jestjs.io/docs/en/ecmascript-modules

Die ESM-Unterstützung wird in einer zukünftigen Version von Node 12 aufgehoben (vielleicht nicht vor April https://github.com/nodejs/node/pull/29866#issuecomment-574055057) und sie ist in Node 13.2 bereits deaktiviert, also denke ich, dass es so ist Zeit, um zu evaluieren, wie wir in Jest native Unterstützung hinzufügen können. Ich werde versuchen, aufzulisten, welche Funktionen Jest derzeit bietet, die von der ESM-Unterstützung betroffen sind, und wie wir sie lösen/untersuchen können.

Es gibt Problem #4842, aber ich denke, das ist eher ein Diskussionsthema, während dieses Problem auf die tatsächliche Implementierung von Support ausgerichtet ist und besser für diejenigen geeignet ist, die nur den aktuellen Implementierungsstatus nachverfolgen möchten. Alle Kommentare, die zu diesem Problem hinzugefügt wurden, _nicht_ sich darauf beziehen, wie wir die Unterstützung für die unten aufgeführten Funktionen implementieren können, werden als Spam markiert. Bitte leiten Sie alle Problemumgehungen/Diskussionen an separate Probleme weiter. Sie können uns auch gerne mitteilen, wenn etwas in Bezug auf ESM-Funktionen in der Liste fehlt!

Bitte beachten Sie, dass Jest die vm API (https://nodejs.org/api/vm.html) verwendet und zum Zeitpunkt des Schreibens (node ​​v13.6) die ESM-Teile dieser API noch gekennzeichnet sind ( --experimental-vm-modules ). Zu sagen, dass ESM nicht gekennzeichnet ist, ist im Moment also eine falsche Bezeichnung. Aber ich denke, wir sollten mit dem Experimentieren beginnen und der AG Modules möglicherweise Feedback geben.

Schließlich schreibe ich diese Ausgabe hauptsächlich für Leute, die Support implementieren werden. Für Leute, die _nur_ wissen möchten, ob der Support gelandet ist oder nicht, empfehle ich die wunderbare "benutzerdefinierte Benachrichtigung" von GH zu verwenden und nur Benachrichtigungen beim Schließen / Wiedereröffnen zu abonnieren.


  • [x] Ausführen des Moduls im richtigen Kontext

Wir erreichen Sandboxes, indem wir ein Skript innerhalb eines bestimmten vm.Context ausführen (entweder von JSDOM oder Knotenkern-APIs bereitgestellt). Wir müssen dasselbe für ESM tun, aber wir benötigen Zugriff auf context während der Konstruktion des Moduls, nicht nur beim Ausführen des Moduls. Ich habe #9428 geöffnet, das die erforderlichen APIs zu JestEnvironment hinzufügt.

  • [x] Globale

expect , test , beforeEach etc werden weiterhin als Globals hinzugefügt, hier sollte sich nichts ändern. jasmine global wird auch weiterhin hier sein.

  • [x] jest "globale" Eigenschaft

Dies ist nicht wirklich global - es wird in den Modulbereich eingefügt. Da der Modulumfang in ESM weg ist, müssen wir ihn irgendwo verschieben. Das Hinzufügen zu import.meta scheint natürlich - es gibt eine Option namens initializeImportMeta die wir verwenden können.

BEARBEITEN: Lösung hier ist, es über import {jest} from '@jest/globals' abzurufen. Wir könnten es in Zukunft noch über import.meta hinzufügen, aber das sollte für den Moment reichen.

  • [ ] jest.(do|un)mock

Da ESM bei der Evaluierung eines Moduls verschiedene "Stufen" hat, funktioniert jest.mock nicht für statische Importe. Es kann jedoch für dynamische Importe funktionieren, daher denke ich, dass wir in den Dokumenten nur klarstellen müssen, was es unterstützt und was nicht.

jest.mock Anrufe werden hochgezogen, aber das hilft bei ESM nicht. Wir könnten in Erwägung ziehen, import 'thing' in import('thing') umzuwandeln, was das Heben ermöglichen sollte, aber dann ist es asynchron. Die Verwendung von await oberster Ebene ist wahrscheinlich eine Notwendigkeit für einen solchen Ansatz. Ich denke auch, dass es invasiv genug ist, um eine separate Option zu rechtfertigen. Etwas zu besprechen - wir müssen nicht alles unterstützen, was jest.mock für eine erste Veröffentlichung leisten kann.

  • [ ] jest.requireActual

Ich bin mir nicht sicher, ob es sich in ESM verhalten soll. Sollen wir jest.importActual bereitstellen und requireActual in CJS auswerten lassen?

  • [x] import.meta

Node hat url als einzige Eigenschaft (zumindest vorerst). Wir müssen sicherstellen, dass es auch in Jest bevölkert ist. Wir stellen identifier anstelle von filename wenn das Modul erstellt wird, daher denke ich nicht, dass dies automatisch geschieht, aber url wird im Wesentlichen filename übergeben pathToFileURL .

Es gibt auch eine offene PR für import.meta.resolve : https://github.com/nodejs/node/pull/31032

  • [x] import thing from 'thing'

Dies sollte eigentlich ziemlich einfach sein, wir müssen nur ein linker implementieren, wo wir auch die Quelle transformieren können, bevor wir sie zurückgeben, was bedeutet, dass wir die Loader-API (die noch nicht existiert) nicht benötigen. Auf diese Weise können wir auch Mocks zurückgeben (obwohl sie aus einem __mocks__ Verzeichnis stammen müssen).

  • [x] import('thing')

Im Wesentlichen wie oben, aber beim Erstellen des Moduls als importModuleDynamically . Wird auch jest.mock , jest.resetModules usw. sauberer unterstützen, wird also wahrscheinlich ziemlich häufig verwendet.

Dies kann auch für vm.Script über dieselbe Option erfolgen.

  • [ ] Umgang mit Fehlern bei der Auswertung

Im Moment ist es ein Laufzeitfehler (zB Modul nicht gefunden), aber das ist bei ESM nicht unbedingt der Fall. Ist es für uns wichtig? Wir sollten überprüfen, ob Fehler immer noch gut aussehen.

  • [x] module.createRequire

Wir müssen uns damit für Leute befassen, die CJS von ESM verwenden möchten. Ich habe #9426 geöffnet, um dies separat zu verfolgen, da die Implementierung nicht wirklich mit der ESM-Unterstützung zusammenhängt.

BEARBEITEN: Implementiert in #9469

  • [ ] module.syncBuiltinESMExports

https://nodejs.org/api/modules.html#modules_module_syncbuiltinesmexports. Interessieren wir uns dafür oder reicht es nur aus, es zu einem No-Op zu machen? Ich bin mir nicht sicher, was der Anwendungsfall in Jest wäre. Das Herumspielen mit den Builtins zerstört bereits die Sandbox und ich denke, das sollte keine Rolle spielen.

EDIT: #9469 hat dies zu einem No-Op gemacht. Ich denke, das ist in Ordnung?

  • [ ] Erkennen, ob eine Datei im ESM- oder CJS-Modus sein soll

Das Inspizieren des type Felds im package.json eines Moduls scheint vernünftig: https://nodejs.org/api/esm.html#esm_enabling. Sollten wir auch unser eigenes Konfigurationsflag haben? Muss auch Dateiendungen respektieren.

https://github.com/nodejs/modules/issues/393

  • [x] moduleNameMapper

Ich bin mir nicht sicher, ob dies Auswirkungen hat. Ich _glaube_ nicht, da wir die Module selbst miteinander verknüpfen werden. Muss aber untersucht werden.

EDIT: Das ist alles Auflösungslogik, die wir kontrollieren. Also hier keine Änderungen.

  • [x] jest.config.mjs

Durch #9291 unterstützen wir jest.config.cjs - müssen wir für .mjs etwas Besonderes tun? Verwenden Sie wahrscheinlich import('path/to/configFile.mjs') was bedeutet, dass es asynchron sein muss. Ist das ein Problem? Könnte sich lohnen, die Konfigurationsauflösung async in Jest 25 zu erstellen, damit dies kein Blocker für die inkrementelle Unterstützung von ESM in Jest 25 ist.

BEARBEITEN: #9431

  • [ ] Paketexporte

Node unterstützt Paketexporte , die dem moduleNameMapper von Jest zugeordnet sind, bietet aber auch Kapselungsfunktionen. Hoffentlich wird resolve implementieren, aber wenn nicht, müssen wir etwas tun. Könnte es ausreichen, die Option pathFilter ? Unsicher.

  • [ ] JSON/WASM-Modul

https://nodejs.org/api/esm.html#esm_experimental_json_modules. Müssen wir uns kümmern? Wahrscheinlich, besonders für json . Es ist trivial für uns, import thing from './package.json' da wir die Linking-Phase kontrollieren, aber wir sollten dies wahrscheinlich nicht standardmäßig tun, da es sich vom Standardknoten unterscheidet. Sollten wir die Leute zwingen, eine Transformation dafür zu definieren?

  • [x] Codeabdeckung

Ist es wichtig? Ich glaube nicht, dass es davon betroffen ist, da wir die Quelle immer noch mit Babel transformieren können (vielleicht wird es durch import Anweisungen verwirrt, wahrscheinlich nicht) und V8-Abdeckung sollte definitiv egal sein. Wir sollten es jedoch überprüfen.

  • [ ] Asynchrone Codeauflösung

Dies ist absolut kein Blocker, da die Synchronisierungsauflösung gut funktioniert. Aber wir _können_ jetzt die asynchrone Auflösung verwenden, was großartig ist. Ich frage mich, ob wir uns erneut überlegen sollten, das resolve Modul von npm zu verwenden, da es bereits Async unterstützt. Siehe #9505.

  • [ ] Asynchrone Codetransformation

Ähnlich wie oben, nicht blockierend, aber es wäre schön, es zu unterstützen. Könnte @jest/transformer auch in anderen Umgebungen besser nutzbar machen. Siehe #9504.

  • [ ] Schlechte Leistung beim Zugriff auf Globals

Aufgrund von #5163 haben wir die Option extraGlobals als Problemumgehung - diese Problemumgehung ist in ESM nicht mehr praktikabel. Ich habe hier Knoten geöffnet und Probleme mit diesem Problem: https://github.com/nodejs/node/issues/31658

ES Modules

Hilfreichster Kommentar

Ich habe mit #9772 eine sehr einfache Unterstützung gefunden. Ich habe nur die einfachsten Fälle getestet und es gibt viele bekannte Einschränkungen (vor allem keine jest Objektunterstützung und kaputte Semantik beim Mischen von CJS und ESM), aber immerhin ist es _etwas_. Es wird in der nächsten Veröffentlichung von Jest erscheinen (hoffentlich bald, nur blockiert von #9806)

Alle 131 Kommentare

Ich habe mit #9772 eine sehr einfache Unterstützung gefunden. Ich habe nur die einfachsten Fälle getestet und es gibt viele bekannte Einschränkungen (vor allem keine jest Objektunterstützung und kaputte Semantik beim Mischen von CJS und ESM), aber immerhin ist es _etwas_. Es wird in der nächsten Veröffentlichung von Jest erscheinen (hoffentlich bald, nur blockiert von #9806)

25.4.0 wurde mit den ersten Support-Elementen veröffentlicht. Zusätzlich zu #9772, das oben erwähnt wurde, habe ich auch #9842 aufgenommen. In der _Theorie_ sollte das Mischen von CJS und ESM nun korrekt funktionieren (🤞).

Die einzige fehlende Funktion ist die Unterstützung des jest Objekts. Ich habe mich nicht entschieden, ob wir es bei import.meta festhalten oder von den Leuten verlangen sollen, es über import {jest} from '@jest/globals' zu importieren. Feedback erwünscht!

Ich habe noch keine Dokumente dafür geschrieben, aber um es zu aktivieren, müssen Sie 3 Dinge tun

  1. stellen Sie sicher , laufen Sie nicht verwandeln weg import Anweisungen (set transform: {} in Config oder auf andere Weise sicherzustellen babel die Datei nicht zu CJS verwandeln, wie die Vermeidung von modules Option zur Voreinstellungsumgebung)
  2. node@^12.16.0 || >=13.2.0 mit --experimental-vm-modules Flag ausführen
  3. Führen Sie Ihren Test mit jest-environment-node oder jest-environment-jsdom-sixteen

Bitte probieren Sie es aus und geben Sie Feedback! Wenn Sie Fehler melden, wäre es wunderbar, wenn Sie auch angeben könnten, wie derselbe Code (ohne testspezifischen Code) in Node. Ich habe https://nodejs.org/api/esm.html in den letzten Wochen _viel_ gelesen, aber wahrscheinlich habe ich etwas übersehen.

Die einzige fehlende Funktion ist die Unterstützung des Scherzobjekts. Ich habe mich nicht entschieden, ob wir es in import.meta einfügen oder von den Leuten verlangen sollen, es über import {jest} from '@jest/globals' zu importieren.

Für den Anwendungsfall Typoskript ist es besser, einen expliziten Import zu haben.

Ja, ich habe ein @jest/globals Paket hinzugefügt (und vorübergehend zurückgesetzt), das dies unterstützt, sodass es unabhängig davon verfügbar ist. Ich frage mich, ob es sinnvoll ist, es _auch_ auf import.meta freizugeben. Neige derzeit dazu, dies nicht zu tun, vor allem, weil es einfacher ist, später hinzuzufügen als zu entfernen (und ich persönlich bin kein Fan von Globals).

+1 für den expliziten Import, es ist etwas ausführlicher, aber einfacher zu verstehen

Ich bekomme das in Node 13.2 & Jest 25.4: ES Modules are only supported if your test environment has the getVmContext function Was fehlt mir?

@zandaqo Oh Entschuldigung, habe diesen Punkt vergessen. Oben hinzugefügt, aber es ist

Führen Sie Ihre Tests mit jest-environment-node oder jest-environment-jsdom-sixteen

ReferenceError: jest is not defined Ich vermute, das liegt an den fehlenden @jest/globals

Ja, wie bereits erwähnt, funktioniert dies nur, wenn Sie das jest Objekt nicht verwenden.
Mocks sind wohl auch kaputt, habe sie nicht getestet 😃

Ich habe ein sehr einfaches Projekt aus dem zusammengestellt, was ich im e2e-Testverzeichnis ( e2e/native-esm/__tests__/native-esm.test.js ) und in dieser Ausgabe sehe. Und leider kann ich es immer noch nicht zum Laufen bringen 🙃Kann das zufällig jemand überprüfen?

https://drive.google.com/file/d/1vyDZjsVKOTu6j55QA11GjO9E7kM5WX8_/view?usp=sharing

  • [x] Scherzversion 25.4.0
  • [x] Knotenversion v13.12.0
  • [x] package.json enthält empfohlene Jest-Optionen und es scheinen keine Babel-Transformationen vorhanden zu sein

Ausführen eines Beispielskripts (nur die Funktion double importieren und double(2) drucken):

npm run main

> [email protected] main /Users/ilya/Projects/jest-esm
> node src/main.js

(node:16961) ExperimentalWarning: The ESM module loader is experimental.
4

Laufspaß mit nur einem Test auf Doppelfunktion:

npm run test

> [email protected] test /Users/ilya/Projects/jest-esm
> jest

 FAIL  __tests__/native-esm.test.js
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /Users/ilya/Projects/jest-esm/__tests__/native-esm.test.js:8
    import {double} from '../src/index.js';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime._execModule (node_modules/jest-runtime/build/index.js:1074:58)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.542s
Ran all test suites.

Sie müssen den Knoten mit --experimental-vm-modules ausführen und Ihre Datei entweder .mjs oder "type": "module" in package.json benennen.

BEARBEITEN: Sie haben wahrscheinlich letzteres, da es außerhalb von Jest für Sie funktioniert, es fehlt nur das experimentelle Flag für Node

@SimenB oh wow es gibt --experimental-vm-modules UND --experimental-modules . Ich war verwirrt von der Tatsache, dass --experimental-modules ab einer Version von Knoten 13 nicht erforderlich ist. Danke!

TLDR: node --experimental-vm-modules node_modules/jest/bin/jest.js funktioniert für mich

Ja, vom OP

Bitte beachten Sie, dass Jest die vm API (https://nodejs.org/api/vm.html) verwendet und zum Zeitpunkt des Schreibens (node ​​v13.6) die ESM-Teile dieser API noch gekennzeichnet sind ( --experimental-vm-modules ). Zu sagen, dass ESM nicht gekennzeichnet ist, ist im Moment also eine falsche Bezeichnung.

Aber toll, dass es bei dir funktioniert!

(Ich werde diese Kommentare als gelöst markieren)

@SimenB Danke dafür! Zwei Probleme sehe ich bisher.

Fehler 1

  • ESM-Einheitentestdatei importiert Standard aus ESM-Datei (fn wird getestet)
  • Die getestete ESM-Datei importiert Standard aus einem Paket, das nur CJS exportiert
  • Fehlerhafte Ergebnisse: ReferenceError: module is not defined in der CJS-Paketdatei

Also denke ich, dass dies möglicherweise nicht richtig implementiert wird?

Eine Importanweisung kann auf ein ES-Modul oder ein CommonJS-Modul verweisen

Dies funktioniert gut, wenn die App ausgeführt wird. Benannte Exporte aus CJS können nur mit createRequire importiert werden, aber Standardexporte können einfach importiert werden.

Ausgabe 2

Wenn ich den obigen Fehler nicht treffe, treffe ich diesen:

TypeError: _vm(...).SyntheticModule is not a constructor

      at Runtime._importCoreModule (node_modules/jest-runtime/build/index.js:1198:12)

Projekt Details

  • Knoten 12.14.1
  • Scherz und Babel-Scherz 25.4.0
  • Neuestes Babel mit targets: { node: 12 } und 2 Plugins: babel-plugin-transform-import-meta und rewire-exports . (Ich habe versucht, das import-meta Plugin zu entfernen, erhielt aber eine Fehlermeldung, die besagt, dass es wieder hinzugefügt werden soll.)
  • testEnvironment: "node" ist so ziemlich die einzige Konfiguration
  • node --experimental-vm-modules node_modules/jest/bin/jest.js

Wenn ein Reproduktions-Repository hilfreich wäre, lassen Sie es mich wissen.

Danke @aldeed!

Ich werde mir Problem 1 ansehen, das sieht tatsächlich nach einem Fehler aus. EDIT: Sollte über #9850 behoben werden

Ausgabe 2 benötigt Knoten 12.16.0: https://nodejs.org/docs/latest-v12.x/api/vm.html#vm_class_vm_syntheticmodule

Ich werde den Check in Jest ändern (im Moment sucht er nach vm.SourceTextModule was in weiteren Versionen verfügbar ist, aber wir brauchen auch SyntheticModule ).

Bestätigt, dass die Ausführung mit 12.16.0 mein Problem 2 behebt. Wird Problem 1 erneut testen, nachdem dieses Update veröffentlicht wurde. Andernfalls warte ich auf das jest Objekt für weitere Tests, und ich stimme zu, dass es importiert werden muss.

Tolle Arbeit, @SimenB! Ich probiere dies an einem kleinen Projekt aus, bin jedoch auf Probleme mit dynamischen Importen gestoßen. Dies ist der Fehler, den ich sehe:

Module status must not be unlinked or linkingError [ERR_VM_MODULE_STATUS]: Module status must not be unlinked or linking

Wenn ich die dynamischen Importe entferne, wird der Test ausgeführt (aber natürlich aus anderen Gründen fehlschlagen). Der gleiche Test funktioniert derzeit mit Mocha (das vor kurzem ESM-Unterstützung geliefert hat).

Wenn es hilft, können die betreffenden dynamischen Importe hier eingesehen werden: https://github.com/beejunk/firn.js/blob/switch-to-jest/lib/renderPage.js#L43 -L55

Die Testdatei ist hier: https://github.com/beejunk/firn.js/blob/switch-to-jest/test/build.test.js. Die funktionierende Mocha-Version ist im Master-Zweig zu sehen.

Lassen Sie es mich wissen, wenn es andere nützliche Informationen gibt.

Danke @beejunk! Ich habe mich gefragt, ob es Racebedingungen zwischen import s geben könnte, die dasselbe Modul importieren, bevor es vollständig verknüpft ist. Es _scheint_ das zu sein, was Sie hier treffen. Ich werde das heute beheben, danke für den Bericht!

BEARBEITEN: In #9858 behoben. Habe den Fix in dein Repository kopiert:
image

Hat jemand es geschafft, dies mit TypeScript zum Laufen zu bringen? node --experimental-vm-modules node_modules/jest/bin/jest.js gibt das gleiche SyntaxError: Cannot use import statement outside a module , obwohl mein package.json "type": "module" .

babel.config.cjs

module.exports = {
  presets: [
    '@babel/preset-typescript',
  ],
};

jest.config.cjs

module.exports = {
  testEnvironment: 'jest-environment-node',
  transform: {},
};

@dandv Du https://github.com/facebook/jest/pull/9772/files#r407255029

Könnten Sie ein separates Thema eröffnen? Muss herausfinden, was mit Nicht-Js-Erweiterungen zu tun ist

@SimenB : #9860. Danke fürs reinschauen.

@aldeed @beejunk 25.5.0 wurde mit Korrekturen für Ihre Probleme veröffentlicht. Lass die Fehlerberichte kommen

Oh, zusätzlich enthält es Unterstützung für import { jest } from '@jest/globals' für diejenigen von euch, die darauf warten 👍

Danke für die schnelle Arbeit an all dem, @SimenB! Ich glaube, ich bin auf ein anderes Problem gestoßen.

Ich habe mit der Verwendung von Abfrageparametern in einem Importpfad experimentiert, um den Modulcache auf einem Entwicklungsserver zu sprengen. Die Idee ist, einen Datei-Watcher zu haben, der Änderungen in einer Komponente erkennt und dann den Importpfad mit einem beliebigen Abfrageparameter aktualisiert, sodass der neue Code beim nächsten Seitenladen sofort eingezogen wird, ohne den Server neu starten zu müssen. Dies funktioniert, wenn der Dev-Server ausgeführt wird. Jest wirft jedoch den folgenden Fehler aus:

Cannot find module '/path/to/project/components/BasePage.js?cache=0' from 'renderPage.js'

Hier ist ein Beispiel dafür, wo die Abfrageparameter verwendet werden: https://github.com/beejunk/firn.js/blob/switch-to-jest/lib/renderPage.js#L55 -L56

Wenn ich die Abfrageparameter entferne, werden die Tests bestanden, wenn auch nicht konsistent. Wenn ich eine einzelne Suite ausführe (z. B. npm test -- test/build.test.js ), sind die Tests erfolgreich, aber wenn ich alle Tests gleichzeitig ausführe, werden sie meistens mit mehrdeutigen Fehlern fehlschlagen. Ich befasse mich immer noch mit dem Problem mit den inkonsistenten Tests, aber ich dachte, ich würde zuerst über das Problem mit den Abfrageparametern berichten.

Danke für den Bericht @beejunk. #6282 soll damit umgehen, aber das will auch die Abfrage an Transformatoren und so weitergeben, die wir hier nicht brauchen. Daher kann es sinnvoll sein, die Abfrage vorerst nur intern in der Laufzeit zu unterstützen und #6282 einfach mit der Weitergabe dieser Abfrage zu befassen.

Ich habe ein bisschen Code hinzugefügt, um den Modulcache je nach Abfrage variieren zu lassen: https://github.com/facebook/jest/blob/d425a49bd575e7167bc786f3c4f2833589091fa1/packages/jest-runtime/src/index.ts#L330 -L334

Aber kein Code ruft es jemals mit einer Abfrage auf. Ich denke, wir sollten in der Lage sein, einfach resolvePath.split('?') und alles sollte funktionieren.

In Bezug auf inkonsistente Fehler werde ich nachsehen, ob das Repo es reproduziert. Ich habe den ESM-Code nicht mit Tests parallel getestet, nur einen einzigen Test. Ich bin mir nicht sicher, warum es Auswirkungen auf die Dinge haben würde, aber wer weiß 😀

@beejunk- Abfrage-Ding in 25.5.1 behoben. Ich hatte noch keine Zeit, das andere Problem zu untersuchen

Ich habe ein Problem, von dem ich denke, dass es damit zusammenhängt, aber in 25.X nicht behoben wurde.

Ich werde versuchen, das folgende Szenario zusammenzufassen:

  • Sie haben einen Test mit einem Setup-Skript
  • Dieses Setup-Skript erfordert dynamisch eine Datei, wie in:
    { default: generator } = require(path.resolve(f))
  • Alles in f wird nicht transpiliert, was den "unerwarteten Fehler beim Importieren von Kennungen" verursacht.

Dies passiert auch, wenn ich es mit import() versuche

Da Sie Transpilation erwähnen; Wenn Sie ein Setup haben, das import in require umwandelt, ist dieses Problem nicht der richtige Ort - dieses Problem betrifft die native Unterstützung.


Das heißt - Sie können nicht require ESM, und ich konnte noch keine Unterstützung für import() von CJS hinzufügen, da Node keine API dafür hat. Unterstützung dafür ist auf Node Master gelandet, aber noch nicht veröffentlicht: https://github.com/nodejs/node/pull/32985. Wie in den verlinkten Release-PRs zu sehen ist, wird es in 13.14.0 und 14.1.0 erscheinen. An dieser Stelle werde ich Support dafür implementieren 👍

Sie sollten jedoch in der Lage sein, eine .mjs Setup-Datei zu verwenden.

@SimenB Das ist großartig, es scheint jetzt in mehreren Testdateien zu funktionieren! Es ist ein kleiner Prozess, die Unterschiede zwischen Babel- und Node-Importen in jeder Datei zu beheben, einen Jest-Import hinzuzufügen usw., so dass ich möglicherweise auf weitere Probleme stoße, wenn ich dies bei Hunderten von Testdateien tue.

Ein paar Dinge, die mehr Fragen sind:

  • was Sie in Ihrem vorherigen Kommentar über die Unterstützung von import() von cjs gesagt haben, wird dies auch ermöglichen, dass die Jest-Konfigurationsdatei jest.config.js ? Es funktioniert derzeit nur bei mir, wenn es jest.config.cjs und module.exports = (Fehler ist TypeError [ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING]: A dynamic import callback was not specified )
  • Der Name "@jest/globals" verfehlt die eslint-Regel node/no-extraneous-import da er kein Paket in package-lock . Gibt es einen Grund für diese Namenskonvention? Ist es möglich, jest ohne @ ? Es ist leicht, die Regel zu ignorieren, aber ich frage mich nur.
  • Verwandte Frage, warum unterscheidet sich jest global von magischen Fns wie test , describe , before usw.? Sollen die jetzt auch alle importiert werden?
  • Wird es Jest möglich sein, das Flag --experimental-vm-modules zu setzen, wenn dies abgeschlossen ist? Dies lässt dies irgendwie nicht standardmäßig erscheinen, wenn es nicht nur mit dem Befehl jest funktioniert. Wenn Sie Flags nicht direkt übergeben können, können Sie möglicherweise die env-Variable NODE_OPTIONS setzen/ändern?
  • Ich scheine jetzt einen etwas anderen Fehler als zuvor zu erhalten, wenn ich dies auf einem älteren Node versuche, aber keiner der Fehler war klar, dass die minimale Node-Version das Problem war. Ist es einfach, eine Überprüfung für die Mindestversion mit einer hilfreicheren Fehlermeldung hinzuzufügen?

wird dies auch ermöglichen, dass die Jest-Konfigurationsdatei jest.config.js heißt?

Es kann .js heißen, wenn sein nächstgelegenes package.json type: 'module' . Um ESM in der Konfigurationsdatei zu verwenden, muss es ansonsten .mjs heißen. Siehe https://nodejs.org/api/esm.html#esm_enabling. Beachten Sie, dass die Konfigurationsdatei außerhalb von Jest ausgeführt wird, sodass wir dort nicht viel Kontrolle haben. Im Moment unterstützen wir keine asynchrone Konfiguration, aber await Ein exportiertes Versprechen wäre trivial, PR willkommen 🙂 #8357 ist ins Stocken geraten.

Ich bin sehr überrascht, dass Sie A dynamic import callback was not specified , wir laden die Konfigurationsdatei nicht in eine VM... Könnten Sie ein separates Problem öffnen?

Der Name "@jest/globals" verfehlt die eslint-Regel node/no-extraneous-import da er kein Paket ist, das in package-lock . Gibt es einen Grund für diese Namenskonvention? Ist es möglich, jest ohne @ ? Es ist leicht, die Regel zu ignorieren, aber ich frage mich nur.

Sie sollten devDependency auf @jest/globals hinzufügen. Das Paket selbst besteht ausschließlich aus Typdefinitionen. Es ist ein separates Paket von jest damit Typdefinitionen korrekt funktionieren und wir einen Fehler ausgeben können, wenn es außerhalb der Jest-Laufzeit geladen wird.

Ich habe derzeit keine Pläne, dies zu ändern, aber wir könnten dieses Paket möglicherweise verwerfen und die Typen aus jest exportieren. Das ist jedoch eine große bahnbrechende Änderung, also sehen wir uns später an 🙂

Verwandte Frage, warum unterscheidet sich jest global von magischen Fns wie test , describe , before usw.? Sollen die jetzt auch alle importiert werden?

jest ist wie require oder module Objekt von CJS darin, dass es pro Datei eindeutig ist, es ist nicht wirklich ein globales (dh globalThis.jest === undefined ). Dadurch kann jest.mock('../../file.js') usw. relativ zu der Datei, in die es eingefügt wurde, korrekt funktionieren. Sie können auch die tatsächlichen Globals importieren, sie sind jedoch weiterhin als globalThis.expect usw. verfügbar.

Wird es Jest möglich sein, das Flag --experimental-vm-modules zu setzen, wenn dies abgeschlossen ist?

Ich denke, wir warten darauf, dass der Knoten die Kennzeichnung aufhebt, anstatt sie im Hintergrund zu setzen. Sie sind aus einem bestimmten Grund gekennzeichnet, die API könnte sich irgendwann ändern. Wir könnten eine Option hinzufügen, die NODE_OPTIONS festlegt. Ich schätze, ich bin mir nicht sicher, ob das die aktuelle Laufzeit ändert? Unabhängig davon gibt es keine aktuellen Pläne dafür.

Ich scheine jetzt einen etwas anderen Fehler als zuvor zu erhalten, wenn ich dies auf einem älteren Node versuche, aber keiner der Fehler war klar, dass die minimale Node-Version das Problem war. Ist es einfach, eine Überprüfung für die Mindestversion mit einer hilfreicheren Fehlermeldung hinzuzufügen?

Ja, ich werde eine bessere Fehlermeldung zusammen mit einer Dokumentation hinzufügen, sobald sich die Implementierung ein wenig stabilisiert hat. Da die Implementierung von einer experimentellen Flagge bewacht wird, glaube ich nicht, dass jemand darüber stolpern wird.

@SimenB , ich habe Jest auf 25.5.2 aktualisiert und jetzt sind alle Tests erfolgreich. Die Abfrageparameter funktionieren und die zeitweiligen Fehler, die ich zuvor gesehen habe, treten nicht mehr auf. Nochmals vielen Dank für Ihre ganze Arbeit!

Okay, ich habe die Fehler bei meinem letzten Testlauf wieder gesehen, also passiert das immer noch. Ich werde sehen, ob ich einen Weg finden kann, konsistent zu reproduzieren und Bericht zu erstatten.

Ich glaube, ich habe einen konsistenten Weg gefunden, das Problem zu reproduzieren. Hier ist der Zweig, von dem aus ich arbeite: https://github.com/beejunk/firn.js/tree/switch-to-jest

Reproduzieren:

  1. Löschen Sie den Jest-Cache, falls vorhanden. Ich habe gerade /tmp/jest_rs manuell gelöscht.
  2. Führen Sie npm test dreimal aus. Die ersten beiden Läufe sollten gelingen. Der dritte Lauf sollte jedoch fehlschlagen.

Dies ist der Stack-Trace, den ich sehe, wenn der Fehler auftritt:

    Error: 
        at invariant (/home/brian/Projects/firn.js/node_modules/jest-runtime/build/index.js:1866:11)
        at Runtime.loadEsmModule (/home/brian/Projects/firn.js/node_modules/jest-runtime/build/index.js:480:7)
        at Runtime.linkModules (/home/brian/Projects/firn.js/node_modules/jest-runtime/build/index.js:548:19)
        at importModuleDynamicallyWrapper (internal/vm/module.js:397:21)
        at htmPreactPath (internal/process/esm_loader.js:31:14)
        at renderPage (/home/brian/Projects/firn.js/lib/renderPage.js:53:15)
        at map (/home/brian/Projects/firn.js/lib/build.js:43:12)
        at Array.map (<anonymous>)
        at build (/home/brian/Projects/firn.js/lib/build.js:36:43)
        at Object.<anonymous> (/home/brian/Projects/firn.js/test/build.test.js:57:5)

Der Fehler scheint von den dynamischen Importen zu stammen. Es gibt keine Fehlermeldung, daher bin ich mir nicht ganz sicher, was passiert.

Ein zusätzlicher Hinweis: Wenn ich den Jest-Cache lösche und das Testskript aktualisiere, indem ich --no-cache hinzufüge, kann ich das Problem nicht reproduzieren.

Heh, da war ich faul und habe keine richtige Fehlermeldung ausgegeben. Das Problem ist, dass die Testumgebung abgerissen wurde, daher vermute ich, dass irgendwo await fehlt. Habe beim Durchsuchen deines Codes jedoch nichts gesehen, also muss ich noch etwas graben

@SimenB Hier ist eine Reproduktion dieses ESM-Konfigurationsproblems: https://github.com/facebook/jest/issues/9935

@SimenB Ich habe ein Minimalbeispiel erstellt, um die oben erwähnten Jest-Fehler bei der Verwendung dynamischer Importe zu reproduzieren:

https://github.com/beejunk/jest-esm-dynamic-import-error

Danke für die tolle Reproduktion @beejunk! Ich habe hier mehr Stunden verbracht, als ich zugeben möchte, ohne wirklich zu verstehen, ob es sich um einen Fehler in Jest oder in Node handelt. Ich habe das Verhalten ausschließlich mit Node-Core-Modulen reproduziert und im Upstream gemeldet, also mal sehen, was sie sagen: https://github.com/nodejs/node/issues/33216

Danke, dass Sie sich das angeschaut haben, @SimenB. Die Tests scheinen durchweg zu bestehen, wenn ich das Flag --no-cache hinzufüge, was für meinen Anwendungsfall in Ordnung ist. Ich schätze die ganze Arbeit!

Ja, das ist mir auch aufgefallen. Ich denke, es ist eine Art Timing-Problem - ohne Cache sind die Dinge langsam genug, dass es funktioniert.

@SimenB Danke, dass gelöst hast . Ich habe dort eine zweite Sorge erwähnt, die meiner Meinung nach immer noch gültig ist. Wenn type: "module" , generiert jest --init immer noch die Konfigurationsdatei mit module.exports darin. Dies ist relativ geringfügig manuell zu ändern, wenn Sie wissen, was Sie tun jest --init && jest bei einem neuen ESM-Projekt wird einen Fehler auslösen). Sollte ich ein anderes Problem speziell zur Verbesserung der Init-Logik einreichen?

@aldeed bist du dir sicher? Wenn ich gerade teste, bekomme ich eine mjs Datei mit export default darin. Ich schätze, wir könnten js generieren und nicht mjs , aber trotzdem. Es verwendet die ESM-Syntax

@SimenB Nun, ich war mir sicher, bis du gefragt hast. 😄Ich habe es versucht und du hast recht. Vielleicht habe ich es anfangs mit einer älteren Version von Node oder Jest gemacht? Außer Acht lassen.

Das ist fantastisch! Ich habe gerade Tests in einer meiner Bibliotheken überarbeitet, um ES-Module zu verwenden, und Babel aufgegeben. Danke @SimenB!

Erkennen, ob eine Datei im ESM- oder CJS-Modus sein soll

Apropos, es gibt viele browser-/bundlerorientierte Pakete, die die Syntax "module":"<path to es module>" , um ihre ES-Modulexporte zu bezeichnen. Es kann ratsam sein, eine Möglichkeit zu haben, anzugeben, wie ein bestimmtes Paket unabhängig von den eigenen Einstellungen des Pakets aufgelöst werden soll. Etwas wie moduleNameMapper aber um anzugeben, ob es sich um CJS oder ESM handelt.

Hallo @SimenB , sobald dieses Problem geschlossen ist, bedeutet dies, dass ts-jest auch commonjs aufheben kann, oder? Ist eine Dateierweiterung erforderlich, um von der Transformatorseite zu wechseln, um mit esm zu arbeiten?

Zum Beispiel kompiliert ts-jest jetzt ts zu js für commonjs , erfordert esm die Dateierweiterung mjs beim Kompilieren von ts zu js ?

@zandaqo wir werden das Feld modules nicht unterstützen, wir folgen der Spezifikation des Knotens und verwenden exports : #9771. Sie können jedoch Ihren eigenen Resolver anschließen, um modules wenn Sie möchten: https://jestjs.io/docs/en/configuration#resolver -string. Wir könnten eine andere Option hinzufügen ( mainFields , wie Webpack vielleicht?), aber das wird später kommen, wenn sich die Implementierung stabilisiert und wir weniger unbekannte Unbekannte haben 🙂


@ahnpnl #9860

Ciao Jungs!
Nur eine Frage: Der Blog-Beitrag erwähnt, dass ES6-Module statisch sind und nicht verspottet werden können; Also gibt es eigentlich keine Möglichkeit, ein Modul A zu simulieren, das von einem Modul B in ES6 importiert wurde?

@gabrieledarrigo Ich verwende dafür moduleNameMapper , zum Beispiel:

    "moduleNameMapper": {
      "moduleA": "<rootDir>/test/moduleA-mock.js"
    },

@gabrieledarrigo kannst du machen

jest.mock('the-thing-i-want-to-mock', () => /* do whatever in here */);

let importedThing;

beforeAll(async () => {
  importedThing = await import('thing-that-imports-mocked-module');
});

Sie müssen also nur den Import nicht statisch machen und das Mocking funktioniert.

Ich bin mir jedoch nicht sicher, ob es jetzt funktioniert, da ich noch keine Scheinauflösungen im ESM-Codepfad verdrahtet habe. Werde es demnächst mal machen. Aber so werden wir _wahrscheinlich_ Modulmocks für natives ESM dokumentieren.

Wie in den Blog-Töpfen erwähnt, dokumentieren wir diese Muster irgendwann, wir müssen sie nur noch herausfinden 🙂

Eine Idee, die wir hatten, war, auf Top-Level-Await zu warten, dann könnten wir dies mit einem Babel-Plugin tun.

@SimenB Zunächst einmal vielen Dank für die tolle Arbeit hier :)

Ich stehe tatsächlich vor einem Problem, wenn ich eine benutzerdefinierte Umgebung erstellen möchte, die von jest-environment-node . Ich muss dort meine Serverimplementierung importieren, die als esm geschrieben ist. Aber es sieht so aus, als ob die Umgebung als cjs .
Meine Frage ist, gibt es eine Option, benutzerdefinierte testEnvironment als esm zu definieren, um mein Servermodul importieren zu können? Vielen Dank für jeden Rat.

@kuka-radovan könntest du dafür eine separate Funktionsanfrage stellen?

UPDATE: Dieses Problem wird jetzt in https://github.com/facebook/jest/issues/10025 nachverfolgt

@SimenB Danke für die jest.mock Ratschläge oben. Zufälligerweise konvertiere ich ein paar Dateien, die das heute brauchen. Ich kann bestätigen, dass Ihr Beispiel funktioniert, wenn das verspottete Modul ein node_modules Paket ist, aber es funktioniert nicht, wenn ich ein Modul im selben Projekt verspotte.

Hier ist ein einfaches Beispiel:

// main.js
import secondary from "./secondary.js";

export default function main() {
  return secondary();
}

// secondary.js
export default function secondary() {
  return true;
}

// test.js
import { jest } from "@jest/globals";

jest.mock("./secondary.js");

let main;
let secondary;
beforeAll(async () => {
  ({ default: main } = await import("./main.js"));
  ({ default: secondary } = await import("./secondary.js"));
});

test("works", () => {
  secondary.mockReturnValueOnce(false); // TypeError: Cannot read property 'mockReturnValueOnce' of undefined
  expect(main()).toBe(false);
});

Exakt dasselbe Muster funktioniert, wenn "./secondary.js" stattdessen ein Paketname ist. (Ich denke, das Paket, das ich mit CommonJS-Exporten ausprobiert habe, falls das wichtig ist.)

Jest 26.0.1 mit Knoten 12.16.3

Irgendwelche Ideen oder sollte ich eine komplette separate Ausgabe einreichen?

EDIT: transform: {} in der Konfiguration, also überhaupt kein Babel

EDIT 2: Das geht auch nicht:

jest.mock("./secondary.js", () => ({
  default: jest.fn()
}));

Erstaunliche Arbeit dazu.

Wenn ich jedoch nichts falsch mache, scheint es noch nicht möglich zu sein, import() in einer CJS-Testdatei zu verwenden.

Ich betreibe Jest mit node --experimental-vm-modules node_modules/jest/bin/jest.js und habe testEnvironment: 'node', transform: {} in jest.config.js . Dies ist auf Knoten 14.2.0.

Der Importausdruck erzeugt einen Fehler:

TypeError [ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING]:
A dynamic import callback was not specified.

Ist das derzeit eine bekannte Einschränkung? Ich sehe https://github.com/nodejs/node/pull/32985 ist jetzt in Node 14.1.0 gelandet.

Ja, ich bin noch nicht dazu gekommen, es umzusetzen. Ich werde es wahrscheinlich dieses Wochenende landen.

@aldeed könnten Sie ein separates Problem eröffnen? Ich muss durchgehen und sicherstellen, dass Mocks Teil der Auflösung sind, und Ihr Beispiel scheint ein guter Testfall zu sein 🙂

@SimenB Danke für die schnelle Antwort. Ich werde Ausschau halten, wenn es landet.

Da import in Skripten möglicherweise aufgrund einer Regression zurückgesetzt werden (https://github.com/nodejs/node/issues/33166), warten wir, bis sich das erledigt hat

Ich habe Probleme, dies mit .mjs Testdateien zu verwenden. Wenn ich __tests__/my-test.mjs , bekomme ich

$ yarn test
yarn run v1.22.4
$ node --experimental-vm-modules node_modules/jest/bin/jest.js
No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In C:\Users\Domenic\Dropbox\Programming\WIP\remember-to-eat
  1 file checked.
  testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 0 matches
  testPathIgnorePatterns: \\node_modules\\ - 1 match
  testRegex:  - 0 matches
Pattern:  - 0 matches
error Command failed with exit code 1.

Wenn ich hinzufüge

"testMatch": ["**/__tests__/**/*.mjs"]

zu meinem package.json bekomme ich

$ yarn test
yarn run v1.22.4
$ node --experimental-vm-modules node_modules/jest/bin/jest.js
No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In C:\Users\Domenic\Dropbox\Programming\WIP\remember-to-eat
  1 file checked.
  testMatch: **/__tests__/**/*.mjs - 0 matches
  testPathIgnorePatterns: \\node_modules\\ - 1 match
  testRegex:  - 0 matches
Pattern:  - 0 matches
error Command failed with exit code 1.

Wenn ich jedoch "testMatch" entferne und meine Datei dann in __tests__/my-test.js umbenenne, funktioniert es.

Ich möchte in meinem Projekt konsequent .mjs-Erweiterungen verwenden können. Ist das bei Jest möglich?

@domenic Ich bin auch darauf "moduleFileExtensions": ["js", "mjs"] hinzuzufügen (zusätzlich zu "testMatch" ).

Schaute nach, und moduleFileExtensions ist in der Tat notwendig.

Jest ruft eine Liste aller Dateien im Projekt ab, indem er hier hasteFS.getAllFiles() ausführt:

https://github.com/facebook/jest/blob/2460c059ad1dbf124466ac25c8d5ccfd74ae9f25/packages/jest-core/src/SearchSource.ts#L159 -L164

hasteFS wird als Teil der HasteMap mit der folgenden extensions Konfiguration erstellt:

https://github.com/facebook/jest/blob/2460c059ad1dbf124466ac25c8d5ccfd74ae9f25/packages/jest-runtime/src/index.ts#L291


Ich denke jedoch, dass es in diesem Fall nicht notwendig sein sollte, moduleFileExtensions anzugeben. Wir erzwingen bereits, dass .snap gefunden wird. Sollten wir auch bekannte JS-Erweiterungen erzwingen? Diese sind (aus dem Kopf) js , mjs , cjs , jsx , ts und tsx ? Es wird das Crawlen verlangsamen, aber ich würde nicht glauben, dass es einen großen Einfluss hat. Kann ich mich aber irren? Standardmäßig sollte es nicht viel langsamer sein, da nur cjs und mjs noch nicht Teil der Standardmuster sind, aber für Leute, die benutzerdefinierte Muster haben, könnte es die Dinge verlangsamen?

Ja, es wäre ideal, wenn .mjs zumindest im ES-Modulmodus einfach funktioniert, ohne moduleFileExtensions hinzufügen oder den StandardtestMatch ändern zu müssen.

Es wäre auch schön, wenn ich .js-Dateien ausschließen könnte; als ich das versuchte, bekam ich

 Validation Error:

  moduleFileExtensions must include 'js':
  but instead received:
    ["mjs"]
  Please change your configuration to include 'js'.

Ich frage mich, ob es sinnvoll ist, einen "ESM-Modus" zu haben, der die Knoten-ESM-Dateierweiterungen hinzufügt und auch beim Kompilieren in js mit Esm hilft, sich anzumelden (#9860).


Ohne js bricht einiges intern ab, das wir in die Sandbox laden (da es dieselbe require Implementierung verwendet usw.). Wir sollten das wahrscheinlich reparieren, damit der Benutzer uns nicht kaputt machen kann.

Was das Verlangsamen angeht, ist es bei großen Projekten bereits ziemlich langsam, aber ich weiß nicht, ob die Anzahl der Erweiterungen einen so großen Einfluss hat. Aber ich stimme zu, dass mjs und cjs als Standard hinzugefügt werden sollten. Die Angabe von moduleFileExtensions: ['js'] würde die Standardeinstellungen überschreiben und es beschleunigen, oder? Dokumentieren Sie das vielleicht einfach als Leistungsoptimierung.

Danke für all diese Arbeit! Es ist sicherlich erstaunlich. Ich habe die 3 Schritte befolgt ( "type": "module" in meinem package.json, "testEnvironment": "jest-environment-node" in meiner jest config und --experimental-vm-modules in der CLI) und es scheint auch gut zu funktionieren 🎉

Aber dann versuche ich, import.meta zu lesen und zu verwenden, wie in den Node.js-Dokumenten beschrieben (und das scheint nach dem Kontrollkästchen bereits implementiert zu sein), um __dirname zu erstellen, aber es scheint wie import.meta schlägt fehl:

console.log(import.meta);

SyntaxError: [PATH]/files.test.js: Support for the experimental syntax 'importMeta' isn't currently enabled (31:20):
    Add @babel/plugin-syntax-import-meta (https://git.io/vbKK6) to the 'plugins' section of your Babel config to enable parsing.

Ich habe kein Babel und dachte, Babel würde mit dieser Arbeit zurückgelassen. Ich werde zurückkommen, um zu berichten, ob ich es irgendwie beheben kann, ohne Babel zu installieren.

Node.js v14.3.0, Jest v25.5.4

Ich habe jetzt einen Workaround gefunden. Da ich das Skript aus demselben Verzeichnis ausführe, in dem sich meine Datei

const __dirname = process.cwd();
const __filename = __dirname + "/files.test.js";

Ich werde diesem Repo folgen, falls es ein Update gibt. Nochmals vielen Dank dafür!

Sie müssen sich explizit von Babel abmelden, indem Sie transform: {} als Konfiguration verwenden

@SimenB Ich kann bestätigen, dass das Hinzufügen von transform: {} funktioniert hat, danke! Ich habe diesen Punkt missverstanden als "Transformationen nicht hinzufügen" und nicht wie beabsichtigt als "Transformationen wegnehmen".

Übrigens, das Testen ist von 2,4 Sekunden auf nur 1,3 Sekunden gestiegen und sie fühlen sich konstant schneller an.

Node 12 wurde mit unmarkiertem ESM veröffentlicht (https://nodejs.org/en/blog/release/v12.17.0/). Wie im OP jedoch erwähnt, sind die von Jest verwendeten APIs _nicht_ unmarkiert

@SimenB Ich bin diesen Thread mehrmals

Beim Ausführen von Jest 26.0.1 erhalte ich diese Fehlermeldung:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /app/tests/setup.js
require() of ES modules is not supported.
require() of /app/tests/setup.js from /app/node_modules/@jest/transform/build/ScriptTransformer.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename setup.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /app/package.json.

Ich habe transform: {}, und laufe mit node --experimental-vm-modules node_modules/jest/bin/jest.js .

Was vermisse ich?

@aldarund nicht sicher, könntest du eine minimale Reproduktion zusammenstellen?

@SimenB hier ist ein minimales Repo zum Repro, führen Sie einfach yarn test https://github.com/aledalgrande/jest-example - Ich habe es mit Node 13/14 versucht und es ist das gleiche Ergebnis. Mir scheint, dass der Ablauf für das globale Setup nicht aktualisiert wurde, um mit ESM zu funktionieren.

Außerdem hast du jemand anderen erwähnt 😆

~Nicht @simenB , aber @aledalgrande Sie scheinen hier alles richtig zu haben, was ich versucht habe. Sehen Sie sich mein Projekt zum Vergleich an, das package.json ).~

~Um es nach Möglichkeit zu debuggen, würde ich vorschlagen, Ihre jest-Konfiguration so zu vereinfachen, dass sie _nur_ die beiden relevanten Eigenschaften hat, vielleicht sogar zuerst in package.json . Fügen Sie dann jede der anderen Eigenschaften hinzu, die Sie derzeit benötigen, um zu sehen, welche funktioniert/nicht funktioniert.~

Ah der zweite Kommentar erwähnt globalSetup und keine normalen Tests, nvm dann mein Kommentar. Wenn ich den globalSetup Schlüssel in Jest entferne, läuft der Test wie in diesem Beispiel erwartet, aber der globalSetup Schlüssel funktioniert nicht wie gesagt.

Aha, ich habe den globalen Aufbau und Abbau vergessen. Kann beheben 👍

Hallo @SimenB , ich nochmal. Werden benannte Exporte unterstützt? Mit Node.js kann ich ein Paket wie dieses importieren und verwenden:

import { customAlphabet } from "nanoid";

Wenn Sie jedoch versuchen, einen Test durchzuführen, gibt derselbe Code diesen Fehler aus:

SyntaxError: The requested module 'nanoid' does not provide an export named 'customAlphabet'

Für die Tests kann ich den Code so ändern und es funktioniert:

import nanoid from "nanoid";
const { customAlphabet } = nanoid;

Aber dann funktioniert die Node.js-Version nicht mehr, da es eigentlich keinen Standardsport gibt (aber aus irgendeinem Grund funktioniert der Standardexport mit Jest):

SyntaxError: The requested module 'nanoid' does not provide an export named 'default'

Der veröffentlichte (das Repo scheint gerade im Fluss zu sein) nanoid Code endet wie folgt, ohne Standardexport:

export { nanoid, customAlphabet, customRandom, urlAlphabet, random }

Jest verbraucht nur den "Haupt"-Einstiegspunkt. "Exporte" wird noch nicht berücksichtigt. Sie importieren einfach die Commonjs-Version, die nur den Standardexport hat.

Ah ich sehe, das package.json scheint Folgendes zu beinhalten:

  "main": "index.cjs",
  "module": "index.js",
  "exports": {
    "./package.json": "./package.json",
    ".": {
      "require": "./index.cjs",
      "import": "./index.js",
      "browser": "./index.browser.js"
    },
    ...
  }
  ...

Node.js findet also wahrscheinlich die Modulversion, während Jest die CommonJS-Version verwendet, die keinen benannten Export hat, oder?

Ich warte, bis Package Exports überprüft ist und teste es dann, danke für die ganze Arbeit! Bis dahin diese 2 Kommentare als gelöst markieren. Der Test, auf den ich mich beziehe, ist dieser .

Ich schaue mir das noch einmal an, um zu sehen, wie es funktioniert - aktualisiert auf Jest 26.0.1 und Knoten 14.4. Setzen Sie package.json auf den Modultyp, setzen Sie transform auf {} , env auf jest-environment-node und laufen Sie mit node --experimental-vm-modules . Jetzt bekomme ich diesen neuen Fehler:

ES Modules are only supported if your test environment has the `getVmContext` function

Ich konnte keine Informationen dazu finden, außer einem Änderungsprotokoll von Jest, das besagte, dass getVmContext vor einiger Zeit hinzugefügt wurde.

Irgendwelche Ideen?

Könnten Sie bitte die relevanten Teile Ihres package.json @cyberwombat teilen ? Einschließlich des Startskripts, das Sie für Jest verwenden.

Als Referenz sieht es bei mir in einem Arbeitsprojekt so aus :

{
  ...
  "type": "module",
  "scripts": {
    ...
    "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
  },
  "jest": {
    "transform": {},
    "testEnvironment": "jest-environment-node"
  },
  ...

Dann starte es mit npm test

@franciscop Mine ist im Grunde gleich. Knoten 14.4.0. Ich kann deine gut laufen lassen. Ich werde in die Dinge eintauchen, um das Diff zu sehen.
Paket.json

{
  "type": "module",
  "devDependencies": {
    "jest": "^26.0.1",
  },
}

jest.config.js

export default {
  testEnvironment: 'jest-environment-node',
  setupFilesAfterEnv: ['./test/bootstrap.js'],
  testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/config/', '/<rootDir>/src/'],
  testRegex: '(\\.|/)(test|spec)\\.[jt]sx?$',
  transform: {
//    '^.+\\.jsx?$': 'babel-jest' // esm someday
  },
  transformIgnorePatterns: [],
  modulePaths: [
    '<rootDir>/test',
    '<rootDir>/src',
    '<rootDir>'
  ]
}

Skript:
node --experimental-vm-modules node_modules/jest/bin/jest.js

Ich bin mir nicht sicher, aber ich würde versuchen, anders herum zu arbeiten. Entfernen Sie alles außer transform: {} und testEnvironment: 'jest-environment-node' und fangen Sie an, jede der Optionen hinzuzufügen, bis Sie sehen, welche den vorherigen Fehler auslöst. Ich vermute besonders, dass transformIgnorePatterns _might_ in Konflikt mit transform , aber ich bin mit Scherzoptionen nicht so vertraut.

Hallo an alle! Ich bin auf ein Problem gestoßen, als ich Jest zum Testen einer Express-Anwendung verwendet habe. Näheres hier . Ich bin mir nicht sicher, ob das für das, was Sie hier tun/verfolgen, nützlich ist :roll_eyes:

@ x80486 Ich bin gestern auf in StackOverflow mit einer längeren Erklärung aus meinem Verständnis

Bearbeiten: Ich habe meinen vorherigen Kommentar ausgeblendet, da er relevant zu sein scheint. Dieses "exports" scheint beliebt zu sein, sehr wahrscheinlich aus diesem Artikel über Hybridpakete .

exports wird in #9771 verfolgt

@franciscop ok Problem gelöst - es stellt sich heraus, dass es einen Konflikt in den Paketen gibt - ich hatte serverless-bundle installiert, was den ES Modules are only supported if your test environment has the getVmContext function Fehler verursacht. Ich bin mir nicht sicher warum - ich würde annehmen, dass die Installation keinen Konflikt mit Jest verursacht, aber offensichtlich tut es das.

@franciscop Ich denke, der Grund, warum pkg.exports bezogene Probleme jetzt auftauchen, ist, dass diese Funktion in Node.js 14.x markiert wurde und einige Paketbetreuer (wie ich für uuid ) damit begonnen haben Hinzufügen von pkg.exports Feldern. Während Sie also ein Befehlszeilen-Flag brauchten, um diese Funktion in Node.js 12.x zu aktivieren, erhalten Sie dieses Verhalten jetzt standardmäßig.

Es wird eine Weile dauern, bis sich das gesamte Ökosystem angepasst hat. Vielen Dank, dass Sie Probleme zu diesem Thema melden!

Für diejenigen, die über exports , falls es im langen Thread dieser Ausgabe verloren gegangen ist, hat meine geschlossene Ausgabe dazu (https://github.com/facebook/jest/issues/9565) ein Beispiel des darin enthaltenen moduleNameMapper Workarounds.

Das im Mai gemeldete globalSetup Problem besteht wahrscheinlich immer noch (Jest 26.1.0)? Das Erhalten der gleichen Fehler wie im Beispiel-Repo @aledalgrande bietet:

$ git clone [email protected]:aledalgrande/jest-example.git
$ cd jest-example
$ npm test

> @ test /Users/asko/Temp/jest-example
> node --experimental-vm-modules node_modules/jest/bin/jest.js --config=./jest.config.js

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/asko/Temp/jest-example/tests/setup.js
require() of ES modules is not supported.
require() of /Users/asko/Temp/jest-example/tests/setup.js from /Users/asko/Temp/jest-example/node_modules/@jest/transform/build/ScriptTransformer.js 

Keine Eile. CHANGELOG überprüft und es wurde kein Fix für globalSetup/globalTeardown mit ES6 erwähnt.

Node.js 14.4.0, Jest 26.1.0


Update (13. August 20):

Noch nicht möglich, Node.js 14.7.0, Jest 26.4.0

Nebenmeinung, aber sollte dieses Thema ein fixiertes Thema sein, da es im Moment im Mittelpunkt des Scherzes steht?

Irgendwelche Gedanken dazu, was getan werden muss, um in ES-Modulen geschriebene Testreporter zu konsumieren?...
Mit der neuesten Jest-Version erhalte ich einen Fehler, der im Wesentlichen besagt, dass testScheduler einen benutzerdefinierten Reporter im Commonjs-Format erwartet.


Fehler sehen

~/projects/esw-ts/lib/dist/test/testReporter.js:1
os aus 'os' importieren;
^^^^^^

SyntaxError: Import-Anweisung kann nicht außerhalb eines Moduls verwendet werden
bei wrapSafe (intern/modules/cjs/loader.js:1116:16)
at Module._compile (internal/modules/cjs/loader.js:1164:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
bei Module.load (internal/modules/cjs/loader.js:1049:32)
bei Function.Module._load (internal/modules/cjs/loader.js:937:14)
bei Module.require (internal/modules/cjs/loader.js:1089:19)
bei erfordern (internal/modules/cjs/helpers.js:73:18)
unter /Users/manish.gowardipe/Desktop/projects/esw-ts/lib/node_modules/@jest/core/build/TestScheduler.js:418:65
bei Array.forEach ()
bei TestScheduler._addCustomReporters (/Users/manish.gowardipe/Desktop/projects/esw-ts/lib/node_modules/@jest/core/build/TestScheduler.js:411:15)

Hallo, ich möchte die native Unterstützung für ES-Module in meinem kleinen Projekt testen, aber ich bin neu bei NodeJS und habe mich in dieser Ausgabe verirrt. Ich würde mich über eine Anleitung freuen.

  • node --version : v14.5.0
  • yarn jest --version : 26.1.0
  • Ich versuche dieses kleine Projekt zu testen, ist sehr einfach.
  • Ich habe meine Dateien wie folgt:

Paket.json

{
"jest": {
    "transform": {},
    "testEnvironment": "jest-environment-node"
  }
}

markov.test.js

const fs = require("fs");
const Markov = require("./markov.mjs");
// import fs from "fs";
// import Markov from "./markov.mjs";

const file = fs.readFileSync("text.txt", "utf8");
const markov = new Markov(file.toString());

test("Generates sentence with especified words", () => {
  expect(markov.makeSentence(8).length).toBe(8);
});
  • Ich führe yarn jest . und bekomme diesen Fehler:
    imagen

  • Ich habe es mit node node_modules/jest/bin/jest.js . versucht und es gibt mir den gleichen Fehler.

@pepetorres1998 In diesem Thread geht es darum, Jest mit nativen esm-Modulen auszuführen, was das Ausführen von Dingen mit bestimmten Flags/Optionen beinhaltet - siehe den Kommentar oben für was zu tun ist (und setze "type": "module" in package.json). Ehrlich gesagt, ist es zu diesem Zeitpunkt noch nicht ganz bereit für die Hauptsendezeit. Wenn Sie also Ihr Projekt brauchen, um zu funktionieren, bleibe ich vielleicht bei Babel. Es gibt eine Reihe von ungeprüften Problemen, die echte Showstopper sind. Ich habe vor ein paar Wochen genüsslich versucht zu wechseln und bin weinend zu Babel zurückgekommen.

Bekommt jemand anderes ReferenceError: jest is not defined wenn er versucht, Dinge wie jest.setTimeout(...) in einer Testdatei mit diesem Setup zu tun? Versuchen herauszufinden, ob dies mit der Modulumgebung, der Knotenversion, der Jest-Version oder einer Kombination dieser Dinge zusammenhängt. (Benutzt derzeit Knoten v14.5.0, jest 26.1.0, Umgebung jest-environment-node)

BEARBEITEN
Ich sehe jetzt das deaktivierte Kontrollkästchen in der Problembeschreibung für die jest-Eigenschaft 'global'. 🙃

@bdentino Ich denke, Sie können versuchen, es explizit zu importieren import {jest} from '@jest/globals';

25.4.0 wurde mit den ersten Support-Elementen veröffentlicht. Zusätzlich zu #9772, das oben erwähnt wurde, habe ich auch #9842 aufgenommen. In der _Theorie_ sollte das Mischen von CJS und ESM nun korrekt funktionieren (🤞).

Die einzige fehlende Funktion ist die Unterstützung des jest Objekts. Ich habe mich nicht entschieden, ob wir es bei import.meta festhalten oder von den Leuten verlangen sollen, es über import {jest} from '@jest/globals' zu importieren. Feedback erwünscht!

Ich habe noch keine Dokumente dafür geschrieben, aber um es zu aktivieren, müssen Sie 3 Dinge tun

  1. stellen Sie sicher , laufen Sie nicht verwandeln weg import Anweisungen (set transform: {} in Config oder auf andere Weise sicherzustellen babel die Datei nicht zu CJS verwandeln, wie die Vermeidung von modules Option zur Voreinstellungsumgebung)
  2. node@^12.16.0 || >=13.2.0 mit --experimental-vm-modules Flag ausführen
  3. Führen Sie Ihren Test mit jest-environment-node oder jest-environment-jsdom-sixteen

Bitte probieren Sie es aus und geben Sie Feedback! Wenn Sie Fehler melden, wäre es wunderbar, wenn Sie auch angeben könnten, wie derselbe Code (ohne testspezifischen Code) in Node. Ich habe https://nodejs.org/api/esm.html in den letzten Wochen _viel_ gelesen, aber wahrscheinlich habe ich etwas übersehen.

@SimenB
Dieser Thread wurde enorm, und ich denke, diejenigen, die mit Scherz beginnen / ES-Module verwenden möchten, werden Schwierigkeiten haben, die grundlegenden Richtlinien zu finden und zu verstehen, um damit anzufangen.
Gibt es in den Dokumenten eine formelle Erklärung zum Hinzufügen von Scherz zu einem ES-Modulprojekt (oder einem "Schnellstart")?

@aldeed Haben Sie in Bezug auf Ihr Problem mit dem Verspotten von Modulen aus demselben Projekt eine Lösung gefunden? Ich habe genau das gleiche Problem

(Übrigens verwenden wir auch Reactioncommerce, also Prost, haha)

@guilhermetelles nein, und es wird jetzt in https://github.com/facebook/jest/issues/10025 verfolgt.

Ich verwende Jest 26.1.0, node Version 14.6.0 mit --experimental-vm-modules , aber ich sehe immer noch ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING wenn ich import() innerhalb von CommonJS verwende . Sollte ich versuchen, eine minimale Reproduktion zu erstellen und eine neue Ausgabe zu eröffnen?

Abgesehen davon, gibt es eine einfache Möglichkeit, yarn link eine Kopie von jest Paketen in ein Projekt zu integrieren, jetzt wo Jest Garnbeere verwendet? Ich wollte das neueste master ausprobieren, nur für den Fall, dass dies von noch nicht veröffentlicht wurde. Ich habe versucht, etwas wie path/to/facebook/jest/.yarn/releases/yarn-sources.cjs link --all path/to/jest zu tun, aber es würde fehlschlagen. Das manuelle Ausführen von etwas wie cd node_modules; for p in jest*; do if [[ -d path/to/jest/packages/$p ]]; then rm -rf $p; ln -s path/to/jest/packages/$p; fi; done funktionierte auch nicht, ich bin mir nicht sicher warum.

@vvanpo import() in CJS wurde in Node zurückgesetzt, Sie können https://github.com/nodejs/node/issues/31860 folgen

Was das Ausführen von local angeht, deinstalliere ich normalerweise nur jest aus dem Projekt, das ich testen möchte, und mache ../jest/jest . Potenziell nose ../jest/packages/jest/bin/jest.js . Stellen Sie einfach sicher, dass Sie zuerst yarn und yarn build:js ausführen. Wenn diese Anweisungen nicht funktionieren (ich schreibe aus dem Gedächtnis auf einem Telefon in einem Flugzeug), öffnen Sie bitte ein Problem (oder PR), damit wir dies richtig in die Datei CONTRIBUTING.md schreiben können

Planen Sie zyklische Importe zu unterstützen?

Wenn ich eine Dummy-Testdatei habe, die nur eine von zwei Dateien importiert, die sich nur gegenseitig importieren, erhalte ich RangeError: Maximum call stack size exceeded . Wenn ich einen der Importe entferne, besteht der Test. Repo, das das Problem reproduziert .

Hallo! Ich habe dies in einem leeren Knotenprojekt eingerichtet und es hat wirklich gut funktioniert, aber in unserer Produktionsumgebung erhalte ich die folgende Fehlermeldung, wenn ich versuche, Tests auszuführen:

ES Modules are only supported if your test environment has the 'getVmContext' function

Ich habe in einer früheren Antwort (von @cyberwombat ) gesehen, dass jemand anderes das Problem hatte, aber das Paket, das als Schuldiger package.json Datei vorhanden. Wie kann man das Paket (oder die Einstellung) ableiten, das das Problem verursacht? Ich habe versucht, systematisch jede Scherzeinstellung zu entfernen, die nicht notwendig ist, damit dies funktioniert, aber ich hatte keinen Erfolg.

UPDATE : Ich habe es geschafft, Fortschritte zu machen, indem ich eine kleine Änderung in jest-runtime . Ich habe den Debugger in der Zeile gestoppt, die versucht, auf den VM-Kontext zuzugreifen, und während die Funktion wirklich nicht existiert, ist this.context (die sie zurückgeben sollte) tatsächlich vorhanden, also habe ich diese Zeile geändert, um direkt auf die Eigenschaft zuzugreifen. Ich weiß, dass dies wahrscheinlich nicht ideal ist, aber @SimenB könnte Ihnen dies eine Vorstellung davon geben, was schief läuft?

Vielen Dank im Voraus für jede Hilfe

Planen Sie zyklische Importe zu unterstützen?

Bestimmt! Könnten Sie ein separates Thema eröffnen?


@zsombro scheint, als würden Sie eine alte Version der Testumgebung jest --show-config ausführen, was wird von testEnvironment angezeigt?

Es sieht so aus, als ob Sie eine alte Version der Testumgebung ausführen. Wenn Sie jest --show-config ausführen, was wird von testEnvironment angezeigt?

@SimenB steht folgendes:

"testEnvironment": "/Users/zberki/git/project-name/node_modules/jest-environment-node/build/index.js",
"testEnvironmentOptions": {},

Ich habe es einfach auf jest-environment-node basierend auf deinen Anweisungen

Bevor ich diesen Vorgang gestartet habe, habe ich jest mit yarn add jest@latest aktualisiert. Muss ich die Umgebung separat aktualisieren?

UPDATE: Es stellte sich heraus, dass ich es musste. Ich habe node_modules und yarn.lock gelöscht, um eine Neuinstallation durchzuführen, und es hat immer noch nicht funktioniert. Wenn ich es jedoch manuell mit yarn add -D jest-environment-node hinzufüge, scheint es zu funktionieren. Gibt es eine bessere Möglichkeit, dies zu verwalten? Ich habe ein minimalistisches Testprojekt durchgeführt, bevor ich dies auf unserer Codebasis getan habe, und ich musste dies nicht tun

yarn list jest-environemnt-node (oder npm list jest-environemnt-node ) werden wahrscheinlich mehrere auflisten, nehme ich an

├─ [email protected]
│  └─ [email protected]
└─ [email protected]

die 26.2.0 Version ist wahrscheinlich die, die ich manuell installiert habe (zumindest basierend auf package.json , was bedeutet, dass jest-config eine Version installiert hat, die anscheinend veraltet ist?

Sie haben etwas anderes, das eine ältere Version von jest-config ( react-scripts vielleicht (Teil von create-react-app )?). Dieses Thema ist nicht der Ort, um es zu diskutieren, aber

ES-Module in meinem globalSetup nicht verwenden zu können, fängt an weh zu tun.

Zwei Punkte:

  • sollte dies am Anfang dieser Ausgabe als Kontrollkästchen erwähnt werden (damit es verfolgt wird)?
  • Wenn es eine Alpha/Beta gibt, die ich versuchen könnte, bin ich bereit, dies zu tun

ICH:

  • Sichergestellt, dass ich die neueste Jest-Version (26.4.0) verwende
  • Jest-Environment-Node zu meinem Projekt hinzugefügt
  • Stellen Sie sicher, dass es nicht dupliziert wird, indem Sie die Sperrdatei überprüfen
  • "testEnvironment": "jest-environment-node", in jest.config.json hinzugefügt
  • import { jest } from '@jest/globals'; hinzugefügt, wo immer Scherze verwendet wurde
  • Testbefehlseinstellung --experimental-vm-modules indem er mit NODE_OPTIONS='--experimental-vm-modules' yarn jest

Und es stürzt bei folgendem Code ab:

jest.mock('../../some/other/path', () => ({
  someOtherMethod: jest.fn().mockImplementation(…),
}));

mit folgendem Fehler (gekürzt - Hinweis "Erlaubte Objekte"!):

ReferenceError: src/foo/bar.spec.js: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
Invalid variable access: jest
Allowed objects: Array, …, jest, …, unescape.
Note: This is a precaution to guard against uninitialized mock variables. If it is ensured that the mock is required lazily, variable names prefixed with `mock` (case insensitive) are permitted.

Ich kann Babel nicht verwenden, weil es Importe, die ich für die Ausführung auf Node 14 ohne Babel festgelegt habe, falsch analysiert:

-import { map } from 'lodash';
+import lodash from 'lodash';
+const { map } = lodash;

Was leider von @babel/preset-env falsch geparst wird , was zu TypeError: Cannot destructure property 'map' of '_lodash.default' as it is undefined. .

Kann mir bitte jemand helfen, dieses Problem zu umgehen?

Bearbeiten: Es scheint, als ob Sie Jest + Babel auf mit nativem ES-Modulen kompatiblem Code mit CommonJS-Importen verwenden können, indem Sie diesen absolut ekelhaften Fix durchführen:

jest.mock('common-js-module', () => ({
  __esModule: false,
  ...jest.requireActual('common-js-module'),
}));

Diesen Weg,

import lodash from 'lodash';
const { map } = lodash;

wird von Node 14 und dem Code, der sich aus der Ausführung von Jest+Babel ergibt, perfekt verbraucht,

var _lodash = _interopRequireDefault(require("lodash"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const {
  map
} = _lodash.default;

läuft auch.

Wir haben alle unsere Scherztests erfolgreich konvertiert, um unseren ES6-Code zu verwenden und zu importieren, aber wir sind bei einigen Paketen hängen geblieben: nämlich puppeteer und uuid

Die App funktioniert nur, wenn wir sie in ein Objekt importieren (wie import uuid from 'uuid' ), aber die Tests werden nicht auf diese Weise ausgeführt. Wenn wir diesen Import jedoch durch die Dekonstruktionssyntax (wie import { v4 } from 'uuid' ersetzen, ist es umgekehrt: Der Test funktioniert, aber die App löst eine Ausnahme aus.

ursprünglich sind wir der Anleitung gefolgt und haben jede Transformation deaktiviert, aber wir haben auch versucht, einen Garn-Workspace zu erstellen, in dem wir Babel mit einer minimalen Knotenkonfiguration installiert haben, aber dies hat dieses spezifische Problem nicht gelöst (oder verschlimmert)

Wenn wir diesen Import jedoch durch die Dekonstruktionssyntax ersetzen (wie import { v4 } from 'uuid', dann ist es umgekehrt: Der Test funktioniert, aber die App wirft eine Ausnahme aus.

Das hört sich so an, als wäre Ihre App in CommonJS kompiliert und verwendet in der Praxis keine Module. Von "echtem" ESM sollte import uuid from 'uuid' nicht funktionieren, da uuid keinen Standardexport hat und einen ESM-Build für node verfügbar macht .

Hey @SimenB , denkst du, dass eine vorläufige Dokumentation dazu eine gute Idee wäre?

@grantcarthew definitiv! Ich hatte gehofft, ich könnte mehr Zeit damit verbringen und es für Jest 27 stabilisieren, aber ich bezweifle, dass ich das schaffen werde. Aber eine Dokumentationsseite darüber zu schreiben, was es jetzt gibt (und dass es experimentell ist) klingt nach einer guten Idee

@SimenB Ich weiß nicht, wie der aktuelle Stand des Problems ist und ob Jest schon mit meinem Fall arbeiten sollte oder nicht, aber vielleicht kann es dir irgendwie helfen.

Ich versuche, eine nur esm-Bibliothek zu laden (ihre Erweiterung ist cjs, aber der Typ ist module und node scheint damit in Ordnung zu sein), aber Jest lädt sie nicht richtig mit Fehler:

    C:\dev\codemirror-next-repro-cra\test-in-jest-esm\node_modules\style-mod\dist\style-mod.cjs:15
    export var StyleModule = function StyleModule(spec, options) {

Hier das Problem, das ich ursprünglich geöffnet habe https://github.com/codemirror/codemirror.next/issues/310. Und ein Repro für Jest + ESM, das mit Knoten 14.13.1 fehlschlägt https://github.com/dubzzz/codemirror-next-repro-cra/tree/main/test-in-jest-esm

@dubzzz Sie können ESM nicht in einer cjs Datei haben. Knoten fällt auch aus

$ node node_modules/style-mod/dist/style-mod.cjs
(node:48829) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/Users/simen/repos/codemirror-next-repro-cra/test-in-jest-esm/node_modules/style-mod/dist/style-mod.cjs:15
export var StyleModule = function StyleModule(spec, options) {
^^^^^^

SyntaxError: Unexpected token 'export'
    at wrapSafe (internal/modules/cjs/loader.js:1172:16)
    at Module._compile (internal/modules/cjs/loader.js:1220:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1277:10)
    at Module.load (internal/modules/cjs/loader.js:1105:32)
    at Function.Module._load (internal/modules/cjs/loader.js:967:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

Ups, tut mir leid, ich habe es auf der Knotenseite zu schnell versucht. @nicolo-ribaudo hat den Autor der Bibliothek bereits über dieses Problem informiert.
Wirklich vielen Dank für deine schnelle Antwort.

Ich habe hier eine PR für einige (ziemlich stumpfe) Dokumente geöffnet: # 10611. Ich habe mir nicht die Mühe gemacht, fehlende Funktionen/Bugs aufzuzählen, da ich denke, dass es schwer sein wird, mit der Realität in Einklang zu bleiben, und die Betrachtung von Github-Problemen ist ein besserer Ansatz, da sie (hoffentlich ...) aktuell sind.

@Pomax als neue Ausgabe bitte 🙂

Ich habe gerade #10620 geöffnet, das Unterstützung für import() von CJS hinzufügt. Ein paar Mal angefordert sind wie https://github.com/facebook/jest/issues/9430#issuecomment -626054595

Hallo. Es ist ziemlich schwer für mich, die ganze Geschichte hinter ESM in Node/Jest schnell zu erfassen, daher frage ich wahrscheinlich etwas Offensichtliches oder bereits Beantwortetes. Verstehe ich es richtig, dass der folgende Fall noch nicht unterstützt wird? Oder ich hoffe, ich mache etwas nicht richtig? Ich erlebe es als würde import x from 'x' funktionieren, aber import { sub } from 'x' Destrukturierung nicht.

package.json:

{
  "name": "jest-uuid",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "test": "node --experimental-vm-modules node_modules/.bin/jest"
  },
  "devDependencies": {
    "jest": "26.5.2"
  },
  "dependencies": {
    "uuid": "8.3.1"
  }
}

f.spec.js

import { v4 } from 'uuid';
test('', () => {});

npm-Test

> npm test

> [email protected] test /Users/igoro/p/tmp/jest-uuid
> node --experimental-vm-modules node_modules/.bin/jest

 FAIL  ./f.spec.js
  ● Test suite failed to run

    SyntaxError: The requested module 'uuid' does not provide an export named 'v4'

      at jasmine2 (node_modules/jest-jasmine2/build/index.js:228:5)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.879 s
Ran all test suites.
(node:94492) ExperimentalWarning: VM Modules is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
npm ERR! Test failed.  See above for more details.

Sie warten auf #9771. Vorher weiß Jest nicht, dass es sicher ist, uuid als ESM zu laden (oder besser gesagt, welche Datei zu welchem ​​Zeitpunkt geladen werden soll, es würde wissen, dass es sich um ESM handelt).

Wird dies der Node-eigenen Konvention folgen, bei der CJS nur als Namespace geladen werden kann, oder wird dies "verbessert", indem eine Syntax zugelassen wird, die in Node selbst nicht funktioniert? (zB Node lässt import { readdirSync } from "fs-extra" weil dies ein CJS-Paket ist, aber es erlaubt import fs from "fs-extra"; das dann mit const { readdirSync } = fs entpackt werden kann).

(zB erlaubt Node nicht import { spawn } from "child_process", weil dies ein CJS-Paket ist, aber es erlaubt import child_process von "child_process"; das kann dann mit const { spawn } = child_process; entpackt werden).

Dies ist ein unglückliches Beispiel, da der Knoten "child_process" als "eingebautes" (und nicht als CJS-)Modul betrachtet, sodass benannte Exporte funktionieren. Das neueste nodejs verwendet auch eine Heuristik, damit viele benannte Exporte für CJS-Module funktionieren. Das ist vielleicht am schwierigsten nachzuahmen.

Beispiel aktualisiert, um stattdessen fs-extra verwenden. Aber wenn benannte Exporte auf der Roadmap von Node stehen, um entweder diesen oder den nächsten Major zu landen, dann macht es Sinn, Jest vorwegzunehmen.

Das sollte bereits implementiert sein - Node-Core-Module legen benannte Exporte offen, "normales" CJS nicht.

Das neueste nodejs verwendet auch eine Heuristik, damit viele benannte Exporte für CJS-Module funktionieren. Das ist vielleicht am schwierigsten nachzuahmen.

Haben Sie einen Link zu der PR, die ihn umsetzt? Wir sollten versuchen, es zumindest nachzuahmen 🙂

Die PR ist hier: https://github.com/nodejs/node/pull/35249

Die Heuristik dahinter wird als cjs-module-lexer (https://github.com/guybedford/cjs-module-lexer) veröffentlicht, aber @guybedford weiß möglicherweise mehr über mögliche Abweichungen.

Habe mir das gerade angesehen und es sieht so aus, als ob fs-extra ein Exportmuster verwendet wie:

module.exports = {
  // Export promiseified graceful-fs:
  ...require('./fs'),
  // Export extra methods:
  ...require('./copy-sync'),
  ...require('./copy'),
  ...require('./empty'),
  ...require('./ensure'),
  ...require('./json'),
  ...require('./mkdirs'),
  ...require('./move-sync'),
  ...require('./move'),
  ...require('./output'),
  ...require('./path-exists'),
  ...require('./remove')
}

Dies ist derzeit kein von uns erkannter Fall der Reexportanalyse, aber es könnte möglich sein, cjs-module-lexer hinzuzufügen, wenn dies ein nützlicher Fall für die Erkennung benannter Exporte wäre.

Danke @jkrems & @guybedford! Ich habe jetzt mit diesem Modul eine PR geöffnet: #10673

Die genaue fs-extra-Unterstützung, die in https://github.com/facebook/jest/issues/9430#issuecomment -713204282 beschrieben ist, ist jetzt in [email protected] , Upstream-Tracking unter https://github implementiert. com/nodejs/node/pull/35745.

_Update: Beim Testen dieses Builds werden alle fs-extra-Funktionen korrekt erkannt, aber leider werden die nativen Node.js-Funktionen nicht erkannt, da sie nicht statisch analysiert werden können, da sie von einer for-Schleife aufgefüllt werden._

feat: unterstützt benannte Exporte von CJS als benannte ESM-Importe #10673

Ich dachte, natives ESM unterstützt nur das Importieren der exports eines CommonJS-Moduls als default ?

Hallo. Es ist ziemlich schwer für mich, die ganze Geschichte hinter ESM in Node/Jest schnell zu erfassen, daher frage ich wahrscheinlich etwas Offensichtliches oder bereits Beantwortetes. Verstehe ich es richtig, dass der folgende Fall noch nicht unterstützt wird? Oder ich hoffe, ich mache etwas nicht richtig? Ich erlebe es als würde import x from 'x' funktionieren, aber import { sub } from 'x' Destrukturierung nicht.

...
import {v4} von 'uuid';

ESM-Module unterstützen keine destrukturierenden Importe, obwohl die Syntax so aussieht. Damit dies funktioniert, wird 'export v4' benötigt. 'Exportstandard' wird nicht übereinstimmen.

https://kentcdodds.com/blog/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution

@sdwlig uuid bietet benannte Exporte und hat keinen Standard. Es sollte funktionieren, aber das Laden von esm aus Paketen mit dem Feld "Exporte" wird von jest noch nicht unterstützt. Stattdessen wird Commonjs geladen, das nur über den Standardexport verfügbar ist.
https://github.com/uuidjs/uuid/blob/master/src/index.js

Könnten wir die Unterstützung für die Paketselbstreferenz (#10883) hinzufügen?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen