Jest: ميتا: دعم أصلي لوحدات ES

تم إنشاؤها على ١٩ يناير ٢٠٢٠  ·  131تعليقات  ·  مصدر: facebook/jest

تحرير: دليل سريع للبدء: https://jestjs.io/docs/en/ecmascript-modules

لن يتم الإبلاغ عن دعم ESM في إصدار مستقبلي من Node 12 (ربما ليس قبل أبريل https://github.com/nodejs/node/pull/29866#issuecomment-574055057) ولم يتم الإبلاغ عنه بالفعل في Node 13.2 ، لذلك أعتقد أنه حان الوقت لتقييم كيف يمكننا إضافة دعم محلي في Jest. سأحاول سرد الميزات التي توفرها Jest حاليًا والتي تتأثر بدعم ESM ، وكيف يمكننا حلها / التحقيق فيها.

هناك مشكلة رقم 4842 ، لكنني أعتقد أن هذه مسألة مناقشة ، في حين أن هذه المشكلة ستكون موجهة نحو التنفيذ الفعلي للدعم وأكثر ملاءمة لتعقب أولئك الذين يريدون فقط الحصول على حالة التنفيذ الحالية. سيتم وضع علامة على أي تعليقات تتم إضافتها إلى هذه المشكلة _لا_ المتعلقة بكيفية تنفيذ الدعم للميزات المذكورة أدناه كرسائل غير مرغوب فيها - يرجى توجيه أي حلول / مناقشات إلى مشكلات منفصلة. لا تتردد أيضًا في إخبارنا إذا كان أي شيء متعلق بميزات ESM مفقودًا من القائمة!

يرجى ملاحظة أن Jest سيستخدم vm API (https://nodejs.org/api/vm.html) وحتى كتابة (العقدة v13.6) ، لا تزال أجزاء ESM من واجهة برمجة التطبيقات هذه تحمل علامة ( --experimental-vm-modules ). لذا فإن القول بأن ESM غير معلوم يعد تسمية خاطئة إلى حد ما في الوقت الحالي. لكنني أعتقد أنه يجب علينا البدء في التجريب ومن المحتمل أن نقدم ملاحظات إلى مجموعة العمل للوحدات .

أخيرًا ، أكتب هذه المشكلة في الغالب للأشخاص الذين سينفذون الدعم ، لذلك سيكون مستوى منخفضًا إلى حد ما ومخصص لكيفية عمل Jest. بالنسبة للأشخاص الذين _ just_ يريدون معرفة ما إذا كان الدعم قد وصل أم لا ، أوصي باستخدام "الإخطار المخصص" الرائع من GH والاشتراك فقط في الإشعارات عند الإغلاق / إعادة الفتح.


  • [x] تشغيل الوحدة في السياق الصحيح

نحقق وضع الحماية من خلال تشغيل نص برمجي داخل vm.Context (سواء تم توفيره بواسطة JSDOM أو واجهات برمجة التطبيقات الأساسية للعقدة). نحتاج إلى فعل الشيء نفسه بالنسبة لـ ESM ، لكننا سنحتاج إلى الوصول إلى context أثناء إنشاء الوحدة ، وليس فقط عند تنفيذ الوحدة. لقد فتحت رقم 9428 الذي يضيف واجهات برمجة التطبيقات الضرورية إلى JestEnvironment .

  • [x] جلوبالس

ستظل إضافة expect ، test ، beforeEach وما إلى ذلك على أنها جلوبال ، ولا يجب تغيير أي شيء هنا. سيظل jasmine global هنا أيضًا.

  • [x] jest خاصية "عالمية"

هذا ليس حقًا عالميًا - لقد تم حقنه في نطاق الوحدة. نظرًا لأن نطاق الوحدة قد انتهى في ESM ، فنحن بحاجة إلى نقله إلى مكان ما. تبدو إضافته إلى import.meta أمرًا طبيعيًا - هناك خيار يسمى initializeImportMeta يمكننا استخدامه.

تعديل: الحل هنا هو جلبه عبر import {jest} from '@jest/globals' . ربما لا نزال نضيفه عبر import.meta في المستقبل ، لكن هذا يجب أن يكون كافيًا في الوقت الحالي.

  • [] jest.(do|un)mock

نظرًا لأن ESM لها "مراحل" مختلفة عند تقييم وحدة نمطية ، فلن يعمل jest.mock لعمليات الاستيراد الثابتة. يمكن أن يعمل مع عمليات الاستيراد الديناميكية ، لذلك أعتقد أنه يتعين علينا فقط أن نكون واضحين في المستندات حول ما يدعمه وما لا يدعمه.

يتم رفع المكالمات jest.mock ، لكن هذا لا يساعد في ESM. قد نفكر في تحويل import 'thing' إلى import('thing') والذي يجب أن يسمح للرفع بالعمل ، لكنه بعد ذلك غير متزامن. ربما يكون استخدام المستوى الأعلى await ضرورة لمثل هذا النهج. أعتقد أيضًا أنها غازية بما يكفي لتبرير خيار منفصل. شيء للمناقشة - لسنا بحاجة إلى دعم كل شيء يمكن لـ jest.mock للإصدار الأولي.

  • [] jest.requireActual

لست متأكدًا مما إذا كان يجب أن يتصرف في ESM. هل يجب علينا تقديم jest.importActual والسماح لـ requireActual بالتقييم بـ CJS دائمًا؟

  • [x] import.meta

العقدة لديها url كممتلكاتها الوحيدة (في الوقت الحالي ، على الأقل). نحن بحاجة للتأكد من أنها مأهولة بالسكان في جيست أيضًا. نحن نقدم identifier بدلاً من filename عند إنشاء الوحدة ، لذلك لا أعتقد أن ذلك سيحدث تلقائيًا ، ولكن url هو أساسًا filename مرت على الرغم من pathToFileURL .

هناك أيضًا PR مفتوح مقابل import.meta.resolve : https://github.com/nodejs/node/pull/31032

  • [x] import thing from 'thing'

يجب أن يكون هذا في الواقع واضحًا إلى حد ما ، فنحن نحتاج فقط إلى تنفيذ linker حيث يمكننا أيضًا تحويل المصدر قبل إعادته ، مما يعني أننا لسنا بحاجة إلى واجهة برمجة تطبيقات المحمل (التي لم تكن موجودة بعد). هذا يسمح لنا بإرجاع mocks أيضًا (على الرغم من أنها يجب أن تأتي من دليل __mocks__ ).

  • [x] import('thing')

بشكل أساسي هو نفسه كما هو مذكور أعلاه ، ولكن تم تمريره كـ importModuleDynamically عند إنشاء الوحدة. سيدعم أيضًا jest.mock ، jest.resetModules إلخ بشكل أكثر نظافة ، لذا من المحتمل أن يتم استخدامه قليلاً.

يمكن القيام بذلك أيضًا مقابل vm.Script عبر نفس الخيار.

  • [] معالجة الأخطاء أثناء التقييم

في الوقت الحالي ، يعد هذا خطأ وقت التشغيل (على سبيل المثال ، الوحدة غير موجودة) ، ولكن هذا ليس صحيحًا بالضرورة مع ESM. هل يهمنا؟ يجب علينا التحقق من الأخطاء لا تزال تبدو لطيفة.

  • [x] module.createRequire

نحن بحاجة للتعامل مع هذا للأشخاص الذين يرغبون في استخدام CJS من ESM. لقد فتحت رقم 9426 لتتبع هذا بشكل منفصل لأن تنفيذه لا يرتبط حقًا بدعم ESM.

تحرير: تم التنفيذ في # 9469

  • [] module.syncBuiltinESMExports

https://nodejs.org/api/modules.html#modules_module_syncbuiltinesmexports. هل نهتم به ، أم أنه مجرد جعله غير متاح بما فيه الكفاية؟ لست متأكدًا من حالة الاستخدام في Jest. العبث مع البنايات يكسر بالفعل صندوق الحماية ولا أعتقد أن هذا يجب أن يكون مهمًا.

تحرير: # 9469 جعل هذا في no-op. أعتقد أن هذا جيد؟

  • [] اكتشف ما إذا كان من المفترض أن يكون الملف في وضع ESM أو CJS

يبدو فحص حقل type في package.json للوحدة النمطية أمرًا معقولاً: https://nodejs.org/api/esm.html#esm_enopped. هل يجب أن يكون لدينا أيضًا علم التكوين الخاص بنا؟ يحتاج أيضا إلى احترام نهايات الملف.

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

  • [x] moduleNameMapper

لست متأكدًا مما إذا كان هذا يؤثر على أي شيء. لا أعتقد أننا سنقوم بربط الوحدات معًا بأنفسنا. يحتاج إلى تحقيق ، رغم ذلك.

تحرير: هذا هو منطق القرار الذي نتحكم فيه. لذلك لا توجد تغييرات هنا.

  • [x] jest.config.mjs

من خلال # 9291 ، ندعم jest.config.cjs - هل نحتاج إلى القيام بأي شيء خاص مقابل .mjs ؟ ربما استخدم import('path/to/configFile.mjs') مما يعني أنه يجب أن يكون غير متزامن. هل هذه مشكلة؟ قد يكون من المفيد إجراء دقة التكوين async في Jest 25 لذا فهو ليس مانعًا للدعم المتزايد لـ ESM في Jest 25.

تحرير: # 9431

  • [] حزمة الصادرات

تدعم العقدة تصدير الحزم ، والتي تقوم بترتيب الخرائط إلى Jest's moduleNameMapper ، ولكنها توفر أيضًا ميزات تغليف. نأمل أن ينفذ هذا resolve ، لكن إذا لم يفعلوا ذلك ، فسنحتاج إلى القيام بشيء ما. قد يكون كافيا لاستخدام الخيار pathFilter ؟ غير متأكد.

  • [] وحدة JSON / WASM

https://nodejs.org/api/esm.html#esm_experimental_json_modules. هل نحن بحاجة لرعاية؟ ربما ، خاصة بالنسبة لـ json . من التافه أن ندعم import thing from './package.json' نظرًا لأننا نتحكم في مرحلة الربط ، لكن ربما لا ينبغي لنا القيام بذلك افتراضيًا لأنها ستختلف عن العقدة الافتراضية. هل يجب أن نجبر الناس على تحديد تحول لها؟

  • [x] تغطية الكود

هل يهم؟ لا أعتقد أنه قد تأثر حيث لا يزال بإمكاننا تحويل المصدر باستخدام babel (ربما سيتم الخلط بينه وبين عبارات import ، وربما لا) ولا ينبغي أن تهتم تغطية V8 بالتأكيد. يجب علينا التحقق بالرغم من ذلك.

  • [] دقة رمز غير متزامن

هذا ليس مانعًا على الإطلاق لأن دقة المزامنة ستعمل بشكل جيد. لكننا _يمكننا_ استخدام الدقة غير المتزامنة الآن ، وهو أمر رائع. أتساءل عما إذا كان علينا النظر في استخدام الوحدة النمطية resolve خارج npm مرة أخرى ، لأنها تدعم بالفعل غير المتزامن. انظر # 9505.

  • [] تحويل رمز غير متزامن

على غرار ما ورد أعلاه ، ليس الحظر ، ولكن سيكون من الجيد دعمه. قد تجعل @jest/transformer أكثر قابلية للاستخدام في بيئات أخرى أيضًا. انظر # 9504.

  • [] أداء سيئ عند الوصول إلى الكرة الأرضية

نظرًا ل # 5163 لدينا الخيار extraGlobals كحل بديل - لم يعد هذا الحل قابلاً للتطبيق في ESM. لقد فتحت وأصدرت مع العقدة هنا: https://github.com/nodejs/node/issues/31658

ES Modules

التعليق الأكثر فائدة

لقد حصلت على دعم أساسي للغاية باستخدام # 9772. لقد اختبرت فقط أبسط الحالات ، وهناك العديد من القيود المعروفة (أبرزها عدم وجود دعم للكائن jest ودلالات معطلة عند مزج CJS و ESM) ، ولكن على الأقل _ شيء _. سيصدر في الإصدار التالي من Jest (نأمل قريبًا ، تم حظره فقط بواسطة # 9806)

ال 131 كومينتر

لقد حصلت على دعم أساسي للغاية باستخدام # 9772. لقد اختبرت فقط أبسط الحالات ، وهناك العديد من القيود المعروفة (أبرزها عدم وجود دعم للكائن jest ودلالات معطلة عند مزج CJS و ESM) ، ولكن على الأقل _ شيء _. سيصدر في الإصدار التالي من Jest (نأمل قريبًا ، تم حظره فقط بواسطة # 9806)

تم تحرير 25.4.0 مع قطع الدعم الأولى. بالإضافة إلى # 9772 المذكورة أعلاه ، قمت أيضًا بتضمين # 9842. في _theory_ يجب أن يعمل خلط CJS و ESM بشكل صحيح الآن (🤞).

الميزة الرئيسية المفقودة هي دعم الكائن jest . لم أقرر ما إذا كان يجب علينا التمسك بها import.meta أو مطالبة الأشخاص باستيرادها من خلال import {jest} from '@jest/globals' . نقدر ردود الفعل!

لم أكتب مستندات لهذا حتى الآن ، ولكن لتنشيطه ، عليك القيام بثلاثة أشياء

  1. تأكد من عدم تشغيل تحويل بيانات import (قم بتعيين transform: {} في التكوين أو تأكد من أن babel لا يحول الملف إلى CJS ، مثل تجنب modules خيار الإعداد المسبق)
  2. قم بتشغيل node@^12.16.0 || >=13.2.0 باستخدام علم --experimental-vm-modules
  3. قم بإجراء اختبارك باستخدام jest-environment-node أو jest-environment-jsdom-sixteen

يرجى تجربتها وتقديم الملاحظات! إذا قمت بالإبلاغ عن الأخطاء ، فسيكون من الرائع أن تتمكن من تضمين كيفية تشغيل نفس الكود (باستثناء أي كود اختبار محدد) في Node. لقد قرأت https://nodejs.org/api/esm.html _ الكثير_ على مدار الأسابيع القليلة الماضية ، لكن ربما فاتني شيء ما.

الميزة الرئيسية المفقودة هي دعم كائن الدعابة. لم أقرر ما إذا كان يجب علينا التمسك بها بـ import.meta أو مطالبة الأشخاص باستيرادها من خلال الاستيراد {jest} من "@ jest / globals".

بالنسبة لحالة الاستخدام المطبعية ، من الأفضل أن يكون هناك استيراد صريح.

نعم ، لقد أضفت (والعودة مؤقتًا) حزمة @jest/globals تدعم هذا ، لذا سيكون ذلك متاحًا بغض النظر. أتساءل ما إذا كان من المنطقي _ أيضًا_ فضحه على import.meta . تميل حاليًا نحو عدم القيام بذلك ، ويرجع ذلك أساسًا إلى أنه من الأسهل الإضافة بدلاً من الإزالة لاحقًا (وأنا شخصياً لست من محبي الكرة الأرضية)

+1 للاستيراد الصريح ، فهو مطول أكثر ولكن أسهل في الفهم

أتلقى هذا في Node 13.2 & Jest 25.4: ES Modules are only supported if your test environment has the getVmContext function ما الذي أفتقده؟

zandaqo أوه آسف ، نسيت هذه النقطة. مضاف أعلاه ، لكنه

قم بإجراء اختباراتك باستخدام jest-environment-node أو jest-environment-jsdom-sixteen

ReferenceError: jest is not defined أعتقد أن هذا بسبب عدم وجود @jest/globals

نعم ، كما ذكرنا ، لن يعمل هذا إلا إذا لم تستخدم الكائن jest .
من المحتمل أيضًا أن تكون السخريات مكسورة ، ولم تختبرها 😃

لقد جمعت مشروعًا أساسيًا جدًا مما أراه في دليل اختبارات e2e ( e2e/native-esm/__tests__/native-esm.test.js ) وفي هذه المشكلة. ولسوء الحظ ما زلت لا أستطيع أن أجعلها تعمل ، هل يمكن لأي شخص التحقق من ذلك بأي فرصة؟

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

  • [x] jest الإصدار 25.4.0
  • [x] إصدار العقدة v13.12.0
  • يحتوي [x] package.json على خيارات الدعابة الموصى بها ولا يبدو أن تحويلات babel موجودة

تشغيل نموذج البرنامج النصي (فقط استيراد الدالة double وطباعة 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

تشغيل الدعابة باختبار واحد فقط لوظيفة مزدوجة:

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.

تحتاج إلى تشغيل العقدة بـ --experimental-vm-modules وإما أن تقوم بإدخال .mjs أو "type": "module" في package.json .

تحرير: ربما يكون لديك الخيار الأخير الذي ترى أنه يعمل خارج Jest بالنسبة لك ، فقط تفتقد العلم التجريبي إلى Node

SimenB يا نجاح باهر هناك --experimental-vm-modules و --experimental-modules . لقد كنت في حيرة من أمري من حقيقة أن --experimental-modules غير مطلوب بدءًا من بعض إصدارات العقدة 13. شكرا!

TLDR: يعمل معي node --experimental-vm-modules node_modules/jest/bin/jest.js

نعم ، من OP

يرجى ملاحظة أن Jest سيستخدم vm API (https://nodejs.org/api/vm.html) وحتى كتابة (العقدة v13.6) ، لا تزال أجزاء ESM من واجهة برمجة التطبيقات هذه تحمل علامة ( --experimental-vm-modules ). لذا فإن القول بأن ESM غير معلوم يعد تسمية خاطئة إلى حد ما في الوقت الحالي.

من الرائع أنه يعمل من أجلك ، على الرغم من ذلك!

(سأضع علامة على هذه التعليقات على أنها تم حلها)

SimenB شكرا على هذا! مشكلتان أراهما حتى الآن.

العدد 1

  • يستورد ملف اختبار وحدة ESM افتراضيًا من ملف ESM (يجري اختبار fn)
  • يقوم ملف ESM الذي يتم اختباره باستيراد افتراضي من حزمة ، والتي تقوم بتصدير CJS فقط
  • النتائج عن طريق الخطأ: ReferenceError: module is not defined في ملف حزمة CJS

لذا أعتقد أن هذا قد لا يتم تنفيذه بشكل صحيح؟

يمكن أن تشير عبارة الاستيراد إلى وحدة ES أو وحدة CommonJS

هذا يعمل بشكل جيد عند تشغيل التطبيق. لا يمكن استيراد الصادرات المسماة من CJS إلا باستخدام createRequire ، ولكن يمكن استيراد الصادرات الافتراضية فقط.

العدد 2

عندما لا أتعرض للخطأ أعلاه ، أصاب هذا الخطأ:

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

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

تفاصيل المشروع

  • العقدة 12.14.1
  • Jest and Babel-jest 25.4.0.0 تحديث
  • أحدث برنامج Babel بـ targets: { node: 12 } و 2 من الإضافات: babel-plugin-transform-import-meta و rewire-exports . (حاولت إزالة المكوِّن الإضافي import-meta ولكن ظهرت رسالة خطأ تفيد بإعادته مرة أخرى.)
  • testEnvironment: "node" هو إلى حد كبير ملف التكوين الوحيد
  • node --experimental-vm-modules node_modules/jest/bin/jest.js

إذا كان إعادة النسخ سيكون مفيدًا ، فيرجى إبلاغي بذلك.

شكراaldeed!

سأبحث في المشكلة 1 ، التي تبدو بالفعل وكأنها خطأ. EDIT: يجب أن تكون ثابتة عن طريق # 9850

يحتاج الإصدار 2 إلى العقدة 12.16.0: https://nodejs.org/docs/latest-v12.x/api/vm.html#vm_class_vm_syntheticmodule

سأغير الشيك في Jest (الآن يتحقق من vm.SourceTextModule المتوفر في إصدارات أكثر ، لكننا نحتاج إلى SyntheticModule أيضًا).

تم التأكيد على أن التشغيل مع الإصدار 12.16.0 يصلح مشكلتي 2. سيعيد اختبار المشكلة 1 بعد إصدار هذا الإصلاح. وإلا في انتظار الكائن jest لمزيد من الاختبار ، وأنا أوافق على أنه يجب استيراده.

عمل رائع ، SimenB! أحاول ذلك في مشروع صغير ولكني واجهت مشكلات مع الواردات الديناميكية. هذا هو الخطأ الذي أراه:

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

إذا قمت بإزالة عمليات الاستيراد الديناميكية ، فسيتم تشغيل الاختبار (لكنه فشل لأسباب أخرى بالطبع). يعمل نفس الاختبار حاليًا مع Mocha (التي شحنت دعم ESM مؤخرًا إلى حد ما).

إذا كان ذلك مفيدًا ، فيمكن رؤية عمليات الاستيراد الديناميكية المعنية هنا: https://github.com/beejunk/firn.js/blob/switch-to-jest/lib/renderPage.js#L43 -L55

ملف الاختبار موجود هنا: https://github.com/beejunk/firn.js/blob/switch-to-jest/test/build.test.js. يمكن رؤية نسخة Mocha العاملة في الفرع الرئيسي.

اسمحوا لي أن أعرف إذا كانت هناك أي معلومات أخرى مفيدة لي.

Beejunk شكرا! لقد كنت أتساءل عما إذا كانت هناك شروط سباق بين import s تستورد نفس الوحدة قبل أن يتم ربطها بالكامل. يبدو أن هذا ما يضربك هنا. سوف أصلح هذا اليوم ، شكرا على التقرير!

تحرير: ثابت في # 9858. نسخ الإصلاح إلى الريبو الخاص بك:
image

هل تمكن أي شخص من الحصول على هذا للعمل مع TypeScript؟ يُرجع node --experimental-vm-modules node_modules/jest/bin/jest.js نفس SyntaxError: Cannot use import statement outside a module ، على الرغم من أن package.json يحتوي على "type": "module" .

babel.config.cjs

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

jest.config.cjs

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

dandv أنت تصل إلى هذه الحالة بشكل أساسي: https://github.com/facebook/jest/pull/9772/files#r407255029

هل يمكنك فتح قضية منفصلة؟ سوف تحتاج إلى معرفة ما يجب فعله مع الامتدادات غير js

SimenB : # 9860. شكرا لإلقاء نظرة.

aldeedbeejunk 25.5.0 تم إصداره مع إصلاحات لمشاكلك. حافظ على تقارير الأخطاء قادمة

أوه ، بالإضافة إلى ذلك ، يتضمن دعمًا لـ import { jest } from '@jest/globals' لأولئك منكم الذين ينتظرون ذلك 👍

شكرًا على العمل السريع في كل هذا ،SimenB! أعتقد أنني واجهت مشكلة أخرى.

لقد كنت أجرب استخدام معلمات الاستعلام في مسار الاستيراد كطريقة لكسر ذاكرة التخزين المؤقت للوحدة على خادم تطوير. الفكرة هي أن يكون لديك مراقب ملفات يكتشف التغييرات في أحد المكونات ثم يقوم بتحديث مسار الاستيراد باستخدام معلمة استعلام عشوائية بحيث يتم سحب الكود الجديد فورًا عند تحميل الصفحة التالية دون الحاجة إلى إعادة تشغيل الخادم. يعمل هذا عند تشغيل خادم dev. ومع ذلك ، فإن Jest يلقي الخطأ التالي:

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

فيما يلي مثال على مكان استخدام معلمات الاستعلام: https://github.com/beejunk/firn.js/blob/switch-to-jest/lib/renderPage.js#L55 -L56

إذا قمت بإزالة معلمات الاستعلام ، فستنجح الاختبارات ، على الرغم من عدم استمرارها. إذا قمت بتشغيل مجموعة واحدة (على سبيل المثال ، npm test -- test/build.test.js ) ستنجح الاختبارات ، ولكن إذا قمت بإجراء جميع الاختبارات في وقت واحد ، فسوف تفشل معظم الوقت مع وجود أخطاء غامضة. ما زلت أبحث في المشكلة مع الاختبارات غير المتسقة ، لكنني اعتقدت أنني سأبلغ عن مشكلة معلمة الاستعلام أولاً.

شكرا لتقرير beejunk. من المفترض أن يتعامل # 6282 مع هذا الأمر ، ولكنه يريد أيضًا تمرير الاستعلام إلى المحولات والأشياء التي لا نحتاجها هنا. لذلك قد يكون من المنطقي فقط دعم الاستعلام داخليًا في وقت التشغيل في الوقت الحالي ، والسماح للرقم # 6282 فقط بالتعامل مع تمرير هذا الاستعلام.

لقد أضفت القليل من التعليمات البرمجية لجعل ذاكرة التخزين المؤقت للوحدة تختلف حسب الاستعلام: https://github.com/facebook/jest/blob/d425a49bd575e7167bc786f3c4f2833589091fa1/packages/jest-runtime/src/index.ts#L330 -L334

ولكن لا يوجد رمز يتصل به مع استعلام. أعتقد أننا يجب أن نكون قادرين على القيام بـ resolvePath.split('?') ويجب أن يعمل الجميع.

فيما يتعلق بالأخطاء غير المتسقة ، سألقي نظرة إذا كان هذا الريبو يعيد إنتاجها. لم أختبر رمز ESM مع الاختبارات المتوازية ، فقط اختبار واحد. لست متأكدًا من سبب تأثيرها على الأشياء ، لكن من يدري 😀

beejunk استعلام شيء ثابت في

لدي مشكلة أعتقد أنها قد تكون مرتبطة بهذا ولكن لم يتم إصلاحها في 25.X .

سأحاول تلخيص escenario أدناه:

  • لديك اختبار مع برنامج نصي الإعداد
  • سيتطلب برنامج الإعداد هذا ملفًا ديناميكيًا ، كما في:
    { default: generator } = require(path.resolve(f))
  • كل شيء بداخل f لا يتم نقله مما يتسبب في "خطأ غير متوقع في استيراد المعرف".

يحدث هذا أيضًا إذا حاولت الاستيراد ()

منذ أن ذكرت الترشيح ؛ إذا كان لديك إعداد يقوم بنقل import إلى require فهذه المشكلة ليست المكان الصحيح - هذه المشكلة تتعلق بالدعم المحلي.


ومع ذلك - لا يمكنك require ESM ، ولم أتمكن من إضافة دعم import() من CJS حتى الآن بسبب عدم وجود واجهة برمجة تطبيقات Node لها. لقد وصل الدعم لذلك إلى Node master ، ولكن لم يتم إصداره بعد: https://github.com/nodejs/node/pull/32985. كما يتضح من الإصدار المرتبط PRs ، فإنه سيأتي في 13.14.0 و 14.1.0. في هذه المرحلة ، سأقوم بتنفيذ الدعم لها 👍

يجب أن تكون قادرًا على استخدام ملف إعداد .mjs بالرغم من ذلك.

SimenB هذا رائع ، يبدو أنه يعمل في عدة ملفات اختبار الآن! إنها عملية بسيطة لحل الاختلافات بين استيراد Babel و Node في كل ملف ، وإضافة استيراد jest ، وما إلى ذلك ، لذلك قد أواجه المزيد من المشكلات كما أفعل ذلك عبر مئات ملفات الاختبار.

بعض الأشياء التي تكون أسئلة أكثر:

  • ما قلته في تعليقك السابق حول دعم import() من cjs ، هل سيسمح ذلك أيضًا لملف تكوين Jest بالاسم jest.config.js ؟ إنه يعمل حاليًا فقط عند تسميته jest.config.cjs وباستخدام module.exports = (الخطأ هو TypeError [ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING]: A dynamic import callback was not specified )
  • فشل الاسم "@ jest / globals" في قاعدة eslint node/no-extraneous-import نظرًا لعدم كونها حزمة مُدرجة في package-lock . هل هناك سبب لهذا الاصطلاح التسمية؟ هل من الممكن استخدام jest بدون @ ؟ من السهل تجاهل القاعدة لكني أتساءل فقط.
  • السؤال ذو الصلة ، لماذا يختلف jest عالميًا عن fns السحري مثل test ، describe ، before ، إلخ؟ هل يجب استيراد كل هؤلاء الآن أيضًا؟
  • عند الانتهاء من ذلك ، هل سيكون من الممكن لـ Jest تعيين العلم --experimental-vm-modules ؟ إنه نوع من يجعل هذا يبدو غير قياسي إذا لم يعمل فقط مع الأمر jest . إذا لم تكن قادرًا على تمرير العلامات مباشرةً ، فربما يمكنك تعيين / تعديل متغير env NODE_OPTIONS ؟
  • يبدو الآن أنني حصلت على خطأ مختلف قليلاً عن ذي قبل عند تجربة هذا على Node الأقدم ، لكن لم يكن أي من الخطأ واضحًا أن الحد الأدنى من إصدار Node كان هو المشكلة. هل من السهل إضافة فحص للحد الأدنى من الإصدار مع ظهور رسالة خطأ أكثر إفادة؟

هل سيسمح ذلك أيضًا بتسمية ملف تهيئة Jest باسم jest.config.js؟

يمكن تسميته .js إذا كان أقرب package.json يحتوي على type: 'module' . وإلا لاستخدام ESM في ملف التكوين ، يجب تسميته .mjs . راجع https://nodejs.org/api/esm.html#esm_enabled. لاحظ أن ملف التكوين يعمل خارج Jest ، لذلك ليس لدينا الكثير من التحكم. في الوقت الحالي ، لا ندعم التهيئة غير المتزامنة ، لكن الوعد الذي تم تصديره await سيكون تافهًا ، ترحيب العلاقات العامة 🙂 # 8357 توقف.

أنا مندهش جدًا من حصولك على A dynamic import callback was not specified بالرغم من ذلك ، لا نقوم بتحميل ملف التكوين في جهاز افتراضي ... هل يمكنك فتح مشكلة منفصلة؟

فشل الاسم "@ jest / globals" في قاعدة eslint node/no-extraneous-import نظرًا لعدم كونها حزمة مُدرجة في package-lock . هل هناك سبب لهذا الاصطلاح التسمية؟ هل من الممكن استخدام jest بدون @ ؟ من السهل تجاهل القاعدة لكني أتساءل فقط.

يجب عليك إضافة devDependency على @jest/globals . الحزمة نفسها هي فقط نوع التعريفات. إنها حزمة منفصلة من jest لذلك تعمل تعريفات النوع بشكل صحيح ، وبالتالي يمكننا أن نلقي بالخطأ إذا تم تحميلها خارج وقت تشغيل Jest.

ليس لدي حاليًا أي خطط لتغيير ذلك ، ولكن ربما يمكننا إهمال هذه الحزمة وتصدير الأنواع من jest . هذا تغيير كبير ، لذلك دعونا نرى لاحقًا 🙂

السؤال ذو الصلة ، لماذا يختلف jest عالميًا عن fns السحري مثل test ، describe ، before ، إلخ؟ هل يجب استيراد كل هؤلاء الآن أيضًا؟

jest يشبه require أو module كائن من CJS من حيث أنه فريد لكل ملف ، وليس في الواقع عالميًا (مثل globalThis.jest === undefined ). هذا يسمح jest.mock('../../file.js') إلخ للعمل بشكل صحيح بالنسبة للملف الذي تم إدخاله فيه. يمكنك أيضًا اختيار استيراد الكرات الأرضية الفعلية ، لكنها لا تزال متاحة كـ globalThis.expect إلخ.

عند الانتهاء من ذلك ، هل سيكون من الممكن لـ Jest تعيين العلم --experimental-vm-modules ؟

أعتقد أننا سننتظر حتى تقوم العقدة بإلغاء علاماتها بدلاً من تعيينها بصمت - تم وضع علامة عليها لسبب ما ، وقد تتغير واجهة برمجة التطبيقات في مرحلة ما. يمكننا إضافة خيار يقوم بتعيين NODE_OPTIONS ما أعتقد ، ألست متأكدًا مما إذا كان ذلك يغير وقت التشغيل الحالي؟ بغض النظر ، لا توجد خطط حالية لذلك.

يبدو الآن أنني حصلت على خطأ مختلف قليلاً عن ذي قبل عند تجربة هذا على Node الأقدم ، لكن لم يكن أي من الخطأ واضحًا أن الحد الأدنى من إصدار Node كان هو المشكلة. هل من السهل إضافة فحص للحد الأدنى من الإصدار مع ظهور رسالة خطأ أكثر إفادة؟

نعم ، سأضيف رسالة خطأ أفضل مع بعض الوثائق بمجرد استقرار التطبيق قليلاً. نظرًا لأن التطبيق يخضع للحراسة بواسطة علم تجريبي ، لا أعتقد أن أي شخص سيتعثر عليه.

SimenB ، لقد قمت بتحديث

حسنًا ، لقد رأيت الأخطاء مرة أخرى في آخر تشغيل لي للاختبارات ، لذلك لا يزال هذا يحدث. سأرى ما إذا كان بإمكاني اكتشاف طريقة لإعادة الإنتاج وتقديم التقارير باستمرار.

أعتقد أنني وجدت طريقة ثابتة لإعادة إظهار المشكلة. هنا هو الفرع الذي أعمل منه: https://github.com/beejunk/firn.js/tree/switch-to-jest

لإعادة إنتاج:

  1. احذف ذاكرة التخزين المؤقت Jest إذا كانت موجودة. لقد قمت للتو بحذف /tmp/jest_rs يدويًا.
  2. قم بتشغيل npm test ثلاث مرات. يجب أن ينجح أول تشغيلين. ومع ذلك ، يجب أن تفشل الجولة الثالثة.

هذا هو تتبع المكدس الذي أراه عند حدوث الخطأ:

    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)

يبدو أن الخطأ ناشئ عن عمليات الاستيراد الديناميكية. لا توجد رسالة خطأ ، لذلك لست متأكدًا تمامًا مما يحدث.

ملاحظة إضافية: إذا قمت بمسح ذاكرة التخزين المؤقت Jest وقمت بتحديث البرنامج النصي للاختبار عن طريق إضافة --no-cache ، فلن أتمكن من إعادة إظهار المشكلة.

هيه ، لقد كنت كسولًا هناك ولم أقدم رسالة خطأ مناسبة. المشكلة هي أن بيئة الاختبار قد هُدمت ، لذلك أعتقد أن هناك مفقودًا await مكان ما. لم أر أي شيء يبحث في التعليمات البرمجية الخاصة بك ، لذلك سأضطر إلى البحث عن المزيد

SimenB إليك نسخة من مشكلة تكوين ESM: https://github.com/facebook/jest/issues/9935

SimenB لقد أنشأت مثالًا بسيطًا لإعادة إنتاج أخطاء Jest التي ذكرتها أعلاه عند استخدام عمليات الاستيراد الديناميكية:

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

شكرا على الاستنساخ الرائعbeejunk! لقد أمضيت المزيد من الساعات التي يهمني أن أعترف بها هنا ، دون أن أفهم حقًا ما إذا كان خطأ في Jest أو في Node. لقد أعدت إنتاج السلوك باستخدام الوحدات الأساسية للعقدة فقط وأبلغت عنه في المنبع ، لذلك دعونا نرى ما يقولونه: https://github.com/nodejs/node/issues/33216

شكرا للنظر في الأمر ، SimenB. يبدو أن الاختبارات تمر باستمرار إذا أضفت علامة --no-cache ، وهو أمر جيد بالنسبة لحالة الاستخدام الخاصة بي. أنا أقدر كل العمل!

نعم ، لقد لاحظت ذلك أيضًا. أعتقد أنها نوع من مشكلة التوقيت - مع عدم وجود ذاكرة تخزين مؤقت ، تكون الأشياء بطيئة بدرجة كافية بحيث تعمل.

SimenB شكرا لحل # 9935. لقد ذكرت مصدر قلق آخر هناك ، والذي أعتقد أنه لا يزال ساريًا. عندما type: "module" ، لا يزال jest --init ينشئ ملف التكوين بداخله module.exports . يعد هذا بسيطًا نسبيًا لتغييره يدويًا إذا كنت تعرف ما تفعله ، لكنني أعتقد أنه إذا لم يتم الإبلاغ عن ESM في Node وبدأ الكثير من الأشخاص في تنفيذ مشاريع ESM ، فسيبدأ في الظهور وكأنه خطأ مربك (على سبيل المثال ، مسار سعيد لـ jest --init && jest في مشروع ESM جديد سيظهر خطأ). هل يجب أن أرسل مشكلة مختلفة تتعلق بتحسين منطق init بالتحديد؟

aldeed هل أنت متأكد؟ يمنحني الاختبار الآن ملفًا mjs بداخله export default . أعتقد أنه يمكننا توليد js وليس mjs ، لكن لا يزال. يستخدم بناء جملة ESM

SimenB حسنا كنت متأكدا حتى طلبت. "لقد جربتها وأنت على صواب. ربما فعلت ذلك في البداية باستخدام إصدار أقدم من Node أو Jest؟ تجاهل.

هذا رائع! أعدت للتو الاختبارات في إحدى مكتباتي لاستخدام وحدات ES وتخلصت من Babel. شكرا SimenB!

اكتشف ما إذا كان من المفترض أن يكون الملف في وضع ESM أو CJS

عند الحديث عن هذا ، هناك الكثير من الحزم الموجهة للمتصفح / الحزم خارجها باستخدام بناء الجملة "module":"<path to es module>" للإشارة إلى صادرات الوحدة ES الخاصة بهم. قد يكون من الحكمة أن يكون لديك طريقة ما لتحديد كيفية حل حزمة معينة بغض النظر عن إعدادات الحزمة الخاصة. شيء من هذا القبيل moduleNameMapper ولكن لتحديد ما إذا كان CJS أو ESM.

مرحبًا SimenB ، بمجرد إغلاق هذه المشكلة ، فهذا يعني أن ts-jest يمكنه أيضًا إلغاء فرض commonjs أليس كذلك؟ هل امتداد الملف مطلوب للتغيير من جانب المحول للعمل مع ESM؟

على سبيل المثال الآن ts-jest يجمع ts إلى js لـ commonjs ، لا يتطلب esm امتداد الملف mjs عند التجميع من ts إلى js ؟

zandaqo لن ندعم الحقل modules ، سنتبع مواصفات العقدة ونستخدم exports : # 9771. يمكنك توصيل المحلل الخاص بك لدعم modules إذا كنت تريد ، على الرغم من: https://jestjs.io/docs/en/configuration#resolver -string. قد نضيف خيارًا آخر ( mainFields ، مثل webpack ربما؟) ، لكن هذا سيأتي بعد ذلك عندما يستقر التطبيق ويكون لدينا مجهول أقل 🙂


ahnpnl # 9860

يا شباب!
مجرد سؤال: يذكر منشور المدونة أنه نظرًا لأن وحدات ES6 ثابتة ، فلا يمكن السخرية منها ؛ لذلك ، في الواقع ، لا توجد طريقة للسخرية من وحدة A تم استيرادها بواسطة الوحدة B في ES6؟

gabrieledarrigo أستخدم moduleNameMapper لذلك ، على سبيل المثال:

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

gabrieledarrigo يمكنك القيام به

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

let importedThing;

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

لذلك تحتاج فقط إلى جعل الاستيراد غير ثابت وسيعمل السخرية.

لست متأكدًا من أنه يعمل الآن ، لأنني لم أحصل على دقة وهمية في مسار رمز ESM حتى الآن. سأفعل ذلك في وقت ما في القريب العاجل. ولكن من المحتمل أن تكون هذه هي الطريقة التي نوثق بها نماذج الوحدات النمطية لـ ESM الأصلي.

كما هو مذكور في أواني المدونة ، سنقوم بتوثيق هذه الأنماط في مرحلة ما ، علينا فقط اكتشافها 🙂

كانت إحدى الأفكار التي كانت لدينا هي انتظار انتظار المستوى الأعلى ، ثم يمكننا القيام بذلك باستخدام مكون بابل الإضافي.

SimenB بادئ ذي بدء ، شكرا لك على العمل الرائع هنا :)

أواجه بالفعل مشكلة عندما أرغب في إنشاء بيئة مخصصة ممتدة من jest-environment-node . أحتاج إلى استيراد تطبيق الخادم الخاص بي هناك ، والذي تمت كتابته كـ esm. ولكن يبدو أنه يجب تعريف البيئة على أنها cjs .
سؤالي هو ، هل هناك خيار لتحديد بيئة اختبار مخصصة كـ ESM لتتمكن من استيراد وحدة الخادم الخاصة بي؟ شكرا لك على أي نصيحة.

@ kuka-radovan هل يمكنك فتح طلب ميزة منفصل لذلك؟

تحديث: يتم الآن تتبع هذه المشكلة في https://github.com/facebook/jest/issues/10025

SimenB شكرا jest.mock أعلاه. كما يحدث ، أقوم بتحويل بعض الملفات التي تحتاج إلى ذلك اليوم. يمكنني أن أؤكد أن مثالك يعمل عندما تكون الوحدة النمطية التي تم الاستهزاء بها عبارة عن حزمة node_modules ، لكنها لا تعمل بالنسبة لي عندما تسخر من وحدة في نفس المشروع.

إليك مثال بسيط:

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

يعمل النمط نفسه تمامًا عندما يكون "./secondary.js" اسم حزمة بدلاً من ذلك. (أعتقد أن الحزمة التي جربتها مع تصدير CommonJS ، إذا كان ذلك مهمًا.)

Jest 26.0.1 w / Node 12.16.3

أي أفكار ، أم ينبغي علي إرسال عدد منفصل كامل؟

تحرير: transform: {} في التكوين ، لذلك لا يوجد Babel على الإطلاق

تحرير 2: هذا لا يعمل أيضًا:

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

عمل رائع على هذا.

ومع ذلك ، ما لم أفعل شيئًا خاطئًا ، فلا يبدو أنه من الممكن استخدام import() في ملف اختبار CJS.

أنا أدير Jest بـ node --experimental-vm-modules node_modules/jest/bin/jest.js ولدي testEnvironment: 'node', transform: {} في jest.config.js . هذا موجود على العقدة 14.2.0.

ينتج عن تعبير الاستيراد خطأ:

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

هل هذا قيد معروف في الوقت الحاضر؟ أرى https://github.com/nodejs/node/pull/32985 قد هبط الآن في Node 14.1.0.

نعم ، لم أتمكن من تنفيذه بعد. ربما سأهبط عليه في نهاية هذا الأسبوع.

aldeed هل يمكنك فتح قضية منفصلة؟ أحتاج إلى المتابعة والتأكد من أن السخريات جزء من الدقة ، ويبدو أن مثالك يمثل حالة اختبار جيدة 🙂

SimenB شكرا على الرد السريع. سأراقب عندما تهبط.

بالنظر إلى أن البرامج النصية import في قد يتم إرجاعها بسبب الانحدار (https://github.com/nodejs/node/issues/33166) ، فلننتظر حتى يستقر ذلك

أواجه مشكلات أثناء محاولة استخدام هذا مع ملفات اختبار .mjs . إذا كان لدي __tests__/my-test.mjs ، فسأحصل عليه

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

إذا أضفت

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

إلى طردي. json ، أحصل عليه

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

ومع ذلك ، إذا قمت بإزالة "testMatch" ثم أعدت تسمية الملف الخاص بي إلى __tests__/my-test.js ، فسوف يعمل.

أود أن أكون قادرًا على استخدام امتدادات .mjs باستمرار في مشروعي. هل هذا ممكن مع Jest؟

@ دومينيك واجهت هذا أيضا. الحل هو إضافة إلى config "moduleFileExtensions": ["js", "mjs"] (بالإضافة إلى "testMatch" ).

ألقوا نظرة ، و moduleFileExtensions ضروري بالفعل.

يحصل Jest على قائمة بجميع الملفات في المشروع من خلال تشغيل hasteFS.getAllFiles() هنا:

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

hasteFS كجزء من HasteMap باستخدام التهيئة التالية extensions :

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


ومع ذلك ، لا أعتقد أنه من الضروري تحديد moduleFileExtensions في هذه الحالة بالرغم من ذلك. لقد فرضنا بالفعل العثور على .snap ، فهل يجب علينا فرض امتدادات JS المعروفة أيضًا؟ هؤلاء (خارج رأس رأسي) js ، mjs ، cjs ، jsx ، ts و tsx ؟ ستجعل عملية الزحف أبطأ ، لكنني لا أعتقد أن لها تأثيرًا كبيرًا. قد أكون على خطأ على الرغم من؟ كإعداد افتراضي ، لا ينبغي أن يكون أبطأ كثيرًا نظرًا لأن cjs و mjs ليس جزءًا من الأنماط الافتراضية بالفعل ، ولكن بالنسبة للأشخاص الذين لديهم أنماط مخصصة ، فقد يؤدي ذلك إلى إبطاء الأمور؟

نعم ، سيكون الأمر مثاليًا ، على الأقل في وضع وحدات ES ، إذا عملت .mjs للتو ، دون الحاجة إلى إضافة moduleFileExtensions أو تعديل testMatch الافتراضي.

سيكون من الجيد أيضًا أن أستبعد ملفات .js ؛ عندما حاولت ذلك حصلت

 Validation Error:

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

أتساءل عما إذا كان من المنطقي أن يكون لديك بعض "وضع ESM" الذي من شأنه أن يضيف امتدادات ملفات node esm ويساعد أيضًا في التحويل البرمجي إلى js باستخدام esm للاشتراك (# 9860).


بدون js بعض الأشياء تنكسر داخليًا نقوم بتحميلها داخل sandbox (لأنها تستخدم نفس تطبيق require إلخ). ربما يجب أن نصلح ذلك حتى لا يتمكن المستخدم من كسرنا.

فيما يتعلق بالتباطؤ ، فهو بالفعل بطيء جدًا في المشاريع الكبيرة ، لكنني لا أعرف أن عدد الإضافات يؤثر كثيرًا. لكنني أوافق على أنه يجب إضافة mjs و Cjs كإعدادات افتراضية. سيؤدي تحديد moduleFileExtensions: ['js'] إلى تجاوز الإعدادات الافتراضية وتسريعها ، أليس كذلك؟ لذلك ربما فقط قم بتوثيق ذلك كتعديل في الأداء.

شكرا لكل هذا العمل! إنه لأمر مدهش بالتأكيد. لقد اتبعت الخطوات الثلاث ( "type": "module" على package.json الخاص بي ، "testEnvironment": "jest-environment-node" في تكوين jest الخاص بي و --experimental-vm-modules على CLI) ويبدو أنها تعمل بشكل جيد 🎉

ولكن بعد ذلك أحاول قراءة واستخدام import.meta كما هو موضح في مستندات Node.js (والذي يبدو أنه تم تنفيذه بالفعل من خلال مربع الاختيار) لإنشاء __dirname ، لكن يبدو أنه import.meta فشل:

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.

ليس لدي أي بابل واعتقدت أن بابل تُركت وراء هذا العمل. سأعود للإبلاغ عما إذا كان بإمكاني إصلاحه بطريقة ما دون تثبيت بابل.

Node.js v14.3.0 و Jest v25.5.4

لقد وجدت حلاً الآن. نظرًا لأنني أقوم بتشغيل البرنامج النصي من نفس الدليل حيث يوجد ملفي في مكتبتي ، يمكنني فقط القيام بما يلي:

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

سأتبع هذا الريبو في حالة وجود أي تحديث ، شكرًا مرة أخرى على القيام بذلك!

تحتاج إلى إلغاء الاشتراك في Babel بشكل صريح باستخدام transform: {} كتكوين

SimenB أستطيع أن أؤكد أن إضافة transform: {} نجح ، شكرًا! لقد أساءت فهم هذه النقطة على أنها "لا تضيف تحويلات" وليست "تأخذ التحولات بعيدًا" على النحو المنشود.

راجع للشغل ، فقد انتقل الاختبار من 2.4 ثانية إلى 1.3 ثانية فقط ويشعرون بشكل أسرع باستمرار.

تم إصدار العقدة 12 باستخدام ESM بدون علامات (https://nodejs.org/en/blog/release/v12.17.0/). كما هو مذكور في OP ، فإن استخدام APIs Jest _not_ لم يتم وضع علامة عليه

SimenB لقد تجاوزت هذا الموضوع عدة مرات لكنني ما زلت عالقًا (باستخدام العقدة 12.17).

عند تشغيل Jest 26.0.1 ، يظهر لي هذا الخطأ:

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.

لدي transform: {}, وأعمل بـ node --experimental-vm-modules node_modules/jest/bin/jest.js .

ماذا ينقصني؟

aldarund غير متأكد ، هل يمكنك تجميع الحد الأدنى من الاستنساخ؟

SimenB ، ها هو الحد الأدنى من الريبو الذي يمكنك إعادة تشغيله ، فقط قم بتشغيل yarn test https://github.com/aledalgrande/jest-example - لقد جربت مع Node 13/14 وهي نفس النتيجة. يبدو لي أنه لم يتم تحديث تدفق الإعداد العام للعمل مع ESM.

أيضًا ، لقد ذكرت شخصًا آخر

~ ليس simenB ، ولكن aledalgrande يبدو أن كل شيء صحيح هنا مما جربته ، شاهد مشروعي يعمل بالكامل على ESM للمقارنة (تكوين jest في package.json ). ~

~ لتصحيحها إن أمكن ، أقترح تبسيط تكوين jest الخاص بك إلى _ فقط_ الخاصيتين المرتبطين ، وربما حتى في package.json أولاً. ثم أضف كل خاصية من الخصائص الأخرى التي لديك حاليًا لمعرفة أي منها يعمل / لا يعمل

آه ، التعليق الثاني يذكر globalSetup وليس اختبارات عادية ، nvm تعليقي بعد ذلك. إذا قمت بإزالة المفتاح globalSetup في Jest ، فسيتم تشغيل الاختبار كما هو متوقع في هذا المثال ، لكن المفتاح globalSetup لا يعمل كما قلت.

آها ، لقد نسيت الإعداد الشامل والتفكيك. يمكن إصلاح 👍

مرحبًا SimenB ، أنا مرة أخرى. هل الصادرات المسماة معتمدة؟ باستخدام Node.js يمكنني استيراد حزمة مثل هذه واستخدامها:

import { customAlphabet } from "nanoid";

ومع ذلك ، عند محاولة إجراء اختبار ، يعطي نفس الرمز هذا الخطأ:

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

بالنسبة للاختبارات ، يمكنني تغيير الكود إلى هذا ويعمل:

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

ولكن بعد ذلك ، توقف إصدار Node.js عن العمل نظرًا لعدم وجود رياضة افتراضية في الواقع (ولكن لسبب ما ، يعمل التصدير الافتراضي مع Jest):

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

المنشور (يبدو أن الريبو في حالة تغير مستمر الآن) ينتهي كود nanoid بهذا الشكل ، بدون تصدير افتراضي:

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

يستهلك Jest فقط نقطة الدخول "الرئيسية". لم يتم النظر في "الصادرات" حتى الآن. ما عليك سوى استيراد إصدار Commonjs الذي يحتوي على تصدير افتراضي فقط.

آه أرى ، يبدو أن package.json يتضمن هذا:

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

لذلك من المحتمل أن Node.js يعثر على إصدار الوحدة النمطية ، بينما يستخدم Jest إصدار CommonJS الذي لا يحتوي على تصدير مسمى ، أليس كذلك؟

سأنتظر حتى يتم فحص Package Exports ثم أختبره ، شكرًا على كل العمل مرة أخرى! وضع علامة "تم الحل" على هذين التعليقين حتى ذلك الحين. الاختبار الذي أشير إليه هو هذا .

سأعيد النظر في هذا لمعرفة كيفية عملها - تمت ترقيته إلى Jest 26.0.1 والعقدة 14.4. عيّن package.json إلى نوع الوحدة النمطية ، واضبط التحويل على {} ، و env على jest-environment-node ويعمل بـ node --experimental-vm-modules . الآن أتلقى هذا الخطأ الجديد:

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

لم أتمكن من العثور على معلومات حول هذا الأمر باستثناء سجل التغيير من Jest يقول إن getVmContext تمت إضافته منذ فترة.

أيه أفكار؟

هل يمكنك مشاركة الأجزاء ذات الصلة من package.json فضلك cyberwombat ؟ بما في ذلك برنامج التشغيل الذي تستخدمه لـ Jest.

كمرجع ، هكذا تبدو لي في مشروع عمل :

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

ثم قم بتشغيله بـ npm test

franciscop Mine في الأساس هو نفسه. العقدة 14.4.0. يمكنني تشغيل لك بشكل جيد. سوف أغوص في الأشياء لرؤية الفرق.
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>'
  ]
}

النصي:
node --experimental-vm-modules node_modules/jest/bin/jest.js

لست متأكدًا ، لكنني سأحاول العمل في الاتجاه المعاكس. قم بإزالة كل شيء باستثناء transform: {} و testEnvironment: 'jest-environment-node' ، وابدأ في إضافة كل خيار حتى ترى الخيار الذي تسبب في الخطأ السابق. أشك بشكل خاص في أن transformIgnorePatterns _might_ يتعارض مع transform ، لكنني لست على دراية بخيارات الدعابة.

أهلا بالجميع! واجهت بعض المشكلات أثناء استخدام Jest لاختبار تطبيق Express. مزيد من التفاصيل هنا . لست متأكدًا مما إذا كان ذلك مفيدًا لما تفعله / تتبعه هنا: roll_eyes:

@ x80486 لقد واجهت نفس المشكلة أمس بالضبط . لقد أجبت في StackOverflow بشرح أطول من فهمي.

تحرير: لقد قمت بإلغاء إخفاء تعليقي السابق لأنه يبدو أنه قد يكون ذا صلة ، ويبدو أن هذا "exports" شائع ، ومن المحتمل جدًا من هذه المقالة عن الحزم المختلطة .

يتم تعقب exports في 9771 #

franciscop ok تم حل المشكلة - اتضح أن هناك تعارضًا في الحزم - لقد تم تثبيت serverless-bundle مما تسبب في حدوث خطأ ES Modules are only supported if your test environment has the getVmContext function . لست متأكدًا من السبب - أفترض أن تثبيته لن يتسبب في حدوث تعارض جاري ولكن من الواضح أنه يحدث.

@ franciscop أعتقد أن سبب بدء ظهور المشكلات المتعلقة بـ pkg.exports الآن هو أن هذه الميزة لم يتم وضع علامة عليها في Node.js 14.x وأن بعض المشرفين على الحزم (مثلي مقابل uuid ) بدأوا إضافة حقول pkg.exports . لذلك بينما كنت بحاجة إلى علامة سطر أوامر لتنشيط هذه الميزة في Node.js 12.x تحصل على هذا السلوك افتراضيًا الآن.

سيستغرق الأمر بعض الوقت حتى يتكيف النظام البيئي بأكمله ، لذا نشكرك على الإبلاغ عن المشكلات المتعلقة بهذا الموضوع!

بالنسبة لأولئك الذين ينشرون حول exports ، في حالة فقده في سلسلة طويلة من هذه المشكلة ، فإن مشكلتي المغلقة حول هذا الموضوع (https://github.com/facebook/jest/issues/9565) لديها مثال من الحل البديل moduleNameMapper فيه.

من المحتمل أن مشكلة globalSetup الإبلاغ عنها في مايو لا تزال موجودة (Jest 26.1.0)؟ الحصول على نفس الأخطاء كما في المثال يوفر repoaledalgrande :

$ 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 

لا داعي للاندفاع. تحقق من CHANGELOG ولم يذكر إصلاحًا لـ globalSetup / globalTeardown مع ES6.

Node.js 14.4.0 ، جيست 26.1.0


التحديث (13-أغسطس -20):

لا يزال غير ممكن ، Node.js 14.7.0 ، Jest 26.4.0

رأي جانبي ، لكن هل يجب أن تكون هذه القضية مشكلة معلقة لأنها محور الدعابة في الوقت الحالي؟

أي أفكار حول ما يجب القيام به لاستهلاك مراسلي الاختبار المكتوبين في وحدات ES؟ ...
مع أحدث إصدار دعابة ، أتلقى خطأ يقول بشكل أساسي أن testScheduler يتوقع مراسلًا مخصصًا بتنسيق commonjs.


لرؤية الخطأ

~ / project / esw-ts / lib / dist / test / testReporter.js: 1
استيراد نظام التشغيل من "نظام التشغيل" ؛
^ ^ ^ ^ ^ ^

SyntaxError: لا يمكن استخدام عبارة الاستيراد خارج وحدة نمطية
في wrapSafe (داخلي / وحدات / cjs / loader.js: 1116: 16)
في Module._compile (داخلي / وحدات / cjs / loader.js: 1164: 27)
في Object.Module._extensions..js (داخلي / وحدات / cjs / loader.js: 1220: 10)
في Module.load (داخلي / وحدات / cjs / loader.js: 1049: 32)
في Function.Module._load (داخلي / وحدات / cjs / loader.js: 937: 14)
في Module.require (داخلي / وحدات / cjs / loader.js: 1089: 19)
عند الطلب (داخلي / وحدات / cjs / helpers.js: 73:18)
في /Users/manish.gowardipe/Desktop/projects/esw-ts/lib/node_modules/@jest/core/build/TestScheduler.js:418:65
في Array.forEach ()
في TestScheduler._addCustomReporters (/ المستخدمون/manish.gowardipe/Desktop/projects/esw-ts/lib/node_modules/@jest/core/build/TestScheduler.js:411:15)

مرحبًا ، أرغب في اختبار الدعم الأصلي لوحدات ES في مشروعي الصغير ، لكنني جديد على NodeJS وقد ضاعت في هذا العدد ، أود الحصول على بعض الإرشادات من فضلك.

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);
});
  • أقوم بتشغيل yarn jest . ويعطيني هذا الخطأ:
    imagen

  • حاولت باستخدام node node_modules/jest/bin/jest.js . وهو يعطيني نفس الخطأ.

@ pepetorres1998 يدور هذا الموضوع حول تشغيل Jest مع وحدات التعليق أعلاه لمعرفة ما يجب فعله (وقم بتعيين "type": "module" في package.json). بصراحة ، على الرغم من أنه في هذه المرحلة ليس جاهزًا تمامًا لوقت الذروة ، لذا إذا كنت بحاجة إلى عمل مشروعك ، فقد ألتزم ببرنامج Babel. هناك عدد من المشكلات التي لم يتم التحقق منها والتي تعمل على إيقاف عرض حقيقي. حاولت بفرح التبديل قبل أسبوعين وعدت أبكي إلى بابل.

هل يحصل أي شخص آخر على ReferenceError: jest is not defined عند محاولة القيام بأشياء مثل jest.setTimeout(...) في ملف اختبار بهذا الإعداد؟ محاولة اكتشاف ما إذا كان هذا متعلقًا ببيئة الوحدة النمطية es أو إصدار العقدة أو إصدار الدعابة أو مجموعة من هذه الأشياء. (يتم حاليًا استخدام العقدة v14.5.0 و jest 26.1.0 و jest-environment-node)

تعديل
أرى الآن مربع الاختيار غير المحدد في وصف المشكلة للخاصية "العامة" المزحة. 🙃

bdentino أعتقد أنه يمكنك محاولة استيراده بشكل صريح import {jest} from '@jest/globals';

تم تحرير 25.4.0 مع قطع الدعم الأولى. بالإضافة إلى # 9772 المذكورة أعلاه ، قمت أيضًا بتضمين # 9842. في _theory_ يجب أن يعمل خلط CJS و ESM بشكل صحيح الآن (🤞).

الميزة الرئيسية المفقودة هي دعم الكائن jest . لم أقرر ما إذا كان يجب علينا التمسك بها import.meta أو مطالبة الأشخاص باستيرادها من خلال import {jest} from '@jest/globals' . نقدر ردود الفعل!

لم أكتب مستندات لهذا حتى الآن ، ولكن لتنشيطه ، عليك القيام بثلاثة أشياء

  1. تأكد من عدم تشغيل تحويل بيانات import (قم بتعيين transform: {} في التكوين أو تأكد من أن babel لا يحول الملف إلى CJS ، مثل تجنب modules خيار الإعداد المسبق)
  2. قم بتشغيل node@^12.16.0 || >=13.2.0 باستخدام علم --experimental-vm-modules
  3. قم بإجراء اختبارك باستخدام jest-environment-node أو jest-environment-jsdom-sixteen

يرجى تجربتها وتقديم الملاحظات! إذا قمت بالإبلاغ عن الأخطاء ، فسيكون من الرائع أن تتمكن من تضمين كيفية تشغيل نفس الكود (باستثناء أي كود اختبار محدد) في Node. لقد قرأت https://nodejs.org/api/esm.html _ الكثير_ على مدار الأسابيع القليلة الماضية ، لكن ربما فاتني شيء ما.

تضمين التغريدة
أصبح هذا الموضوع هائلاً ، وأعتقد أن أولئك الذين يريدون البدء بوحدات المزحة / استخدام وحدات ES - سيواجهون صعوبات في العثور على المبادئ التوجيهية الأساسية وفهمها لبدء القيام بذلك.
هل يوجد تفسير رسمي في المستندات حول إضافة دعابة إلى مشروع وحدات ES (أو بعض "البداية السريعة")؟

aldeed فيما يتعلق

(راجع للشغل ، نحن نستخدم أيضًا التفاعل التجاري ، لذا في صحتك لهذه الهاها)

guilhermetelles لا ، ويتم تعقبها في https://github.com/facebook/jest/issues/10025 الآن.

أنا أستخدم Jest 26.1.0 ، الإصدار 14.6.0 node مع --experimental-vm-modules ، لكن ما زلت أرى ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING عند استخدام import() داخل CommonJS . هل يجب أن أحاول التوصل إلى الحد الأدنى من إعادة النشر وفتح إصدار جديد؟

جانبا ، هل هناك طريقة سهلة لنسخة yarn link نسخة من حزم jest في مشروع الآن يستخدم Jest غزل التوت؟ كنت أرغب في تجربة أحدث master فقط في حالة تنفيذ ذلك من قبل لم يتم إصداره بعد. كنت أحاول القيام بشيء مثل path/to/facebook/jest/.yarn/releases/yarn-sources.cjs link --all path/to/jest ، لكنه سيفشل. تشغيل شيء مثل 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 يدويًا لم يكن يعمل أيضًا ، ولست متأكدًا من السبب.

vvanpo import() في CJS تم إرجاعه في Node ، يمكنك متابعة https://github.com/nodejs/node/issues/31860

بالنسبة إلى التشغيل المحلي ، عادةً ما أقوم بإلغاء تثبيت jest من المشروع الذي أريد اختباره وإجراء ../jest/jest . يحتمل أن يكون nose ../jest/packages/jest/bin/jest.js . فقط تأكد من تشغيل yarn و yarn build:js أولاً. إذا لم تنجح هذه التعليمات (أنا أكتب من الذاكرة على هاتف على متن طائرة) ، يرجى فتح مشكلة (أو PR) حتى نتمكن من كتابة هذا بشكل صحيح في ملف CONTRIBUTING.md

هل تخطط لدعم الواردات الدورية؟

إذا كان لدي ملف اختبار وهمي يستورد واحدًا فقط من ملفين يستورد كل منهما الآخر ، فسأحصل على RangeError: Maximum call stack size exceeded . إذا قمت بإزالة أحد الواردات ، فإن الاختبار يجتاز. إعادة إنتاج هذه المشكلة .

مهلا! لقد قمت بإعداد هذا في مشروع عقدة فارغة وعمل جيدًا حقًا ، ولكن في إعداد الإنتاج لدينا ، أحصل على رسالة الخطأ التالية عندما أحاول تشغيل الاختبارات:

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

لقد رأيت شخصًا آخر يواجه مشكلة ما في رد سابق (بواسطة cyberwombat ) ، لكن الحزمة التي وجدوها هي الجاني ليست موجودة في package.json . كيف نستنتج الحزمة (أو الإعداد) التي تسبب المشكلة؟ لقد حاولت بشكل منهجي إزالة كل وضع مزاح ليس ضروريًا لإنجاح هذا العمل ، لكن لم أحقق نجاحًا.

تحديث : لقد تمكنت من إحراز تقدم من خلال إجراء تغيير طفيف في jest-runtime . لقد أوقفت مصحح الأخطاء عند السطر الذي يحاول الوصول إلى سياق VM وبينما الوظيفة غير موجودة بالفعل ، فإن this.context (الذي يجب أن تعيده) يفعل ذلك ، لذلك قمت بتغيير هذا السطر للوصول إلى الخاصية مباشرة. أعلم أن هذا ربما ليس مثاليًا ، لكن ربما SimenB @ قد يمنحك هذا فكرة عن الخطأ الذي يحدث؟

شكرا لكم مقدما على أي مساعدة

هل تخطط لدعم الواردات الدورية؟

قطعا! هل يمكنك فتح قضية منفصلة؟


zsombro يبدو أنك تشغل بعض الإصدارات القديمة من بيئة الاختبار. إذا قمت بتشغيل jest --show-config ، فما الذي يعرضه testEnvironment ؟

يبدو أنك تشغل بعض الإصدارات القديمة من بيئة الاختبار. إذا قمت بتشغيل jest --show-config ، فما الذي يعرضه testEnvironment ؟

SimenB تقول ما يلي:

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

لقد قمت بتعيينه على jest-environment-node بناءً على إرشاداتك

قبل أن أبدأ هذه العملية ، قمت بترقية الدعابة باستخدام yarn add jest@latest . هل يجب علي ترقية البيئة بشكل منفصل؟

تحديث: اتضح أنني اضطررت إلى ذلك. لقد حذفت node_modules و yarn.lock لإجراء تثبيت نظيف وما زال الأمر لا يعمل. ومع ذلك ، إذا قمت بإضافته يدويًا باستخدام yarn add -D jest-environment-node فيبدو أنه يعمل. هل هناك طريقة أفضل لإدارة هذا؟ لقد قمت بمشروع اختبار بسيط قبل القيام بذلك على قاعدة الشفرة الخاصة بنا ولم يكن علي القيام بذلك

yarn list jest-environemnt-node المحتمل أن يسرد npm list jest-environemnt-node ) عدة ، حسب تخميني

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

من المحتمل أن يكون الإصدار 26.2.0 هو ما قمت بتثبيته يدويًا (على الأقل استنادًا إلى package.json ، مما يعني أن jest-config قام بتثبيت إصدار يبدو أنه قديم؟

لديك شيء آخر يسحب في إصدار أقدم من jest-config (ربما react-scripts (جزء من create-react-app )؟). هذه القضية ليست المكان المناسب لمناقشتها ، مع ذلك

عدم القدرة على استخدام وحدات ES في globalSetup بدأ يؤلم.

نقطتان:

  • هل ينبغي ذكر ذلك كخانة اختيار في بداية هذه المشكلة (بحيث يتم تعقبها)؟
  • إذا كان هناك إصدار ألفا / بيتا يمكنني تجربته ، على استعداد للقيام بذلك

أنا:

  • تأكد من تشغيل أحدث إصدار Jest (26.4.0)
  • تمت إضافة عقدة jest-environment إلى مشروعي
  • تأكد من عدم تكراره من خلال فحص ملف القفل
  • تمت إضافة "testEnvironment": "jest-environment-node", في jest.config.json
  • تمت إضافة import { jest } from '@jest/globals'; أينما تم استخدام الدعابة
  • تم تشغيل إعداد أمر الاختبار --experimental-vm-modules عن طريق تشغيلهم بـ NODE_OPTIONS='--experimental-vm-modules' yarn jest

ويتعطل على الكود التالي:

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

مع الخطأ التالي (مختصر - لاحظ "الكائنات المسموح بها"!):

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.

لا يمكنني استخدام Babel ، لأنه يوزع بشكل غير صحيح الواردات التي قمت بتثبيتها للتشغيل على العقدة 14 بدون Babel:

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

والذي للأسف يتم تحليله بشكل غير صحيح بمقدار @babel/preset-env ، مما أدى إلى TypeError: Cannot destructure property 'map' of '_lodash.default' as it is undefined. .

هل يمكن لأي شخص مساعدتي في حل هذه المشكلة؟

تحرير: يبدو أنك _can_ تستخدم Jest + Babel على كود متوافق مع وحدات ES الأصلية باستخدام عمليات استيراد CommonJS من خلال القيام بهذا الإصلاح المثير للاشمئزاز:

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

من هنا،

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

يتم استهلاكه تمامًا بواسطة Node 14 ، والشفرة الناتجة عن تشغيل Jest + Babel ،

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

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

const {
  map
} = _lodash.default;

يعمل أيضا.

لقد نجحنا في تحويل جميع اختبارات المرح الخاصة بنا لاستخدام واستيراد كود ES6 الخاص بنا ، لكننا علقنا في بعض الحزم: وهي puppeteer و uuid

لا يعمل التطبيق إلا إذا قمنا باستيرادها إلى كائن (مثل import uuid from 'uuid' ) ، لكن الاختبارات لن تعمل بهذه الطريقة. ومع ذلك ، إذا استبدلنا هذا الاستيراد ببنية التفكيك (مثل import { v4 } from 'uuid' ، فعندئذٍ يكون العكس: يعمل الاختبار ، لكن التطبيق يطرح استثناءً.

في الأصل ، اتبعنا الدليل وأوقفنا كل عملية تحويل ، لكننا حاولنا أيضًا إنشاء مساحة عمل للغزل حيث قمنا بتثبيت بابل مع الحد الأدنى من تكوين العقدة ، لكن هذا لم يحل (أو يزيد) هذه المشكلة المحددة

ومع ذلك ، إذا استبدلنا هذا الاستيراد ببنية التفكيك (مثل الاستيراد {v4} من "uuid" ، فسيكون العكس هو الصحيح: يعمل الاختبار ، لكن التطبيق يطرح استثناءً.

يبدو أن تطبيقك مجمع إلى CommonJS ولا يستخدم وحدات في الممارسة. من ESM "الحقيقي" import uuid from 'uuid' لا يجب أن يعمل لأن uuid ليس لديه تصدير افتراضي ويكشف بناء ESM للعقدة .

مرحبًا SimenB ، هل تعتقد أن بعض الوثائق الأولية حول هذا ستكون فكرة جيدة؟

تضمين التغريدة كنت آمل أن أتمكن من قضاء المزيد من الوقت في هذا الأمر وتثبيته في Jest 27 ، لكنني أشك في أنني سأكون قادرًا على القيام بذلك. لكن كتابة صفحة مستند حول ما هو موجود الآن (وأنها تجريبية) تبدو فكرة جيدة

SimenB لا أعرف ما هو الوضع الحالي للمشكلة وما إذا كان يجب أن يعمل Jest بالفعل مع حالتي أم لا ، ولكن ربما يمكن أن يساعدك بطريقة ما.

أحاول تحميل مكتبة esm-only (امتدادها هو cjs ولكن النوع هو وحدة ويبدو أن العقدة لا بأس بها) ولكن Jest يفشل في تحميلها بشكل صحيح مع الخطأ:

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

هنا المشكلة التي فتحتها في الأصل https://github.com/codemirror/codemirror.next/issues/310. ونسخة لـ Jest + ESM الفاشلة مع العقدة 14.13.1 https://github.com/dubzzz/codemirror-next-repro-cra/tree/main/test-in-jest-esm

dubzzz لا يمكنك استخدام ESM في ملف cjs . العقدة فشلت كذلك

$ 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

عذرًا ، آسف جدًا ، لقد حاولت بسرعة كبيرة على جانب العقدة. أبلغ @ nicolo-ribaudo بالفعل مؤلف lib عن هذه المشكلة.
حقا شكرا جزيلا على إجابتك السريعة.

فتحت ملفًا عامًا لبعض المستندات (إلى حد كبير) هنا: # 10611. لم أكلف نفسي عناء تعداد الميزات / الأخطاء المفقودة لأنني أعتقد أنه سيكون من الصعب الحفاظ عليها متزامنة مع الواقع ، والنظر في مشكلات جيثب هو نهج أفضل لأنها (آمل ...) محدثة.

Pomax كإصدار جديد ، من فضلك 🙂

لقد فتحت للتو # 10620 الذي يضيف دعمًا لـ import() من CJS. طلبت عدة مرات مثل https://github.com/facebook/jest/issues/9430#issuecomment -626054595

مرحبا. من الصعب جدًا بالنسبة لي أن أتبنى بسرعة القصة الكاملة وراء ESM في العقدة / الدعابة ، لذلك ، على الأرجح ، سأطلب شيئًا واضحًا أو تمت الإجابة عليه بالفعل. هل أفهم بشكل صحيح أن الحالة التالية غير مدعومة حتى الآن؟ أو ، آمل ، أن أفعل شيئًا ليس بالطريقة الصحيحة؟ أختبر ذلك مثل import x from 'x' يعمل ، لكن التدمير import { sub } from 'x' لا يفعل ذلك.

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

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

أنت تنتظر # 9771. قبل ذلك ، لا يعرف Jest أنه من الآمن تحميل uuid كـ ESM (أو بالأحرى ، أي ملف يتم تحميله عند النقطة التي يعرف أنه ESM)

هل سيتبع ذلك اصطلاح Node الخاص ، حيث لا يمكن تحميل CJS إلا كمساحة اسم ، أم أن هذا "يحسن" ذلك من خلال السماح ببناء الجملة الذي لا يعمل بالفعل في Node نفسها؟ (على سبيل المثال ، لا تسمح Node بـ import { readdirSync } from "fs-extra" لأنها حزمة CJS ، لكنها تسمح بـ import fs from "fs-extra"; والتي يمكن فك حزمها باستخدام const { readdirSync } = fs ).

(على سبيل المثال ، لا تسمح Node بالاستيراد {spawn} من "child_process" لأنها حزمة CJS ، ولكنها تسمح باستيراد child_process من "child_process" ؛ والتي يمكن بعد ذلك فك حزمها باستخدام const {spawn} = child_process؛).

هذا مثال مؤسف لأن العقدة تعتبر "child_process" وحدة "مضمنة" (وليست CJS) ، لذا فإن عمليات التصدير المسماة تعمل. تستخدم أحدث nodejs أيضًا دليلًا لجعل العديد من عمليات التصدير المسماة تعمل مع وحدات CJS. قد يكون هذا هو الجزء الأصعب لمحاكاته.

تم تحديث المثال لاستخدام fs-extra بدلاً من ذلك. ولكن إذا كان التصدير المسمى موجودًا في خارطة طريق Node للهبوط إما هذا أو الرئيسي التالي ، فإن Jest استباق ذلك أمر منطقي.

يجب أن يتم تنفيذ ذلك بالفعل - تكشف الوحدات النمطية الأساسية للعقدة عن الصادرات المسماة ، أما CJS "العادية" فلا تفعل ذلك.

تستخدم أحدث nodejs أيضًا دليلًا لجعل العديد من عمليات التصدير المسماة تعمل مع وحدات CJS. قد يكون هذا هو الجزء الأصعب لمحاكاته.

هل لديك رابط للعلاقات العامة بتنفيذها؟ يجب أن نحاول محاكاته على الأقل 🙂

العلاقات العامة هنا: https://github.com/nodejs/node/pull/35249

تم نشر الاستدلال وراء ذلك كـ cjs-module-lexer (https://github.com/guybedford/cjs-module-lexer) لكن guybedford قد يعرف المزيد عن أي انحرافات محتملة.

ألقيت نظرة على هذا ويبدو أن fs-extra يستخدم نمط تصدير مثل:

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

هذه ليست حالة تحليل إعادة تصدير نكتشفها حاليًا ، ولكن قد يكون من الممكن إضافتها إلى cjs-module-lexer إذا كانت هذه حالة مفيدة للتعامل مع اكتشاف عمليات التصدير المسماة.

شكرا jkrems و guybedford! لقد فتحت العلاقات العامة الآن باستخدام تلك الوحدة: # 10673

يتم الآن تنفيذ الدعم الإضافي الدقيق fs الموضح في https://github.com/facebook/jest/issues/9430#issuecomment -713204282 في [email protected] ، تتبع المنبع على https: // github. كوم / nodejs / node / pull / 35745.

_Update: باختبار هذا البناء ، فإنه يكتشف بشكل صحيح جميع وظائف fs-extra ، ولكن للأسف لا يكتشف وظائف Node.js الأصلية لأنها غير قابلة للتحليل بشكل ثابت بسبب ملؤها بواسطة حلقة for._

الفذ: دعم الصادرات المسماة من CJS باسم واردات ESM المسماة # 10673

اعتقدت أن ESM الأصلي يدعم فقط استيراد exports لوحدة CommonJS للوحدة default ؟

trusktr ليس بعد الآن: https://github.com/nodejs/node/pull/35249

مرحبا. من الصعب جدًا بالنسبة لي أن أتبنى بسرعة القصة الكاملة وراء ESM في العقدة / الدعابة ، لذلك ، على الأرجح ، سأطلب شيئًا واضحًا أو تمت الإجابة عليه بالفعل. هل أفهم بشكل صحيح أن الحالة التالية غير مدعومة حتى الآن؟ أو ، آمل ، أن أفعل شيئًا ليس بالطريقة الصحيحة؟ أختبر ذلك مثل import x from 'x' يعمل ، لكن التدمير import { sub } from 'x' لا يفعل ذلك.

...
استيراد {v4} من "uuid" ؛

لا تدعم وحدات ESM النمطية إتلاف الواردات ، على الرغم من أن بناء الجملة يبدو كذلك. لكي يعمل هذا ، يلزم "تصدير v4". لن يتطابق "التصدير الافتراضي".

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

يوفرsdwlig uuid تصدير مسماة ولا تحتوي على عمليات تصدير افتراضية. يجب أن يعمل ولكن تحميل esm من الحزم التي تحتوي على حقل "الصادرات" لم يتم دعمه بواسطة jest حتى الآن. يتم تحميل Commonjs بدلاً من ذلك وهو متاح فقط من خلال التصدير الافتراضي.
https://github.com/uuidjs/uuid/blob/master/src/index.js

هل يمكننا إضافة دعم المرجع الذاتي للحزمة (# 10883) لهذا؟

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات