theintern / intern

A next-generation code testing stack for JavaScript.
https://theintern.io/
Other
4.36k stars 311 forks source link

Feature Request: Write tests in ES6 #626

Closed stsvilik closed 4 years ago

stsvilik commented 8 years ago

I couldn't find any loader available that would permit writing actual tests in ES6. Same apples to testing code which is written in ES6. I managed to write tests that run against Babel transpiled output and all is well, but it requires additional step before anything could be tested.

andyearnshaw commented 8 years ago

I've been experimenting along these lines over the past week or so and here's my take on things so far:

I think the best solution would be to implement #615 and be as agnostic as possible for module loading. That way, people could write their tests however they like. A short-term fix might be to write a simple wrapper for SystemJS that works with Intern by implementing the AMD APIs.

dylans commented 8 years ago

The short answer is, if it was super easy to get things working today with ES6 modules, it would already be done as we would prefer that as well. Our team at SitePen typically authors tests in TypeScript and then just transpiles the tests to AMD modules and use remap-istanbul to instrument our code coverage back to our original source, because we cannot really rely on alpha code for production releases.

We have a release coming soon that supports writing tests with ES6 features (there's an open PR currently under review/iteration at https://github.com/theintern/intern/pull/590 ).

The bigger challenge is native support for ESM (ES6 modules) or SystemJS. It's a very non-trivial switch, because AMD module loaders provide a lot of power and flexibility to Intern. We've done some initial work on trying to get things working with SystemJS, but it's not trivial.

We also have a branch for rewriting Intern with TypeScript (targeted for Intern 4) which could make this a bit easier to achieve as well. Again though, to reliably run the tests in most browsers today, some level of transpilation is needed, and you will of course need to limit the ES6 code in your tests to a feature set that is either easily transpiled, or else you need the relevant polyfills available (e.g. don't use features that cannot be polyfilled and are not natively supported by all target browsers).

We're definitely very much interested in this, it's just a really messy situation right now where it's far easier to author ES6 modules than it is to test and use them in every possible scenario.

andyearnshaw commented 8 years ago

@dylans thanks for the update, it's good to know some effort has been made towards this. I've been playing around with writing a wrapper for SystemJS today and it's anything but trivial. I've jumped through several hoops writing the wrapper script and configuring the loader, but it doesn't support AMD loader plugins and SystemJS plugins are very different, it seems, so it breaks as soon as it tries to do anything with dojo/has!....

Do you have a timeframe for this next release? I'm just wondering if I should abandon my current efforts and wait, or if I should persevere.

stsvilik commented 8 years ago

Well, I did some experimenting as well and managed to write a loader which transpiles ES6 (using babel-core) on the fly. That almost worked, by almost I mean that it could test files that do not import other dependencies. The stumbling block for me was exports object which transpiled code expects. If I set exports to an empty object it doesn't throw an error, but at the same it doesn't know how to resolve sub-dependencies.

dylans commented 8 years ago

@andyearnshaw well, we certainly have an interest in it, so we could perhaps collaborate on a solution together?

stsvilik commented 8 years ago

Here is my loader (warning - very immature) in case you want to create a temporary solution:

define(function(require) {
  var global = (function() {
    return this;
  })();

  var nodeRequire = global.require && global.require.nodeRequire;

  if (!nodeRequire) {
    throw new Error('Cannot find the Node.js require');
  }

  var module = nodeRequire('module');
  var babel = nodeRequire("babel-core");
  var options = {
    sourceMaps: true,
    plugins: [
      "transform-es2015-arrow-functions",
      "transform-es2015-block-scoped-functions",
      "transform-es2015-block-scoping",
      "transform-es2015-classes",
      "transform-es2015-destructuring",
      "transform-es2015-duplicate-keys",
      "transform-es2015-for-of",
      "transform-es2015-function-name",
      "transform-es2015-literals",
      "transform-es2015-object-super",
      "transform-es2015-parameters",
      "transform-es2015-shorthand-properties",
      "transform-es2015-spread",
      "transform-es2015-sticky-regex",
      "transform-es2015-template-literals",
      "transform-es2015-typeof-symbol",
      "transform-es2015-modules-commonjs",
      "check-es2015-constants"
    ]
  };

  return {
    load: function(resourceId, require, load) {
      babel.transformFile(resourceId, options, function(err, result) {
        if (err) {
          throw err;
        }

        var code = result.code;
        var compiled = new Function("exports", code)({});
        load(compiled);
      });
    }
  };
});
andyearnshaw commented 8 years ago

@stsvilik unfortunately, babel-core isn't appropriate as the node require isn't available in browsers. babel-standalone works, however.

@dylans a collaboration sounds great. I think I may have hit a dead end with dojo/has: after working my way through the errors, it appears that the module's main function is never called by SystemJS. It does seem to work if I manually require the module via the console, though. I'll keep investigating.

stsvilik commented 8 years ago

@andyearnshaw I'll try to use babel-standalone. What else is not available in the browser is the use of intern dojo node loader. I get the same error you described.

kitsonk commented 8 years ago

@andyearnshaw we could expose additional methods if SystemJS doesn't handle AMD Plugin Specification. We also use dojo/node and dojo/text as a loader plugins with Intern IIRC, but I think we could address those. I am just not 100% sure what SystemJS requires as a plugin API.

andyearnshaw commented 8 years ago

@kitsonk they have a similar plugin architecture that return hooks to different stages of module loading. AMD has normalize and load, SystemJS has finer-grained control with locate, fetch, translate and instantiate. These hooks, along with normalize, can be applied at the loader level to apply to all modules, and this is the approach I was investigating yesterday.

I'm not fully sure if SystemJS does not support AMD plugins, as the problems I've encountered don't seem to produce any errors that I would expect to encounter from a plugin being loaded as a module. In fact, once I set the undocumented pluginFirst configuration option with my WIP wrapper, there are no errors at all and it seems like it's more likely a bug in the loader that's preventing me from progressing. Unfortunately, I haven't had time to drill down into the source code to isolate it yet.

There's already a text loader plugin for SystemJS, dojo/node and dojo/has probably wouldn't be too difficult to replicate if I can get that far.

kitsonk commented 8 years ago

@andyearnshaw thanks and ok, will look at incorporating that into the API... I will read up on the SystemJS plugin API as well, as I suspect it will be something folks will want in general.

andyearnshaw commented 8 years ago

https://github.com/andyearnshaw/intern-systemjs-loader

I made a few breakthroughs today and now I've got SystemJS working as Intern's loader for browser environments, as well as loading babel-transpiled source files. The next logical step is to get the runner environment working, which shouldn't be too difficult.

Hopefully, this will give some insight on how to add support for SystemJS in a future version of Intern, as well as provide an interim solution for people who want to use SystemJS with Intern 3. Please test it out and give feedback.

andyearnshaw commented 8 years ago

OK, got intern-client working now, not fully tested all the different reporters and stuff, though.

brianmhunt commented 8 years ago

It would be quite good if rollup.js and Bublé were supported as well.

jason0x43 commented 4 years ago

Intern now handles TS files by default via ts-node. This support could potentially be extended to support babel as well (or arbitrary transpilers).

jason0x43 commented 4 years ago

Closing this as the built in TS support can also be used for ES6 (set "allowJs": true in the TS config and set "node": { "tsconfig": "tsconfig.json" } in the intern config).

Separate issues can be opened to add support for other processors.