Jest: Meta: Dukungan asli untuk Modul ES

Dibuat pada 19 Jan 2020  ·  131Komentar  ·  Sumber: facebook/jest

EDIT: panduan cepat untuk memulai: https://jestjs.io/docs/en/ecmascript-modules

Dukungan ESM tidak akan ditandai dalam rilis Node 12 mendatang (mungkin tidak sebelum April https://github.com/nodejs/node/pull/29866#issuecomment-574055057) dan sudah tidak ditandai di Node 13.2, jadi saya pikir itu waktu untuk mengevaluasi bagaimana kami dapat menambahkan dukungan asli di Jest. Saya akan mencoba membuat daftar fitur mana yang saat ini disediakan oleh Jest yang dipengaruhi oleh dukungan ESM, dan bagaimana kami dapat menyelesaikan/menyelidikinya.

Ada masalah #4842, tapi saya pikir itu lebih merupakan masalah diskusi, sementara masalah ini akan diarahkan untuk benar-benar menerapkan dukungan dan lebih cocok untuk dilacak bagi mereka yang hanya ingin mendapatkan status implementasi saat ini. Setiap komentar yang ditambahkan ke masalah ini _not_ terkait dengan bagaimana kami dapat menerapkan dukungan untuk fitur yang disebutkan di bawah ini akan ditandai sebagai spam - harap arahkan solusi/diskusi apa pun ke masalah yang terpisah. Juga jangan ragu untuk memberi tahu kami jika ada sesuatu yang terkait dengan fitur ESM yang hilang dari daftar!

Harap dicatat bahwa Jest akan menggunakan vm API (https://nodejs.org/api/vm.html) dan pada saat penulisan (node ​​v13.6) bagian ESM dari API ini masih ditandai ( --experimental-vm-modules ). Jadi mengatakan ESM tidak ditandai adalah sedikit keliru saat ini. Tapi saya pikir kita harus mulai bereksperimen dan berpotensi memberikan umpan balik ke Modul WG .

Terakhir, saya menulis masalah ini sebagian besar untuk orang-orang yang akan menerapkan dukungan, jadi ini akan menjadi level rendah dan spesifik untuk cara kerja Jest. Untuk orang-orang yang _hanya_ ingin tahu apakah dukungan telah masuk atau tidak, saya sarankan menggunakan "pemberitahuan khusus" GH yang luar biasa dan hanya berlangganan pemberitahuan saat penutupan/pembukaan kembali.


  • [x] Menjalankan modul dalam konteks yang benar

Kami mencapai kotak pasir dengan menjalankan skrip dalam vm.Context (baik disediakan oleh JSDOM atau API inti simpul). Kita perlu melakukan hal yang sama untuk ESM, tetapi kita memerlukan akses ke context selama konstruksi modul, bukan hanya saat menjalankan modul. Saya telah membuka #9428 yang menambahkan API yang diperlukan ke JestEnvironment .

  • [x] Global

expect , test , beforeEach dll masih akan ditambahkan sebagai global, tidak ada yang berubah di sini. jasmine global juga akan tetap ada.

  • [x] jest properti "global"

Ini tidak benar-benar global - itu disuntikkan ke dalam lingkup modul. Karena ruang lingkup modul hilang di ESM, kita perlu memindahkannya ke suatu tempat. Menambahkannya ke import.meta tampaknya wajar - ada opsi bernama initializeImportMeta yang dapat kita gunakan.

EDIT: Solusi di sini adalah mengambilnya melalui import {jest} from '@jest/globals' . Kami mungkin masih menambahkannya melalui import.meta di masa mendatang, tetapi ini sudah cukup untuk saat ini.

  • [ ] jest.(do|un)mock

Karena ESM memiliki "tahapan" yang berbeda saat mengevaluasi modul, jest.mock tidak akan berfungsi untuk impor statis. Ini dapat bekerja untuk impor dinamis, jadi saya pikir kita hanya perlu memperjelas dokumen tentang apa yang didukungnya dan apa yang tidak.

jest.mock panggilan diangkat, tetapi itu tidak membantu dalam ESM. Kami mungkin mempertimbangkan untuk mengubah import 'thing' menjadi import('thing') yang seharusnya memungkinkan pengangkatan berfungsi, tetapi kemudian menjadi asinkron. Menggunakan await mungkin merupakan kebutuhan untuk pendekatan semacam itu. Saya juga berpikir itu cukup invasif untuk menjamin opsi terpisah. Sesuatu untuk didiskusikan - kita tidak perlu mendukung semua yang jest.mock dapat lakukan untuk rilis awal.

  • [ ] jest.requireActual

Tidak yakin bagaimana seharusnya berperilaku di ESM. Haruskah kita memberikan jest.importActual dan membiarkan requireActual mengevaluasi CJS ?

  • [x] import.meta

Node memiliki url sebagai satu-satunya propertinya (setidaknya untuk saat ini). Kita perlu memastikan itu diisi di Jest juga. Kami menyediakan identifier alih-alih filename ketika membangun modul jadi saya tidak berpikir itu akan terjadi secara otomatis, tetapi url pada dasarnya filename dilewatkan meskipun pathToFileURL .

Ada juga PR terbuka untuk import.meta.resolve : https://github.com/nodejs/node/pull/31032

  • [x] import thing from 'thing'

Ini sebenarnya cukup mudah, kita hanya perlu mengimplementasikan linker mana kita juga dapat mengubah sumber sebelum mengembalikannya, artinya kita tidak memerlukan API pemuat (yang belum ada). Ini memungkinkan kita untuk mengembalikan tiruan juga (walaupun itu harus berasal dari direktori __mocks__ ).

  • [x] import('thing')

Pada dasarnya sama seperti di atas, tetapi diteruskan sebagai importModuleDynamically saat membuat modul. Juga akan mendukung jest.mock , jest.resetModules dll lebih bersih, jadi kemungkinan besar akan digunakan sedikit.

Ini juga dapat dilakukan untuk vm.Script melalui opsi yang sama.

  • [ ] Menangani kesalahan selama evaluasi

Saat ini kesalahan runtime (misalnya modul tidak ditemukan), tapi itu belum tentu benar dengan ESM. Apakah itu penting bagi kita? Kami harus memverifikasi kesalahan masih terlihat bagus.

  • [x] module.createRequire

Kita perlu menangani ini untuk orang yang ingin menggunakan CJS dari ESM. Saya telah membuka #9426 untuk melacak ini secara terpisah karena penerapannya tidak terlalu terkait dengan dukungan ESM.

EDIT: Diimplementasikan di #9469

  • [ ] module.syncBuiltinESMExports

https://nodejs.org/api/modules.html#modules_module_syncbuiltinesmexports. Apakah kita peduli tentang itu, atau hanya membuatnya tidak cukup? Tidak yakin seperti apa use case di Jest. Bermain-main dengan builtin sudah memecahkan kotak pasir dan saya rasa ini tidak masalah.

EDIT: # 9469 membuat ini menjadi no-op. Saya pikir itu baik-baik saja?

  • [ ] Mendeteksi apakah suatu file seharusnya dalam mode ESM atau CJS

Memeriksa bidang type di package.json modul tampaknya masuk akal: https://nodejs.org/api/esm.html#esm_enabling. Haruskah kita juga memiliki flag konfigurasi sendiri? Juga perlu menghormati akhiran file.

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

  • [x] moduleNameMapper

Tidak yakin apakah ini berdampak pada apa pun. Saya _think_ tidak karena kita sendiri yang akan menghubungkan modul-modul tersebut. Perlu penyelidikan, meskipun.

EDIT: Ini semua logika resolusi, yang kami kendalikan. Jadi tidak ada perubahan di sini.

  • [x] jest.config.mjs

Melalui #9291 kami mendukung jest.config.cjs - apakah kami perlu melakukan sesuatu yang khusus untuk .mjs ? Mungkin menggunakan import('path/to/configFile.mjs') yang berarti harus asinkron. Apakah ini masalah? Mungkin layak untuk membuat resolusi konfigurasi async di Jest 25 jadi itu bukan pemblokir untuk dukungan tambahan ESM di Jest 25.

EDIT: #9431

  • [ ] Ekspor Paket

Node mendukung ekspor paket , yang agak memetakan ke moduleNameMapper Jest, tetapi juga menyediakan fitur enkapsulasi. Mudah-mudahan resolve akan mengimplementasikan ini, tetapi jika tidak, kita perlu melakukan sesuatu. Mungkin cukup untuk menggunakan opsi pathFilter ? Tidak yakin.

  • [ ] Modul JSON/WASM

https://nodejs.org/api/esm.html#esm_experimental_json_modules. Apakah kita perlu peduli? Mungkin, terutama untuk json . Ini sepele bagi kami untuk mendukung import thing from './package.json' karena kami mengontrol fase penautan, tetapi kami mungkin tidak melakukannya secara default karena akan berbeda dari node default. Haruskah kita memaksa orang untuk mendefinisikan transformasi untuk itu?

  • [x] Cakupan kode

Apakah itu penting? Saya tidak berpikir itu terpengaruh karena kami masih dapat mengubah sumber dengan babel (mungkin akan bingung dengan pernyataan import , mungkin tidak) dan cakupan V8 pasti tidak peduli. Kita harus memverifikasi sekalipun.

  • [ ] Resolusi kode asinkron

Ini sama sekali bukan pemblokir karena resolusi sinkronisasi akan berfungsi dengan baik. Tapi kami _can_ menggunakan resolusi async sekarang, yang sangat bagus. Saya ingin tahu apakah kita harus melihat hanya menggunakan modul resolve dari npm lagi, karena sudah mendukung async. Lihat #9505.

  • [ ] Transformasi kode asinkron

Mirip dengan di atas, tidak memblokir, tetapi alangkah baiknya untuk mendukungnya. Mungkin membuat @jest/transformer lebih bermanfaat di lingkungan lain juga. Lihat #9504.

  • [ ] Performa buruk saat mengakses global

Karena #5163 kami memiliki opsi extraGlobals sebagai solusi - solusi tersebut tidak lagi dapat dijalankan di ESM. Saya telah membuka dan mengeluarkan simpul di sini: https://github.com/nodejs/node/issues/31658

ES Modules

Komentar yang paling membantu

Saya telah mendapatkan dukungan yang sangat mendasar dengan #9772. Saya hanya menguji kasus yang paling sederhana, dan ada banyak batasan yang diketahui (terutama tidak ada dukungan objek jest dan semantik yang rusak saat mencampur CJS dan ESM), tetapi setidaknya itu _something_. Itu akan keluar di rilis Jest berikutnya (semoga segera, hanya diblokir oleh #9806)

Semua 131 komentar

Saya telah mendapatkan dukungan yang sangat mendasar dengan #9772. Saya hanya menguji kasus yang paling sederhana, dan ada banyak batasan yang diketahui (terutama tidak ada dukungan objek jest dan semantik yang rusak saat mencampur CJS dan ESM), tetapi setidaknya itu _something_. Itu akan keluar di rilis Jest berikutnya (semoga segera, hanya diblokir oleh #9806)

25.4.0 telah dirilis dengan dukungan pertama. Selain #9772 yang disebutkan di atas, saya juga menyertakan #9842. Dalam _theory_ pencampuran CJS dan ESM harus bekerja dengan benar sekarang (🤞).

Satu fitur utama yang hilang adalah mendukung objek jest . Saya belum memutuskan apakah kita harus tetap menggunakan import.meta atau meminta orang untuk mengimpornya melalui import {jest} from '@jest/globals' . Umpan balik dihargai!

Saya belum menulis dokumen untuk ini, tetapi untuk mengaktifkannya Anda perlu melakukan 3 hal

  1. pastikan Anda tidak menjalankan transformasi diri import pernyataan (set transform: {} di config atau memastikan babel tidak mengubah file ke CJS, seperti menghindari modules opsi ke preset-env)
  2. Jalankan node@^12.16.0 || >=13.2.0 dengan flag --experimental-vm-modules
  3. Jalankan pengujian Anda dengan jest-environment-node atau jest-environment-jsdom-sixteen

Silakan mencobanya dan berikan umpan balik! Jika melaporkan bug, alangkah baiknya jika Anda juga dapat menyertakan cara menjalankan kode yang sama (dikurangi kode khusus pengujian apa pun) berjalan di Node.js. Saya telah membaca https://nodejs.org/api/esm.html _a lot_ selama beberapa minggu terakhir, tetapi saya mungkin melewatkan sesuatu.

Satu fitur utama yang hilang adalah mendukung objek lelucon. Saya belum memutuskan apakah kita harus menempelkannya ke import.meta atau mengharuskan orang untuk mengimpornya melalui import {jest} dari '@jest/globals'.

Untuk kasus penggunaan TypeScript, lebih baik memiliki impor eksplisit.

Yup, saya telah menambahkan (dan mengembalikan sementara) paket @jest/globals yang mendukung ini, sehingga akan tersedia terlepas dari itu. Saya ingin tahu apakah masuk akal untuk _also_ mengeksposnya di import.meta . Saat ini condong ke arah tidak melakukannya, terutama karena lebih mudah untuk menambahkan daripada menghapus nanti (dan saya pribadi bukan penggemar global)

+1 untuk impor eksplisit, ini sedikit lebih bertele-tele tetapi lebih mudah dipahami

Saya mendapatkan ini di Node 13.2 & Jest 25.4: ES Modules are only supported if your test environment has the getVmContext function Apa yang saya lewatkan?

@zandaqo Oh maaf, lupa poin itu. Ditambahkan di atas, tapi itu

Jalankan pengujian Anda dengan jest-environment-node atau jest-environment-jsdom-sixteen

ReferenceError: jest is not defined Saya menduga ini karena @jest/globals hilang

Ya, seperti yang disebutkan ini hanya akan berfungsi jika Anda tidak menggunakan objek jest .
Mock juga mungkin rusak, belum diuji

Saya telah mengkompilasi proyek yang sangat mendasar dari apa yang saya lihat di direktori tes e2e ( e2e/native-esm/__tests__/native-esm.test.js ) dan dalam masalah ini. Dan sayangnya saya masih tidak bisa membuatnya bekerja Adakah yang bisa memeriksanya?

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

  • [x] versi lelucon 25.4.0
  • [x] versi simpul v13.12.0
  • [x] package.json berisi opsi lelucon yang direkomendasikan dan sepertinya tidak ada transformasi babel

Menjalankan contoh skrip (hanya mengimpor fungsi double dan mencetak double(2) ):

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

Menjalankan lelucon hanya dengan satu tes untuk fungsi ganda:

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.

Anda perlu menjalankan node dengan --experimental-vm-modules dan nama yang Anda ajukan .mjs atau "type": "module" di package.json .

EDIT: Anda mungkin memiliki yang terakhir karena berfungsi di luar Jest untuk Anda, hanya melewatkan flag eksperimental ke Node

@SimenB oh wow ada --experimental-vm-modules DAN --experimental-modules . Saya bingung dengan kenyataan bahwa --experimental-modules tidak diperlukan mulai dari beberapa versi node 13. Terima kasih!

TLDR: node --experimental-vm-modules node_modules/jest/bin/jest.js bekerja untuk saya

Ya, dari OP

Harap dicatat bahwa Jest akan menggunakan vm API (https://nodejs.org/api/vm.html) dan pada saat penulisan (node ​​v13.6) bagian ESM dari API ini masih ditandai ( --experimental-vm-modules ). Jadi mengatakan ESM tidak ditandai adalah sedikit keliru saat ini.

Luar biasa bahwa itu bekerja untuk Anda!

(Saya akan menandai komentar ini sebagai terselesaikan)

@SimenB Terima kasih untuk ini! Dua masalah yang saya lihat sejauh ini.

masalah 1

  • File uji unit ESM mengimpor default dari file ESM (fn sedang diuji)
  • File ESM yang sedang diuji mengimpor default dari sebuah paket, yang hanya mengekspor CJS
  • Hasil dalam kesalahan: ReferenceError: module is not defined dalam file paket CJS

Jadi saya pikir ini mungkin tidak diterapkan dengan benar?

Pernyataan impor dapat mereferensikan modul ES atau modul CommonJS

Ini berfungsi dengan baik saat menjalankan aplikasi. Ekspor bernama dari CJS hanya dapat diimpor dengan menggunakan createRequire, tetapi ekspor default hanya dapat diimpor.

Edisi 2

Ketika saya tidak menemukan kesalahan di atas, saya menemukan yang ini:

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

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

Detail proyek

  • Node 12.14.1
  • Lelucon dan babel-gurauan 25.4.0
  • Babel terbaru dengan targets: { node: 12 } dan 2 plugin: babel-plugin-transform-import-meta dan rewire-exports . (Mencoba menghapus plugin import-meta tetapi mendapat kesalahan saat mengatakan untuk menambahkannya kembali.)
  • testEnvironment: "node" adalah satu-satunya konfigurasi
  • node --experimental-vm-modules node_modules/jest/bin/jest.js

Jika repo reproduksi akan membantu, beri tahu saya.

Terima kasih @aldeed!

Saya akan membahas masalah 1, yang memang terlihat seperti bug. EDIT: Harus diperbaiki melalui #9850

Masalah 2 membutuhkan node 12.16.0: https://nodejs.org/docs/latest-v12.x/api/vm.html#vm_class_vm_syntheticmodule

Saya akan mengubah centang di Jest (saat ini memeriksa vm.SourceTextModule yang tersedia di lebih banyak versi, tetapi kami juga membutuhkan SyntheticModule ).

Dikonfirmasi bahwa berjalan dengan 12.16.0 memperbaiki masalah saya 2. Akan menguji ulang masalah 1 setelah perbaikan itu dirilis. Jika tidak, menunggu objek jest untuk pengujian lebih lanjut, dan saya setuju bahwa itu harus diimpor.

Kerja yang luar biasa, @SimenB! Saya mencoba ini pada proyek kecil tetapi mengalami masalah dengan impor dinamis. Ini adalah kesalahan yang saya lihat:

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

Jika saya menghapus impor dinamis maka tes akan berjalan (tetapi gagal karena alasan lain, tentu saja). Tes yang sama saat ini bekerja dengan Mocha (yang mengirimkan dukungan ESM baru-baru ini).

Jika membantu, impor dinamis yang dimaksud dapat dilihat di sini: https://github.com/beejunk/firn.js/blob/switch-to-jest/lib/renderPage.js#L43 -L55

File tes ada di sini: https://github.com/beejunk/firn.js/blob/switch-to-jest/test/build.test.js. Versi Mocha yang berfungsi dapat dilihat di cabang master.

Beri tahu saya jika ada info lain yang berguna bagi saya.

Terima kasih @beejunk! Saya bertanya-tanya apakah mungkin ada kondisi balapan antara import s yang mengimpor modul yang sama sebelum ditautkan sepenuhnya. _Sepertinya_ itulah yang Anda lakukan di sini. Saya akan memperbaikinya hari ini, terima kasih atas laporannya!

EDIT: Diperbaiki di #9858. Menyalin perbaikan ke repo Anda:
image

Adakah yang berhasil membuatnya bekerja dengan TypeScript? node --experimental-vm-modules node_modules/jest/bin/jest.js mengembalikan SyntaxError: Cannot use import statement outside a module , meskipun package.json memiliki "type": "module" .

babel.config.cjs

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

jest.config.cjs

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

@ dandv Anda pada dasarnya memukul kasus ini: https://github.com/facebook/jest/pull/9772/files#r407255029

Bisakah Anda membuka masalah terpisah? Perlu mencari tahu apa yang harus dilakukan dengan ekstensi non-js

@SimenB : #9860. Terima kasih telah melihat.

@aldeed @beejunk 25.5.0 telah dirilis dengan perbaikan untuk masalah Anda. Jauhkan laporan bug datang

Oh, tambahan itu termasuk dukungan untuk import { jest } from '@jest/globals' bagi yang menunggu itu 👍

Terima kasih atas kerja cepat untuk semua ini, @SimenB! Saya pikir saya telah mengalami masalah lain.

Saya telah bereksperimen dengan menggunakan params kueri di jalur impor sebagai cara untuk menghilangkan cache modul di server pengembangan. Idenya adalah memiliki file watcher yang mendeteksi perubahan dalam komponen dan kemudian memperbarui jalur impor dengan parameter kueri arbitrer sehingga kode baru segera ditarik pada pemuatan halaman berikutnya tanpa harus me-restart server. Ini berfungsi saat menjalankan server dev. Namun, Jest melempar kesalahan berikut:

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

Berikut adalah contoh di mana parameter kueri digunakan: https://github.com/beejunk/firn.js/blob/switch-to-jest/lib/renderPage.js#L55 -L56

Jika saya menghapus params kueri maka tes akan lulus, meskipun tidak secara konsisten. Jika saya menjalankan satu suite (misalnya, npm test -- test/build.test.js ) tes lulus, tetapi jika saya menjalankan semua tes sekaligus mereka akan gagal sebagian besar waktu dengan kesalahan ambigu. Saya masih menggali masalah dengan tes yang tidak konsisten, tetapi saya pikir saya akan melaporkan masalah param kueri terlebih dahulu.

Terima kasih atas laporannya @beejunk. #6282 seharusnya menangani ini, tetapi itu juga ingin meneruskan kueri ke transformer dan sejenisnya, yang tidak kita perlukan di sini. Jadi mungkin masuk akal untuk hanya mendukung kueri secara internal di runtime untuk saat ini, dan biarkan #6282 hanya berurusan dengan meneruskan kueri itu.

Saya telah menambahkan sedikit kode untuk membuat cache modul bervariasi berdasarkan kueri: https://github.com/facebook/jest/blob/d425a49bd575e7167bc786f3c4f2833589091fa1/packages/jest-runtime/src/index.ts#L330 -L334

Tetapi tidak ada kode yang pernah memanggilnya dengan kueri. Saya pikir kita harus bisa melakukan resolvePath.split('?') dan semua harus bekerja.

Mengenai kesalahan yang tidak konsisten, saya akan melihat apakah repo itu mereproduksinya. Saya belum menguji kode ESM dengan tes secara paralel, hanya satu tes. Saya tidak yakin mengapa itu akan memengaruhi banyak hal, tetapi siapa yang tahu

@beejunk masalah kueri diperbaiki di 25.5.1. Saya belum punya waktu untuk menyelidiki masalah lainnya

Saya memiliki masalah yang menurut saya mungkin terkait dengan ini namun tidak diperbaiki di 25.X .

Saya akan mencoba merangkum escenario di bawah ini:

  • Anda memiliki tes dengan skrip pengaturan
  • Skrip pengaturan itu akan membutuhkan file secara dinamis, seperti pada:
    { default: generator } = require(path.resolve(f))
  • Segala sesuatu di dalam f tidak ditranspilasikan yang menyebabkan "kesalahan impor pengenal yang tidak terduga".

Ini juga terjadi jika saya mencoba dengan import()

Karena Anda menyebutkan transpilasi; jika Anda memiliki pengaturan yang mengubah import menjadi require masalah ini bukan tempat yang benar - masalah ini tentang dukungan asli.


Yang mengatakan - Anda tidak dapat require ESM, dan saya belum dapat menambahkan dukungan untuk import() dari CJS karena Node tidak memiliki API untuk itu. Dukungan untuk itu telah mendarat di Node master, tetapi belum dirilis: https://github.com/nodejs/node/pull/32985. Seperti yang dapat dilihat di PR rilis terkait, itu akan datang di 13.14.0 dan 14.1.0. Pada saat itu saya akan menerapkan dukungan untuk itu 👍

Anda seharusnya dapat menggunakan file setup .mjs .

@SimenB Ini bagus, tampaknya berfungsi di beberapa file pengujian sekarang! Ini sedikit proses untuk menyelesaikan perbedaan antara impor Babel dan Node di setiap file, menambahkan impor lelucon, dll., jadi saya mungkin menemukan lebih banyak masalah saat saya melakukannya di ratusan file pengujian.

Beberapa hal yang lebih banyak pertanyaan:

  • apa yang Anda katakan di komentar Anda sebelumnya tentang dukungan untuk import() dari cjs, apakah itu juga memungkinkan file konfigurasi Jest diberi nama jest.config.js ? Saat ini hanya berfungsi untuk saya ketika bernama jest.config.cjs dan menggunakan module.exports = (kesalahan adalah TypeError [ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING]: A dynamic import callback was not specified )
  • Nama "@jest/globals" gagal dalam aturan eslint node/no-extraneous-import karena bukan merupakan paket yang terdaftar di package-lock . Apakah ada alasan untuk konvensi penamaan ini? Apakah mungkin menggunakan jest tanpa @ ? Sangat mudah untuk mengabaikan aturan tetapi saya hanya ingin tahu.
  • Pertanyaan terkait, mengapa jest global berbeda dari magic fns seperti test , describe , before , dll.? Haruskah semua itu diimpor sekarang juga?
  • Ketika ini selesai, apakah mungkin Jest menyetel flag --experimental-vm-modules ? Agak membuat ini tampak tidak standar jika tidak hanya bekerja dengan perintah jest . Jika Anda tidak dapat mengirimkan flag secara langsung, mungkin Anda dapat mengatur/mengubah variabel env NODE_OPTIONS ?
  • Saya sekarang tampaknya mendapatkan kesalahan yang sedikit berbeda dari sebelumnya ketika mencoba ini pada Node yang lebih lama, tetapi tidak ada kesalahan yang jelas bahwa versi Node minimum adalah masalahnya. Apakah mudah menambahkan centang untuk versi minimum dengan pesan kesalahan yang lebih bermanfaat?

apakah itu juga memungkinkan file konfigurasi Jest diberi nama jest.config.js?

Itu dapat dinamai .js jika package.json memiliki type: 'module' . Jika tidak, untuk menggunakan ESM dalam file konfigurasi, itu perlu diberi nama .mjs . Lihat https://nodejs.org/api/esm.html#esm_enabling. Perhatikan bahwa file konfigurasi berjalan di luar Jest, jadi di sana kita tidak memiliki banyak kendali. Saat ini, kami tidak mendukung konfigurasi async, tetapi await melakukan janji yang diekspor akan menjadi masalah sepele, sambutan PR #8357 terhenti.

Saya sangat terkejut Anda mendapatkan A dynamic import callback was not specified , kami tidak memuat file konfigurasi di vm... Bisakah Anda membuka masalah terpisah?

Nama "@jest/globals" gagal dalam aturan eslint node/no-extraneous-import karena bukan merupakan paket yang terdaftar di package-lock . Apakah ada alasan untuk konvensi penamaan ini? Apakah mungkin menggunakan jest tanpa @ ? Sangat mudah untuk mengabaikan aturan tetapi saya hanya ingin tahu.

Anda harus menambahkan devDependency pada @jest/globals . Paket itu sendiri hanyalah definisi tipe. Ini adalah paket terpisah dari jest sehingga definisi tipe bekerja dengan benar, dan jadi kami dapat membuat kesalahan jika dimuat di luar runtime Jest.

Saat ini saya tidak memiliki rencana untuk mengubahnya, tetapi kami mungkin dapat menghentikan paket itu dan mengekspor jenisnya dari jest . Itu adalah perubahan besar, jadi mari kita lihat nanti

Pertanyaan terkait, mengapa jest global berbeda dari magic fns seperti test , describe , before , dll.? Haruskah semua itu diimpor sekarang juga?

jest seperti objek require atau module dari CJS karena unik per file, sebenarnya bukan global (yaitu globalThis.jest === undefined ). Itu memungkinkan jest.mock('../../file.js') dll bekerja dengan benar relatif terhadap file yang disuntikkannya. Anda dapat memilih untuk juga mengimpor global yang sebenarnya, tetapi mereka masih tersedia sebagai globalThis.expect dll.

Ketika ini selesai, apakah mungkin bagi Jest untuk menyetel flag --experimental-vm-modules ?

Saya pikir kita akan menunggu node untuk menghapus tandanya daripada mengaturnya secara diam-diam - mereka ditandai karena suatu alasan, API mungkin berubah di beberapa titik. Kami dapat menambahkan opsi yang mengatur NODE_OPTIONS Saya kira, tidak yakin apakah itu mengubah runtime saat ini? Terlepas dari itu, tidak ada rencana saat ini untuk itu.

Saya sekarang tampaknya mendapatkan kesalahan yang sedikit berbeda dari sebelumnya ketika mencoba ini pada Node yang lebih lama, tetapi tidak ada kesalahan yang jelas bahwa versi Node minimum adalah masalahnya. Apakah mudah menambahkan centang untuk versi minimum dengan pesan kesalahan yang lebih bermanfaat?

Ya, saya akan menambahkan pesan kesalahan yang lebih baik bersama dengan beberapa dokumentasi setelah implementasinya sedikit stabil. Melihat implementasinya dijaga oleh bendera eksperimental, saya tidak berpikir siapa pun akan tersandung karenanya.

@SimenB , saya memperbarui Jest ke 25.5.2 dan sekarang semua tes lulus. Parameter kueri berfungsi dan kesalahan intermiten yang saya lihat sebelumnya tidak lagi terjadi. Terima kasih lagi untuk semua pekerjaan Anda!

Oke, saya melihat kesalahan lagi pada pengujian terakhir saya, jadi itu masih terjadi. Saya akan melihat apakah saya dapat menemukan cara untuk secara konsisten mereproduksi dan melaporkan kembali.

Saya yakin saya telah menemukan cara yang konsisten untuk mereproduksi masalah. Inilah cabang tempat saya bekerja: https://github.com/beejunk/firn.js/tree/switch-to-jest

Untuk mereproduksi:

  1. Hapus cache Jest jika ada. Saya baru saja menghapus /tmp/jest_rs secara manual.
  2. Jalankan npm test tiga kali. Dua putaran pertama harus berhasil. Namun, putaran ketiga harus gagal.

Ini adalah jejak tumpukan yang saya lihat ketika kesalahan terjadi:

    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)

Kesalahan tampaknya berasal dari impor dinamis. Tidak ada pesan kesalahan, jadi saya tidak sepenuhnya yakin apa yang terjadi.

Catatan tambahan: Jika saya menghapus cache Jest dan memperbarui skrip pengujian dengan menambahkan --no-cache , maka saya tidak dapat mereproduksi masalah.

Heh, saya malas di sana dan tidak memberikan pesan kesalahan yang tepat. Masalahnya adalah lingkungan pengujian telah diruntuhkan, jadi saya kira ada await hilang di suatu tempat. Tidak melihat apa pun yang melihat melalui kode Anda, jadi saya harus menggali lagi

@SimenB Ini adalah reproduksi masalah konfigurasi ESM itu: https://github.com/facebook/jest/issues/9935

@SimenB Saya telah membuat contoh minimal untuk mereproduksi kesalahan Jest yang saya sebutkan di atas saat menggunakan impor dinamis:

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

Terima kasih atas reproduksi yang luar biasa @beejunk! Saya telah menghabiskan lebih banyak waktu yang saya akui di sini, tanpa benar-benar memahami apakah itu bug di Jest atau di Node.js. Saya telah mereproduksi perilaku hanya menggunakan modul inti simpul dan melaporkannya ke hulu, jadi mari kita lihat apa yang mereka katakan: https://github.com/nodejs/node/issues/33216

Terima kasih telah memeriksanya, @SimenB. Tes tampaknya lulus secara konsisten jika saya menambahkan flag --no-cache , yang baik untuk kasus penggunaan saya. Saya menghargai semua pekerjaan!

Ya, saya perhatikan itu juga. Saya pikir ini semacam masalah waktu - tanpa cache, semuanya cukup lambat untuk berfungsi.

@SimenB Terima kasih telah menyelesaikan #9935. Saya menyebutkan kekhawatiran kedua di sana, yang menurut saya masih valid. Ketika type: "module" , jest --init masih menghasilkan file konfigurasi dengan module.exports di dalamnya. Ini relatif kecil untuk diubah secara manual jika Anda tahu apa yang Anda lakukan, tetapi saya pikir jika ESM tidak ditandai di Node dan banyak orang mulai melakukan proyek ESM, itu akan mulai terlihat lebih seperti bug yang membingungkan (yaitu, jalur bahagia dari jest --init && jest pada proyek ESM baru akan menimbulkan kesalahan). Haruskah saya mengirimkan masalah berbeda secara khusus tentang meningkatkan logika init?

@aldeed apakah kamu yakin? Pengujian sekarang memberi saya file mjs dengan export default di dalamnya. Saya kira kita bisa menghasilkan js dan bukan mjs , tapi tetap saja. Ini menggunakan sintaks ESM

@SimenB Yah saya yakin sampai Anda bertanya. Saya mencobanya dan Anda benar. Mungkin saya awalnya melakukannya dengan versi Node atau Jest yang lebih lama? Mengabaikan.

Ini luar biasa! Baru saja mengerjakan ulang tes di salah satu perpustakaan saya untuk menggunakan Modul ES dan membuang Babel. Terima kasih @SimenB!

Deteksi apakah suatu file seharusnya menjadi mode ESM atau CJS

Omong-omong, ada banyak paket berorientasi browser/bundler yang menggunakan sintaks "module":"<path to es module>" untuk menunjukkan ekspor modul ES mereka. Mungkin bijaksana untuk memiliki beberapa cara untuk menentukan cara menyelesaikan paket yang diberikan terlepas dari pengaturan paket itu sendiri. Sesuatu seperti moduleNameMapper tetapi untuk menentukan apakah itu CJS atau ESM.

hai @SimenB , setelah masalah ini ditutup, itu berarti ts-jest juga dapat membatalkan commonjs kan? Apakah ekstensi file diperlukan untuk mengubah dari sisi transformator agar berfungsi dengan esm?

Misalnya sekarang ts-jest mengkompilasi ts ke js untuk commonjs , apakah esm memerlukan ekstensi file mjs saat mengkompilasi dari ts ke js ?

@zandaqo kami tidak akan mendukung bidang modules , kami akan mengikuti spesifikasi node dan menggunakan exports : #9771. Anda dapat memasang resolver Anda sendiri untuk mendukung modules jika Anda mau, meskipun: https://jestjs.io/docs/en/configuration#resolver -string. Kami mungkin menambahkan beberapa opsi lain ( mainFields , seperti webpack mungkin?), tetapi itu akan datang lebih jauh ketika implementasinya stabil dan kami memiliki lebih sedikit yang tidak diketahui yang tidak diketahui


@ahnpnl #9860

Ciao guys!
Hanya sebuah pertanyaan: posting blog menyebutkan bahwa, karena modul ES6 statis, mereka tidak dapat diejek; jadi, sebenarnya, tidak ada cara untuk mengejek modul A yang diimpor oleh modul B di ES6?

@gabrieledarrigo saya menggunakan moduleNameMapper untuk itu, misalnya:

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

@gabrieledarrigo Anda bisa melakukannya

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

let importedThing;

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

Jadi Anda hanya perlu membuat impor non-statis dan ejekan akan berfungsi.

Saya tidak yakin itu berfungsi sekarang, karena saya belum memasang resolusi tiruan di jalur kode ESM. Akan melakukannya di beberapa titik segera. Tapi itu _mungkin_ akan menjadi cara kami mendokumentasikan tiruan modul untuk ESM asli.

Seperti yang disebutkan dalam pot blog, kami akan mendokumentasikan pola-pola ini di beberapa titik, kami hanya perlu mencari tahu

Satu ide yang kami miliki adalah menunggu level teratas menunggu, kemudian kami dapat melakukan ini dengan plugin babel.

@SimenB Pertama-tama, terima kasih atas pekerjaan yang luar biasa di sini :)

Saya sebenarnya menghadapi masalah ketika saya ingin membuat customEnvironment yang diperluas dari jest-environment-node . Saya perlu mengimpor implementasi server saya di sana, yang ditulis sebagai esm. Tapi sepertinya, lingkungan harus didefinisikan sebagai cjs .
Pertanyaan saya adalah, apakah ada opsi untuk mendefinisikan testEnvironment khusus sebagai esm untuk dapat mengimpor modul server saya? Terima kasih atas sarannya.

@kuka-radovan bisakah Anda membuka permintaan fitur terpisah untuk itu?

PEMBARUAN: Masalah ini sekarang dilacak di https://github.com/facebook/jest/issues/10025

@SimenB Terima kasih atas saran jest.mock atas. Kebetulan saya mengonversi beberapa file yang membutuhkannya hari ini. Saya dapat mengonfirmasi bahwa contoh Anda berfungsi ketika modul yang diejek adalah paket node_modules , tetapi itu tidak berfungsi untuk saya yang mengejek modul dalam proyek yang sama.

Berikut ini contoh sederhana:

// 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);
});

Pola yang sama persis berfungsi ketika "./secondary.js" adalah nama paket. (Saya pikir paket yang saya coba dengan ekspor CommonJS, jika itu penting.)

Bercanda 26.0.1 dengan Node 12.16.3

Ada ide, atau haruskah saya mengirimkan edisi terpisah sepenuhnya?

EDIT: transform: {} dalam konfigurasi, jadi tidak ada Babel sama sekali

EDIT 2: Ini juga tidak berfungsi:

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

Pekerjaan luar biasa dalam hal ini.

Namun, kecuali saya melakukan sesuatu yang salah, sepertinya tidak mungkin untuk menggunakan import() dalam file pengujian CJS.

Saya menjalankan Jest dengan node --experimental-vm-modules node_modules/jest/bin/jest.js dan memiliki testEnvironment: 'node', transform: {} di jest.config.js . Ini ada di Node 14.2.0.

Ekspresi impor menghasilkan kesalahan:

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

Apakah ini batasan yang diketahui saat ini? Saya melihat https://github.com/nodejs/node/pull/32985 kini telah mendarat di Node 14.1.0.

Ya, saya belum sempat menerapkannya. Saya mungkin akan mendaratkannya akhir pekan ini.

@aldeed bisakah Anda membuka masalah terpisah? Saya harus melalui dan memastikan ejekan adalah bagian dari resolusi, dan contoh Anda tampak seperti kasus uji yang bagus

@SimenB Terima kasih atas balasan cepatnya. Aku akan mengawasinya saat mendarat.

Melihat import dalam skrip mungkin dikembalikan karena regresi (https://github.com/nodejs/node/issues/33166), mari tunda sampai selesai

Saya mengalami masalah saat mencoba menggunakan ini dengan file uji .mjs . Jika saya memiliki __tests__/my-test.mjs , saya mendapatkan

$ 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.

Jika saya menambahkan

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

ke package.json saya, saya mendapatkan

$ 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.

Namun jika saya menghapus "testMatch" dan kemudian mengganti nama file saya menjadi __tests__/my-test.js , itu berfungsi.

Saya ingin dapat menggunakan ekstensi .mjs secara konsisten dalam proyek saya. Apakah itu mungkin dengan Jest?

@domenic saya juga mengalami ini. Solusinya adalah menambahkan ke config "moduleFileExtensions": ["js", "mjs"] (selain "testMatch" ).

Lihatlah, dan moduleFileExtensions memang diperlukan.

Jest mendapatkan daftar semua file dalam proyek dengan menjalankan hasteFS.getAllFiles() sini:

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

hasteFS dibuat sebagai bagian dari HasteMap dengan konfigurasi extensions :

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


Namun, saya rasa tidak perlu menentukan moduleFileExtensions dalam kasus ini. Kami sudah memaksa .snap untuk ditemukan, haruskah kami memaksa ekstensi JS yang terkenal juga? Mereka adalah (dari atas kepalaku) js , mjs , cjs , jsx , ts dan tsx ? Itu akan membuat perayapan lebih lambat, tetapi saya tidak berpikir itu memiliki dampak yang besar. Saya mungkin salah meskipun? Sebagai default, seharusnya tidak lebih lambat karena hanya cjs dan mjs yang belum menjadi bagian dari pola default, tetapi untuk orang yang memiliki pola khusus, hal itu mungkin memperlambat segalanya?

Ya, akan ideal jika, setidaknya dalam mode modul ES, .mjs hanya berfungsi, tanpa harus menambahkan moduleFileExtensions atau memodifikasi testMatch default.

Akan lebih baik jika saya dapat mengecualikan file .js; ketika saya mencoba itu saya dapatkan

 Validation Error:

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

Saya bertanya-tanya apakah masuk akal untuk memiliki beberapa "mode ESM" yang akan menambahkan ekstensi file node esm dan juga membantu kompilasi-ke-js menggunakan esm untuk ikut serta (#9860).


Tanpa js beberapa hal rusak secara internal yang kami muat di dalam kotak pasir (karena menggunakan implementasi require dll). Kami mungkin harus memperbaikinya sehingga pengguna tidak dapat merusak kami.

Mengenai perlambatan, itu sudah cukup lambat pada proyek-proyek besar, tetapi saya tidak tahu bahwa jumlah ekstensi berdampak sebesar itu. Tapi saya setuju mjs dan cjs harus ditambahkan sebagai default. Menentukan moduleFileExtensions: ['js'] akan mengesampingkan default dan mempercepatnya, bukan? Jadi mungkin hanya mendokumentasikannya sebagai tweak kinerja.

Terima kasih untuk semua pekerjaan ini! Hal ini tentu menakjubkan. Saya mengikuti 3 langkah ( "type": "module" pada package.json saya, "testEnvironment": "jest-environment-node" dalam konfigurasi lelucon saya dan --experimental-vm-modules pada CLI) dan tampaknya juga berfungsi dengan baik

Tapi kemudian saya mencoba membaca dan menggunakan import.meta seperti yang dijelaskan dalam dokumen Node.js (dan yang tampaknya sudah diterapkan dilihat dari kotak centang) untuk membuat __dirname , tetapi sepertinya import.meta gagal:

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.

Saya tidak punya babel dan saya pikir babel tertinggal dengan pekerjaan ini. Saya akan kembali untuk melaporkan jika saya dapat memperbaikinya tanpa menginstal babel.

Node.js v14.3.0, Jest v25.5.4

Saya menemukan solusi untuk saat ini. Karena saya menjalankan skrip dari direktori yang sama tempat file saya berada di library saya , saya hanya dapat melakukan:

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

Saya akan mengikuti repo ini jika ada pembaruan, sekali lagi terima kasih telah melakukan ini!

Anda harus secara eksplisit memilih keluar dari Babel dengan menggunakan transform: {} sebagai konfigurasi

@SimenB Saya dapat mengonfirmasi bahwa menambahkan transform: {} berhasil, terima kasih! Saya salah memahami poin itu sebagai "jangan tambahkan transformasi" dan bukan sebagai "ambil transformasi" sebagaimana dimaksud.

BTW, pengujian telah berubah dari 2,4 detik menjadi hanya 1,3 detik dan mereka secara konsisten merasa lebih cepat.

Node 12 telah dirilis dengan ESM yang tidak ditandai (https://nodejs.org/en/blog/release/v12.17.0/). Seperti yang dicatat dalam OP, penggunaan APIs Jest _not_ unflagged

@SimenB Saya membahas utas ini beberapa kali tetapi saya masih macet (menggunakan simpul 12.17).

Saat menjalankan Jest 26.0.1 saya mendapatkan kesalahan ini:

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.

Saya memiliki transform: {}, dan berjalan dengan node --experimental-vm-modules node_modules/jest/bin/jest.js .

Apa yang saya lewatkan?

@aldarund tidak yakin, bisakah Anda mengumpulkan reproduksi minimal?

@SimenB inilah repo minimal untuk ditiru, jalankan saja yarn test https://github.com/aledalgrande/jest-example - Saya sudah mencoba dengan Node 13/14 dan hasilnya sama. Tampak bagi saya bahwa alur untuk pengaturan global belum diperbarui agar berfungsi dengan ESM.

juga, kamu menyebut orang lain

~Tidak @simenB , tetapi @aledalgrande Anda tampaknya memiliki segalanya yang benar di sini dari apa yang saya coba, lihat proyek saya sepenuhnya berjalan di ESM untuk perbandingan (konfigurasi lelucon di package.json ).~

~Untuk men-debug-nya jika memungkinkan, saya sarankan untuk menyederhanakan konfigurasi lelucon Anda menjadi _only_ memiliki dua properti yang relevan, bahkan mungkin di package.json terlebih dahulu. Kemudian tambahkan setiap properti lain yang saat ini Anda miliki untuk melihat mana yang berfungsi/tidak berfungsi.~

Ah komentar kedua menyebutkan globalSetup dan bukan tes normal, nvm komentar saya kalau begitu. Jika saya menghapus kunci globalSetup di Jest, maka tes berjalan seperti yang diharapkan dalam contoh itu, tetapi kunci globalSetup tidak berfungsi seperti yang Anda katakan.

Aha, saya sudah lupa tentang penyiapan dan pembongkaran global. Bisa diperbaiki 👍

Hai @SimenB , saya lagi. Apakah ekspor bernama didukung? Dengan Node.js saya dapat mengimpor dan menggunakan paket seperti ini:

import { customAlphabet } from "nanoid";

Namun, ketika mencoba melakukan tes, kode yang sama memberikan kesalahan ini:

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

Untuk pengujian, saya dapat mengubah kode menjadi ini dan berfungsi:

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

Tetapi kemudian versi Node.js berhenti berfungsi karena sebenarnya tidak ada olahraga default (tetapi untuk beberapa alasan ekspor default berfungsi dengan Jest):

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

Kode yang diterbitkan (repo tampaknya sedang berubah sekarang) nanoid berakhir seperti ini, tanpa ekspor default:

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

Jest hanya menggunakan titik masuk "utama". "ekspor" belum dipertimbangkan. Anda cukup mengimpor versi commonjs yang hanya memiliki ekspor default.

Ah, begitu, package.json sepertinya menyertakan ini:

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

Jadi mungkin Node.js menemukan versi modul, sementara Jest menggunakan versi CommonJS yang tidak memiliki nama ekspor, bukan?

Saya akan menunggu sampai Package Exports diperiksa dan kemudian mengujinya, terima kasih untuk semua pekerjaan lagi! Menandai 2 komentar ini sebagai diselesaikan sampai saat itu. Tes yang saya maksud adalah yang ini .

Saya meninjau kembali ini untuk melihat cara kerjanya - ditingkatkan ke Jest 26.0.1 dan node 14.4. Setel package.json ke tipe modul, setel transform ke {} , env ke jest-environment-node dan jalankan dengan node --experimental-vm-modules . Sekarang saya mendapatkan kesalahan baru ini:

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

Saya tidak dapat menemukan info tentang ini kecuali changelog dari Jest yang mengatakan getVmContext telah ditambahkan beberapa waktu lalu.

Ada ide?

Bisakah Anda membagikan bagian yang relevan dari package.json @cyberwombat ? Termasuk skrip peluncuran yang Anda gunakan untuk Jest.

Untuk referensi, ini adalah tampilan saya di proyek yang sedang berjalan :

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

Kemudian luncurkan dengan npm test

@franciscop Milik saya pada dasarnya sama. Simpul 14.4.0. Aku bisa menjalankan milikmu dengan baik. Saya akan menyelami hal-hal untuk melihat perbedaannya.
package.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>'
  ]
}

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

Tidak yakin, tapi saya akan mencoba untuk bekerja sebaliknya. Hapus semuanya kecuali transform: {} dan testEnvironment: 'jest-environment-node' , dan mulai tambahkan setiap opsi hingga Anda melihat mana yang memicu kesalahan sebelumnya. Saya secara khusus menduga transformIgnorePatterns _might_ bertentangan dengan transform , tetapi saya tidak begitu akrab dengan opsi lelucon.

Halo semuanya! Saya mengalami beberapa masalah saat menggunakan Jest untuk menguji aplikasi Express. Lebih detail di sini . Tidak yakin apakah itu berguna untuk apa yang Anda lakukan/lacak di sini :roll_eyes:

@ x80486 Saya mengalami masalah yang sama persis kemarin . Saya telah menjawab di StackOverflow dengan penjelasan yang lebih panjang dari pemahaman saya.

Sunting: Saya menyembunyikan komentar saya sebelumnya karena tampaknya mungkin relevan, "exports" tampaknya populer, sangat mungkin dari artikel ini tentang paket hibrida .

exports dilacak di #9771

@franciscop ok masalah terpecahkan - ternyata ada konflik dalam paket - saya telah menginstal serverless-bundle yang menyebabkan ES Modules are only supported if your test environment has the getVmContext function kesalahan. Saya tidak yakin mengapa - saya akan menganggap menginstalnya tidak akan menyebabkan konflik berjalan dengan bercanda tetapi ternyata memang demikian.

@franciscop Saya pikir alasan mengapa masalah terkait pkg.exports mulai muncul sekarang adalah karena fitur itu tidak ditandai di Node.js 14.x dan beberapa pengelola paket (seperti saya untuk uuid ) dimulai menambahkan bidang pkg.exports . Jadi, sementara Anda memerlukan tanda baris perintah untuk mengaktifkan fitur itu di Node.js 12.x Anda mendapatkan perilaku itu secara default sekarang.

Butuh beberapa saat bagi seluruh ekosistem untuk beradaptasi, jadi terima kasih telah melaporkan masalah seputar topik itu!

Bagi mereka yang memposting tentang exports , jika telah hilang di utas panjang masalah ini, masalah tertutup saya tentangnya (https://github.com/facebook/jest/issues/9565) memiliki contoh dari solusi moduleNameMapper di dalamnya.

Masalah globalSetup dilaporkan pada bulan Mei kemungkinan masih ada (Jest 26.1.0)? Mendapatkan kesalahan yang sama seperti pada contoh repo @aledalgrande menyediakan:

$ 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 

Tidak terburu-buru. Memeriksa CHANGELOG dan tidak menyebutkan perbaikan untuk globalSetup/globalTeardown dengan ES6.

Node.js 14.4.0, Bercanda 26.1.0


Pembaruan (13-Agustus-20):

Masih tidak mungkin, Node.js 14.7.0, Jest 26.4.0

Pendapat sampingan tetapi apakah masalah ini harus menjadi masalah yang disematkan karena itu fokus untuk lelucon saat ini?

Adakah pemikiran tentang apa yang perlu dilakukan untuk mengkonsumsi reporter uji yang ditulis dalam modul ES?...
dengan versi lelucon terbaru, saya mendapatkan kesalahan yang pada dasarnya mengatakan testScheduler mengharapkan reporter khusus dalam format commonjs.


untuk melihat kesalahan

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

SyntaxError: Tidak dapat menggunakan pernyataan impor di luar modul
di wrapSafe (internal/modules/cjs/loader.js:1116:16)
di Module._compile (internal/modules/cjs/loader.js:1164:27)
di Object.Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
di Module.load (internal/modules/cjs/loader.js:1049:32)
di Function.Module._load (internal/modules/cjs/loader.js:937:14)
di Module.require (internal/modules/cjs/loader.js:1089:19)
di membutuhkan (internal/modules/cjs/helpers.js:73:18)
di /Users/manish.gowardipe/Desktop/projects/esw-ts/lib/node_modules/@jest/core/build/TestScheduler.js:418:65
di Array.forEach ()
di TestScheduler._addCustomReporters (/Users/manish.gowardipe/Desktop/projects/esw-ts/lib/node_modules/@jest/core/build/TestScheduler.js:411:15)

Hai, saya ingin menguji dukungan Asli untuk Modul ES di proyek kecil saya, tetapi saya baru mengenal NodeJS dan saya tersesat dalam Masalah ini, saya mohon bimbingannya.

  • node --version : v14.5.0
  • yarn jest --version : 26.1.0
  • Saya mencoba menguji proyek kecil ini , sangat sederhana.
  • Saya memiliki file saya seperti ini:

package.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);
});
  • Saya menjalankan yarn jest . dan itu memberi saya kesalahan ini:
    imagen

  • Saya mencoba dengan node node_modules/jest/bin/jest.js . dan itu memberi saya kesalahan yang sama.

@pepetorres1998 Utas ini tentang menjalankan Jest dengan modul esm asli yang melibatkan menjalankan sesuatu dengan flag/opsi tertentu - lihat komentar di atas untuk mengetahui apa yang harus dilakukan (dan atur "ketik": "modul" di package.json). Sejujurnya meskipun pada titik ini belum cukup siap untuk prime time jadi jika Anda membutuhkan proyek Anda untuk bekerja, saya mungkin tetap menggunakan Babel. Ada sejumlah masalah yang tidak dicentang yang merupakan penghenti pertunjukan nyata. Saya dengan gembira mencoba untuk beralih beberapa minggu yang lalu dan kembali menangis ke Babel.

Apakah ada orang lain yang mendapatkan ReferenceError: jest is not defined ketika mencoba melakukan hal-hal seperti jest.setTimeout(...) dalam file pengujian dengan pengaturan ini? Mencoba mencari tahu apakah ini terkait dengan lingkungan modul es, versi simpul, versi lelucon, atau kombinasi dari hal-hal itu. (Saat ini menggunakan node v14.5.0, jest 26.1.0, lingkungan jest-environment-node)

EDIT
Saya sekarang melihat kotak centang yang tidak dicentang dalam deskripsi masalah untuk properti 'global' lelucon. 🙃

@bdentino Saya pikir Anda dapat mencoba mengimpornya secara eksplisit import {jest} from '@jest/globals';

25.4.0 telah dirilis dengan dukungan pertama. Selain #9772 yang disebutkan di atas, saya juga menyertakan #9842. Dalam _theory_ pencampuran CJS dan ESM harus bekerja dengan benar sekarang (🤞).

Satu fitur utama yang hilang adalah mendukung objek jest . Saya belum memutuskan apakah kita harus tetap menggunakan import.meta atau meminta orang untuk mengimpornya melalui import {jest} from '@jest/globals' . Umpan balik dihargai!

Saya belum menulis dokumen untuk ini, tetapi untuk mengaktifkannya Anda perlu melakukan 3 hal

  1. pastikan Anda tidak menjalankan transformasi diri import pernyataan (set transform: {} di config atau memastikan babel tidak mengubah file ke CJS, seperti menghindari modules opsi ke preset-env)
  2. Jalankan node@^12.16.0 || >=13.2.0 dengan flag --experimental-vm-modules
  3. Jalankan pengujian Anda dengan jest-environment-node atau jest-environment-jsdom-sixteen

Silakan mencobanya dan berikan umpan balik! Jika melaporkan bug, alangkah baiknya jika Anda juga dapat menyertakan cara menjalankan kode yang sama (dikurangi kode khusus pengujian apa pun) berjalan di Node.js. Saya telah membaca https://nodejs.org/api/esm.html _a lot_ selama beberapa minggu terakhir, tetapi saya mungkin melewatkan sesuatu.

@SimenB
Utas ini menjadi sangat besar, dan saya pikir mereka yang ingin memulai dengan bercanda / menggunakan modul ES - akan kesulitan menemukan dan memahami pedoman dasar untuk mulai melakukannya.
Apakah ada penjelasan formal dalam dokumen tentang menambahkan lelucon ke proyek modul ES (atau 'mulai cepat')?

@aldeed Mengenai masalah Anda dengan modul mengejek dari proyek yang sama, apakah Anda menemukan perbaikan? Saya mengalami masalah yang sama persis

(Btw, kami juga menggunakan reactioncommerce, jadi bersorak untuk itu haha)

@guilhermetelles tidak, dan itu dilacak di https://github.com/facebook/jest/issues/10025 sekarang.

Saya menggunakan Jest 26.1.0, node versi 14.6.0 dengan --experimental-vm-modules , tapi saya masih melihat ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING saat menggunakan import() di dalam CommonJS . Haruskah saya mencoba membuat repro minimal dan membuka masalah baru?

Selain itu, apakah ada cara mudah untuk yarn link salinan paket jest ke dalam proyek sekarang karena Jest menggunakan yarn berry? Saya ingin mencoba master berjaga-jaga jika ini diterapkan oleh yang belum dirilis. Saya mencoba melakukan sesuatu seperti path/to/facebook/jest/.yarn/releases/yarn-sources.cjs link --all path/to/jest , tetapi itu akan gagal. Menjalankan sesuatu seperti 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 secara manual juga tidak berfungsi, saya tidak yakin mengapa.

@vvanpo import() di CJS dikembalikan di Node, Anda dapat mengikuti https://github.com/nodejs/node/issues/31860

Untuk menjalankan lokal, saya biasanya hanya menghapus jest dari proyek yang ingin saya uji dan lakukan ../jest/jest . Berpotensi nose ../jest/packages/jest/bin/jest.js . Pastikan untuk menjalankan yarn dan yarn build:js terlebih dahulu. Jika instruksi ini tidak berfungsi (saya menulis dari memori di telepon di pesawat) silakan buka masalah (atau PR) sehingga kami dapat menulis ini dengan benar ke dalam file CONTRIBUTING.md

Apakah Anda berencana untuk mendukung impor siklik?

Jika saya memiliki file uji dummy yang hanya mengimpor satu dari dua file yang hanya mengimpor satu sama lain, saya mendapatkan RangeError: Maximum call stack size exceeded . Jika saya menghapus salah satu impor, tes lulus. Repo yang mereproduksi masalah .

Hai! Saya mengatur ini di proyek node kosong dan itu bekerja dengan sangat baik, namun dalam pengaturan produksi kami, saya mendapatkan pesan kesalahan berikut ketika saya mencoba menjalankan tes:

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

Saya melihat orang lain mengalami masalah dalam balasan sebelumnya (oleh @cyberwombat ), tetapi paket yang mereka temukan sebagai pelakunya tidak ada dalam file package.json . Bagaimana cara menyimpulkan paket (atau pengaturan) yang menyebabkan masalah? Saya telah mencoba secara sistematis menghapus setiap pengaturan lelucon yang tidak diperlukan untuk membuat ini berhasil, tetapi saya tidak berhasil.

UPDATE : Saya telah berhasil membuat kemajuan dengan membuat sedikit perubahan pada jest-runtime . Saya menghentikan debugger di baris yang mencoba mengakses konteks VM dan sementara fungsinya benar-benar tidak ada, this.context (yang seharusnya dikembalikan), jadi saya mengubah baris itu untuk mengakses properti secara langsung. Saya tahu ini mungkin tidak ideal, tapi mungkin @SimenB ini bisa memberi Anda gambaran tentang apa yang salah?

Terima kasih sebelumnya atas bantuan apa pun

Apakah Anda berencana untuk mendukung impor siklik?

Pastinya! Bisakah Anda membuka masalah terpisah?


@zsombro sepertinya Anda menjalankan beberapa versi lama dari lingkungan pengujian. Jika Anda menjalankan jest --show-config , apa yang ditampilkan oleh testEnvironment ?

sepertinya Anda menjalankan beberapa versi lama dari lingkungan pengujian. Jika Anda menjalankan jest --show-config , apa yang ditampilkan oleh testEnvironment ?

@SimenB dikatakan sebagai berikut:

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

Saya baru saja mengaturnya ke jest-environment-node berdasarkan instruksi Anda

Sebelum saya memulai proses ini, saya memutakhirkan lelucon menggunakan yarn add jest@latest . Apakah saya harus memutakhirkan lingkungan secara terpisah?

UPDATE: Ternyata saya harus melakukannya. Saya menghapus node_modules dan yarn.lock untuk melakukan instalasi bersih dan masih tidak berhasil. Namun, jika saya menambahkannya secara manual dengan menggunakan yarn add -D jest-environment-node sepertinya berhasil. Apakah ada cara yang lebih baik untuk mengelola ini? Saya melakukan proyek pengujian minimalis sebelum melakukan ini pada basis kode kami dan saya tidak perlu melakukan ini

yarn list jest-environemnt-node (atau npm list jest-environemnt-node ) mungkin akan mencantumkan beberapa, tebakan saya

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

versi 26.2.0 mungkin yang saya instal secara manual (setidaknya berdasarkan package.json , yang berarti jest-config telah menginstal versi yang tampaknya sudah usang?

Anda memiliki sesuatu yang lain menarik dalam versi lama jest-config ( react-scripts mungkin (bagian dari create-react-app )?). Masalah ini bukan tempat untuk membahasnya, tho

Tidak dapat menggunakan modul ES di globalSetup mulai terasa sakit.

Dua poin:

  • haruskah ini disebutkan sebagai kotak centang di awal masalah ini (sehingga dilacak)?
  • kalo ada alpha/beta bisa saya coba, bersedia melakukannya

SAYA:

  • Memastikan saya menjalankan versi Jest terbaru (26.4.0)
  • Menambahkan lelucon-lingkungan-simpul ke proyek saya
  • Pastikan itu tidak diduplikasi dengan memeriksa file kunci
  • Menambahkan "testEnvironment": "jest-environment-node", di jest.config.json
  • Menambahkan import { jest } from '@jest/globals'; mana pun lelucon digunakan
  • Jalankan pengaturan perintah pengujian --experimental-vm-modules dengan menjalankannya dengan NODE_OPTIONS='--experimental-vm-modules' yarn jest

Dan crash pada kode berikut:

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

dengan kesalahan berikut (disingkat - perhatikan "Objek yang diizinkan"!):

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.

Saya tidak dapat menggunakan Babel, karena mem-parsing impor dengan tidak benar yang saya perbaiki untuk dijalankan di Node 14 tanpa Babel:

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

Yang sayangnya tidak diurai dengan benar oleh @babel/preset-env , menghasilkan TypeError: Cannot destructure property 'map' of '_lodash.default' as it is undefined. .

Dapatkah seseorang tolong bantu saya mengatasi masalah ini?

Sunting: Sepertinya Anda _can_ menggunakan Jest+Babel pada kode asli yang kompatibel dengan modul ES menggunakan impor CommonJS dengan melakukan perbaikan yang benar-benar menjijikkan ini:

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

Cara ini,

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

dikonsumsi dengan sempurna oleh Node 14, dan kode yang dihasilkan dari menjalankan Jest+Babel,

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

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

const {
  map
} = _lodash.default;

juga berjalan.

kami telah berhasil mengonversi semua tes lelucon kami untuk menggunakan dan mengimpor kode ES6 kami, tetapi kami terjebak pada beberapa paket: yaitu puppeteer dan uuid

Aplikasi hanya berfungsi jika kita mengimpornya ke dalam objek (seperti import uuid from 'uuid' ), tetapi pengujian tidak akan berjalan seperti ini. Namun, jika kita mengganti impor ini dengan sintaks dekonstruksi (seperti import { v4 } from 'uuid' , maka sebaliknya: pengujian berhasil, tetapi aplikasi mengeluarkan pengecualian.

awalnya, kami mengikuti panduan dan mematikan setiap transformasi, tetapi kami juga mencoba membuat ruang kerja benang tempat kami menginstal babel dengan konfigurasi simpul minimal, tetapi ini tidak menyelesaikan (atau memperburuk) masalah khusus ini

Namun, jika kita mengganti import ini dengan sintaks dekonstruksi (seperti import { v4 } from 'uuid', maka sebaliknya: pengujian berhasil, tetapi aplikasi mengeluarkan pengecualian.

Kedengarannya seperti aplikasi Anda dikompilasi ke CommonJS dan tidak menggunakan modul dalam praktiknya. Dari ESM "asli" import uuid from 'uuid' seharusnya tidak berfungsi karena uuid tidak memiliki ekspor default dan memperlihatkan build ESM untuk node .

Hai @SimenB , menurut Anda beberapa dokumentasi awal tentang ini akan menjadi ide yang bagus?

@grantcarthew pasti! Saya berharap saya dapat menghabiskan lebih banyak waktu untuk ini dan menstabilkannya untuk Jest 27, tetapi saya ragu saya akan dapat melakukannya. Tetapi menulis halaman dokumen tentang apa yang ada sekarang (dan itu eksperimental) terdengar seperti ide yang bagus

@SimenB Saya tidak tahu apa status masalah saat ini dan apakah Jest seharusnya sudah bekerja dengan kasus saya atau tidak, tetapi mungkin itu dapat membantu Anda entah bagaimana.

Saya mencoba memuat perpustakaan khusus esm (ekstensinya adalah cjs tetapi tipenya adalah modul dan simpul tampaknya baik-baik saja dengan itu) tetapi Jest gagal memuatnya dengan benar dengan kesalahan:

    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) {

Di sini masalah yang awalnya saya buka https://github.com/codemirror/codemirror.next/issues/310 . Dan repro untuk Jest + ESM gagal dengan node 14.13.1 https://github.com/dubzzz/codemirror-next-repro-cra/tree/main/test-in-jest-esm

@dubzzz Anda tidak dapat memiliki ESM dalam file cjs . Node juga gagal

$ 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 maaf, saya mencoba terlalu cepat di sisi simpul. @nicolo-ribaudo sudah memberi tahu penulis lib tentang masalah ini.
Benar-benar terima kasih banyak atas jawaban cepat Anda.

Saya membuka PR untuk beberapa (cukup banyak rintisan) dokumen di sini: #10611. Saya tidak repot-repot menyebutkan fitur/bug yang hilang karena saya pikir itu akan sulit untuk disinkronkan dengan kenyataan, dan melihat masalah github adalah pendekatan yang lebih baik karena mereka (semoga…) mutakhir.

@Pomax sebagai edisi baru, tolong

Saya baru saja membuka #10620 yang menambahkan dukungan untuk import() dari CJS. Diminta beberapa kali seperti https://github.com/facebook/jest/issues/9430#issuecomment -626054595

Halo. Cukup sulit bagi saya untuk dengan cepat merangkul seluruh cerita di balik ESM dalam simpul/bercanda, jadi, mungkin, saya menanyakan sesuatu yang jelas atau sudah dijawab. Apakah saya memahami dengan benar bahwa kasus berikut ini belum didukung? Atau, saya harap, saya melakukan sesuatu dengan cara yang tidak benar? Saya mengalaminya seperti import x from 'x' berfungsi, tetapi perusakan import { sub } from 'x' tidak.

paket.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('', () => {});

tes npm

> 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.

Anda sedang menunggu #9771. Sebelum itu, Jest tidak tahu aman untuk memuat uuid sebagai ESM (atau lebih tepatnya, file mana yang akan dimuat pada titik mana ia akan mengetahui bahwa itu adalah ESM)

Apakah ini akan mengikuti konvensi Node sendiri, di mana CJS hanya dapat dimuat sebagai namespace, atau akankah ini "meningkatkan" dengan mengizinkan sintaks yang sebenarnya tidak berfungsi di Node itu sendiri? (misalnya Node tidak mengizinkan import { readdirSync } from "fs-extra" karena itu adalah paket CJS, tetapi itu mengizinkan import fs from "fs-extra"; yang kemudian dapat dibongkar menggunakan const { readdirSync } = fs ).

(misalnya Node tidak mengizinkan import { spawn } dari "child_process" karena itu adalah paket CJS, tetapi mengizinkan import child_process dari "child_process"; yang kemudian dapat dibongkar menggunakan const { spawn } = child_process;).

Ini adalah contoh yang tidak menguntungkan karena node menganggap "child_process" sebagai modul "builtin" (dan bukan CJS), jadi ekspor bernama berfungsi. Nodejs terbaru juga menggunakan heuristik untuk membuat banyak ekspor bernama berfungsi untuk modul CJS. Itu mungkin bagian tersulit untuk ditiru.

contoh diperbarui untuk menggunakan fs-extra sebagai gantinya. Tetapi jika ekspor bernama ada di peta jalan Node untuk mendapatkan jurusan ini atau berikutnya, maka Jest mendahului itu masuk akal.

Itu seharusnya sudah diimplementasikan - Modul inti simpul memperlihatkan ekspor bernama, CJS "normal" tidak.

Nodejs terbaru juga menggunakan heuristik untuk membuat banyak ekspor bernama berfungsi untuk modul CJS. Itu mungkin bagian tersulit untuk ditiru.

Apakah Anda memiliki tautan ke PR yang menerapkannya? Kita harus mencoba untuk menirunya setidaknya

PR ada di sini: https://github.com/nodejs/node/pull/35249

Heuristik di baliknya diterbitkan sebagai cjs-module-lexer (https://github.com/guybedford/cjs-module-lexer) tetapi @guybedford mungkin tahu lebih banyak tentang potensi penyimpangan.

Baru saja melihat ini dan sepertinya fs-extra menggunakan pola ekspor seperti:

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')
}

Saat ini ini bukan kasus analisis ekspor ulang yang kami deteksi, tetapi dimungkinkan untuk menambahkan ke cjs-module-lexer jika ini akan menjadi kasus yang berguna untuk menangani deteksi ekspor bernama.

Terima kasih @jkrems & @guybedford! Saya sudah membuka PR sekarang menggunakan modul itu: #10673

Dukungan fs-extra persis yang dijelaskan di https://github.com/facebook/jest/issues/9430#issuecomment -713204282 sekarang diterapkan di [email protected] , pelacakan hulu di https://github. com/nodejs/node/pull/35745.

_Update: menguji build ini, ia mendeteksi dengan benar semua fungsi fs-extra, tetapi sayangnya tidak mendeteksi fungsi asli Node.js karena tidak dapat dianalisis secara statis karena diisi oleh for loop._

feat: mendukung ekspor bernama dari CJS seperti yang disebut impor ESM #10673

Saya pikir ESM asli hanya mendukung pengimporan exports modul CommonJS sebagai default ?

Halo. Cukup sulit bagi saya untuk dengan cepat merangkul seluruh cerita di balik ESM dalam simpul/bercanda, jadi, mungkin, saya menanyakan sesuatu yang jelas atau sudah dijawab. Apakah saya memahami dengan benar bahwa kasus berikut ini belum didukung? Atau, saya harap, saya melakukan sesuatu dengan cara yang tidak benar? Saya mengalaminya seperti import x from 'x' berfungsi, tetapi perusakan import { sub } from 'x' tidak.

...
impor { v4 } dari 'uuid';

Modul ESM tidak mendukung pengrusakan impor, meskipun sintaksnya terlihat seperti itu. Agar ini berfungsi, 'ekspor v4' diperlukan. 'ekspor default' tidak akan cocok.

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

@sdwlig uuid menyediakan ekspor bernama dan tidak memiliki default. Seharusnya berfungsi tetapi memuat esm dari paket dengan bidang "ekspor" belum didukung oleh lelucon. Commonjs dimuat sebagai gantinya yang hanya tersedia melalui ekspor default.
https://github.com/uuidjs/uuid/blob/master/src/index.js

Bisakah kami menambahkan dukungan referensi sendiri paket (#10883) ke ini?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat