Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support nodejs experimental-modules #150

Closed
jehon opened this issue Feb 13, 2019 · 13 comments
Closed

Support nodejs experimental-modules #150

jehon opened this issue Feb 13, 2019 · 13 comments

Comments

@jehon
Copy link

jehon commented Feb 13, 2019

Expected Behavior

We should be able to use the "ecmascript" experimental modules of nodejs (https://nodejs.org/dist/latest-v11.x/docs/api/esm.html),

Current Behavior

we receive an error:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /mnt/c/Users/jhn/src/kiosk/tests/server/basic-test.mjs
at Object.Module._extensions..mjs (internal/modules/cjs/loader.js:724:11)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
> at /mnt/c/Users/jhn/src/kiosk/node_modules/jasmine/lib/jasmine.js:89:5
at Array.forEach ()
at Jasmine.loadSpecs (/mnt/c/Users/jhn/src/kiosk/node_modules/jasmine/lib/jasmine.js:88:18)
at Jasmine.execute (/mnt/c/Users/jhn/src/kiosk/node_modules/jasmine/lib/jasmine.js:257:8)

Possible Solution

Jasmine should use "import" instead of "require" when loading esm modules. But that is not that easy, since "import" is asynchronous, while require is synchronous. And we need to know when do we have a "esm" module.

Suite that reproduces the behavior (for bugs)

  • Create a .jsm file (can be any test, even a simple one)
    launch nearly as usual:
node --experimental-modules node_modules/.bin/jasmine

Context

This is blocking to use jasmine in this new (experimental) context.

Your Environment

  • Version used: 3.3.1
  • Environment name and version (e.g. Chrome 39, node.js 5.4): nodejs v10.15.1
  • Operating System and version (desktop or mobile): ubuntu
  • Link to your project:
@jehon
Copy link
Author

jehon commented Feb 14, 2019

As a workaround:

Create a file called "jasmine-run.mjs":

import glob from 'glob';
import Jasmine from 'jasmine';

const jasmine = new Jasmine();
jasmine.loadConfigFile('tests/jasmine.json');

// Load your mjs specs
glob('**/*-test.mjs', function (er, files) {
    Promise.all(
        files
            // Use relative paths
            .map(f => f.replace('tests/specs/', './'))
            .map(f => import(f)
                .catch(e => {
                    console.error('** Error loading ' + f + ': ');
                    console.error(e);
                    process.exit(1);
                }))
    )
        .then(() => jasmine.execute());
});

The script would be called like:

node --experimental-modules jasmine-run.mjs

That is not sufficient...

In jasmine.js (jasmine-core/lib/jasmine.js): #6428

You need to extends the StackTrace handling function like this:

	function StackTrace(error) {
		var lines = [ 'unknown result!' ];
                /* esm stackstraces are a bit weird this times */
		if (Array.isArray(error.stack)) {
			lines = error.stack.map(function(site) {
				return site.toString();
			});
		} else {
                /* normal handling */
			lines = error.stack
				.split('\n')
				.filter(function(line) { return line !== ''; });
		}

On stackoverflow: https://stackoverflow.com/questions/47832603/running-tests-mjs-esm-on-node-using-jasmine-or-any-other-alternative/54691621#54691621

@slackersoft
Copy link
Member

That sounds like a nice thing to be able to support. I would be happy to review a Pull Request here to add some the same kind of --experimental-modules flag to Jasmine-NPM to switch the import/require mechanism that is used and a Pull Request in Jasmine-Core to handle stack traces as you've outlined.

Thanks for using Jasmine!

@jehon
Copy link
Author

jehon commented Mar 8, 2019

The stacktrace management is done here: https://github.com/jehon/jasmine/commit/d985a24acc4c5dae68c1301a4368f0fac08bb47c

Have a nice day

@jehon
Copy link
Author

jehon commented Mar 11, 2019

Hello @slackersoft,
Would you review the first pull request here: jasmine/jasmine#1662 ?

After it is ok, I will have a look to a clean way to do this part...

Have a nice day
Jehon

@Skriptach
Copy link

So Node 12 is realesed now. Congratulations! =)

Any updates on topic?

@jehon
Copy link
Author

jehon commented Jun 21, 2019

Hello,

The work to do in the other card is to huge for me, and require to understand the full testing system.

I didn't have the time to work on this now, and in short term, I will not be able to give time.

So, if someone want to take over, please feel free to do so.

@nweldev
Copy link

nweldev commented Aug 16, 2019

This issue is still relevant. I reproduced it with node v12.8.0, but I won't be able to work on it for now.
NODE_OPTIONS="--experimental-modules" npm run jasmine on https://github.com/noelmace/devcards/tree/repro-jasmine-npm-150

workaround

It looks like this issue only affects the CLI ( jasmine command).
You can use jasmine framework with spec and source files with ESM using Karma, karma-jasmine and @open-wc/karma-esm.

Here is my configuration file:

/*
 * derivative of @open-wc/testing-karma create-default-config.js (licensed under MIT)
 * https://github.com/open-wc/open-wc/blob/f21d435/packages/testing-karma/src/create-default-config.js
 */

function getCompatibility() {
  if (process.argv.find(arg => arg.includes('--legacy'))) {
    /* eslint-disable-next-line no-console */
    console.warn(`testing-karma --legacy flag has been renamed to --compatibility`);
    return 'all';
  }

  const indexOf = process.argv.indexOf('--compatibility');
  return indexOf === -1 ? 'none' : process.argv[indexOf + 1];
}

const compatibility = getCompatibility();
const coverage = process.argv.find(arg => arg.includes('--coverage'));

module.exports = config => {
  config.set({
    browsers: ['ChromeHeadlessNoSandbox'],

    customLaunchers: {
      ChromeHeadlessNoSandbox: {
        base: 'ChromeHeadless',
        flags: ['--no-sandbox', '--disable-setuid-sandbox']
      }
    },

    plugins: [
      // resolve plugins relative to this config so that they don't always need to exist
      // at the top level
      require.resolve('@open-wc/karma-esm'),
      require.resolve('karma-source-map-support'),
      require.resolve('karma-coverage-istanbul-reporter'),
      require.resolve('karma-chrome-launcher'),
      require.resolve('karma-jasmine'),
      require.resolve('karma-spec-reporter'),

      // fallback: resolve any karma- plugins
      'karma-*'
    ],

    frameworks: ['esm', 'source-map-support', 'jasmine'],

    esm: {
      coverage,
      compatibility,
      babelModernExclude: ['**/node_modules/jasmine/**/*', '**/node_modules/karma-jasmine/**/*'],
      polyfills: {
        webcomponents: true,
        fetch: true
      }
    },

    reporters: coverage ? ['spec', 'coverage-istanbul'] : ['spec'],

    restartOnFileChange: true,

    colors: true,

    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // ## code coverage config
    coverageIstanbulReporter: {
      reports: ['html', 'lcovonly', 'text-summary'],
      dir: 'coverage',
      combineBrowserReports: true,
      skipFilesWithNoCoverage: false,
      thresholds: {
        global: {
          statements: 80,
          branches: 80,
          functions: 80,
          lines: 80
        }
      }
    },

    files: [
      // runs all files ending with .test in the src folder,
      // can be overwritten by passing a --grep flag. examples:
      //
      // npm run test -- --grep test/foo/bar.test.js
      // npm run test -- --grep test/bar/*
      { pattern: config.grep ? config.grep : 'test/jasmine/**/*.test.js', type: 'module' }
    ],
    esm: {
      nodeResolve: true
    },

    autoWatch: false,
    singleRun: true,
    concurrency: Infinity
  });
};

See https://github.com/noelmace/devcards/blob/master/karma.jasmine.conf.js

Also, see open-wc/open-wc#729 for some context.

@anthumchris
Copy link

Not sure if this helps anyone, I've been using the esm module to run tests against ES Modules:

$ yarn global install jasmine esm
$ jasmine --require=esm src/*.spec.js

@GrosSacASac
Copy link

+1

@sgravrock
Copy link
Member

I've been working on this, and I think I have something that's just about ready to go. But I'm having trouble finding real-world examples to test with. It would be a great help if anyone can point me at something that's publicly available (preferably an npm package), can only be imported as an ES module, and works in Node without being transpiled or bundled.

@sgravrock
Copy link
Member

ES module support was released in version 3.6.2 of the Jasmine npm package.

@JannesMeyer
Copy link

JannesMeyer commented Oct 28, 2020

Sounds amazing!

How do you use the new ES module support? In the release notes it mentions that the files need to have the *.mjs extension. Is there any way to use it with *.js files and "type": "module" in package.json?

Edit: I created a separate issue for it: #170 I didn't notice that this one was closed already.

@tomsoderlund
Copy link

@JannesMeyer Adding "type": "module" in package.json works for me, but

node --experimental-modules node_modules/.bin/jasmine

does not.

My problem is that I need "type": "module" for running Jasmine tests, but can’t have it enabled to run the Next.js web server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants