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

Babel plugins not loading when overridden in package.json AVA section #674

Closed
dcousineau opened this issue Mar 22, 2016 · 16 comments
Closed
Labels
bug current functionality does not work as desired

Comments

@dcousineau
Copy link
Contributor

Description

The documentation discusses overriding Babel configuration in the AVA section. However it appears at least the "plugins" if not the entire configuration is ignored in favor of .babelrc or the defaults.

Specifically: We need babel-plugin-rewire for our tests so we setup the AVA section of our package.json to look like:

{
  //...
  "ava": {
    "files": [
      "./tests/client/**/*.test.js",
      "./tests/server/**/*.test.js"
    ],
    "source": [
      "./src/client/scripts/**/*.{js,jsx}",
      "!./src/client/scripts/*Entry.js",
      "./src/server/**/*.js"
    ],
    "failFast": true,
    "tap": false,
    "require": [
      "babel-register",
      "babel-polyfill"
    ],
    "babel": {
      "presets": ["es2015", "react", "stage-0"],
      "plugins": ["rewire"]
    }
  },
  //...
}

With our .babelrc looking like:

{
  "presets": ["es2015", "react", "stage-0"]
}

However the tests would fail saying TypeError: Cannot read property 'Rewire' of undefined which indicates the plugin isn't running.

When I update the .babelrc file to include the "plugins": ["rewire"] it works.

Dropping console.logs in the rewire plugin inside of node_modules confirms the plugin doesn't even attempt to load.

I dropped some console logs into caching-precompiler.js in the _createTransform method and it IS getting the configuration I expect from package.json so the failure may be on caching-transform's part.

Environment

Node.js v5.9.0
darwin 15.4.0
AVA 0.13.0

@sindresorhus sindresorhus added the bug current functionality does not work as desired label Mar 22, 2016
@dcousineau
Copy link
Contributor Author

Additional notes

So after I submit this issue I set "bablerc": false in the override because I think I'm an idiot and remove rewire from the .babelrc file and the tests work, but I get a weird behavior:

./node_modules/.bin/ava --verbose

Initializing CachingPrecompiler with: { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins: [ 'rewire' ] }
_createTransform with: { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins: [ 'rewire' ] }
++ About to actually execute transform...
:: buildOptions()
Overriding Babel Config { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins: [ 'rewire' ] }
Final Options { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins:
   [ 'rewire',
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] } ],
  inputSourceMap: null,
  filename: '/Users/dcousineau/Projects/grovo/frontend/tests/client/components/primitives-utilities.test.js',
  sourceMaps: true,
  ast: false }
Rewire is loaded and working...
++ Finished transform
++ About to actually execute transform...
:: buildOptions()
Overriding Babel Config { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins:
   [ 'rewire',
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] } ] }
Final Options { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins:
   [ 'rewire',
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] } ],
  inputSourceMap: null,
  filename: '/Users/dcousineau/Projects/grovo/frontend/tests/client/components/progress-meter.test.js',
  sourceMaps: true,
  ast: false }
++ Finished transform
++ About to actually execute transform...
:: buildOptions()
Overriding Babel Config { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins:
   [ 'rewire',
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] } ] }
Final Options { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins:
   [ 'rewire',
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] } ],
  inputSourceMap: null,
  filename: '/Users/dcousineau/Projects/grovo/frontend/tests/client/config/config.test.js',
  sourceMaps: true,
  ast: false }
++ Finished transform
++ About to actually execute transform...
:: buildOptions()
Overriding Babel Config { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins:
   [ 'rewire',
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] } ] }
Final Options { babelrc: false,
  presets: [ 'es2015', 'react', 'stage-0' ],
  plugins:
   [ 'rewire',
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] },
     { visitor: [Object] },
     { __esModule: true, default: [Function], definitions: [Object] } ],
  inputSourceMap: null,
  filename: '/Users/dcousineau/Projects/grovo/frontend/tests/client/reducers/ground-control.test.js',
  sourceMaps: true,
  ast: false }
++ Finished transform

And it repeats slowly accumulating for each file AVA loads

Obviously the console logs are from some that I dropped trying to figure out how AVA is working internally, a copy of my file can be found in this gist

@dcousineau
Copy link
Contributor Author

I think the/a bug is here in the options.plugins.push. Possibly a .concat wouldn't leak between executions?

@dcousineau
Copy link
Contributor Author

That helps a lot actually, PR incoming

@jamestalmage
Copy link
Contributor

@dcousineau
The rewire plugin is generally used on sources, not tests. AVA automatically transpiles tests for you, but not sources. You still need to use .babelrc and --require babel-register to transpile sources.

There are other issues where we are discussing solutions:

@dcousineau
Copy link
Contributor Author

I'll dig in further thanks!

dcousineau added a commit to dcousineau/ava that referenced this issue Mar 22, 2016
Since `babelConfig` in the CachingPrecompiler.prototype._factory method was a JavaScript object coming from an external source, the .push was altering the array in place. objectAssign is shallow so the plugins were being mutated, ensuring that AVA's required plugins were continually apending for each file loaded and parsed.

Using .concat ensures the original plugins array is not mutated and thus doesn't collect plugins like a hoarder.
@dcousineau
Copy link
Contributor Author

@jamestalmage aha I get it now. I'm curious, do you think there'd be a way to provide configuration for the babel-register for the sources?

In the mean time I'm making my webpack config force its own babel config and will use babelrc to include the rewire plugin, in general I only want rewire plugin operating in a testing context but not when building the client.

@jamestalmage
Copy link
Contributor

in general I only want rewire plugin operating in a testing context but not when building the client.

Ah, I see your dilemma. We still need to implement an extends option for your babel config:

// package.json
{
  "ava": {
    "babel" : {
      "extends": "./babelrc",
      "plugins": ["rewire"]
    }
  }
}

It was discussed along with #573, but never got implemented.

@dcousineau
Copy link
Contributor Author

@jamestalmage if and only if I can specify the babel config for the source files as well (not just the test files) which I think is my real ask. (but an extends would be great as well)

Should I close this issue or rename it as a feature request? After doing some other things and sleeping on it I realize this is not a bug given what you've told me about the differences in transpiling test files and transpiling source files.

@jamestalmage
Copy link
Contributor

If you want the same config for both tests and sources, do babel: "inherit" in your config. The extends option is used for adding some extra transforms to test files that you don't want impacting sources.

With rewire you have an interesting case where you want to transpile your sources differently during testing than during production/publishing. I would recommend checking out the env option in .babelrc and setting an environment variable.

@novemberborn
Copy link
Member

The extends approach that @jamestalmage suggested should actually work. The env approach is another avenue you could try.

@dcousineau I'm closing this for now. Please feel free to reopen if you still have issues.

@kosmotaur
Copy link

I have the exact same use case, trying to use babel-plugin-rewire only in tests.
extends unfortunately failed, but the env way worked well. Not ideal, since I am trying for the project to be fully environment agnostic, but it unblocked me.

@jamestalmage
Copy link
Contributor

Your best bet is to have it default to installing rewire / everything you need for testing. That way your most common operation, running tests, needs no special environment variable set.

Use envs to turn off that stuff when you go to build.

@kosmotaur
Copy link

kosmotaur commented May 26, 2016

Good point, apply the env to the least common tasks to remove redundant bits.
One more downside is having to repeat sections of .babelrc, in my case, at the moment:

{
  "presets": [
    "es2015",
    "react",
    "stage-2"
  ],
  "plugins": [
    "transform-object-rest-spread"
  ],
  "env": {
    "test": {
      "plugins": [
        "transform-object-rest-spread",
        "rewire"
      ]
    }
  }
}

But that's just Babel now. Anyhow, things work, testing away! 😂

@djskinner
Copy link

I've found that I have to do the same as @kosmotaur:

{
  "presets": [
    ["env", {
        "loose": true,
        "modules": false,
        "useBuiltIns": true
    }],
    "stage-0",
    "react"
  ],
  "plugins": [],
  "env": {
      "test": {
        "presets": [
            ["env", {
                "loose": true,
                "modules": "commonjs",
                "useBuiltIns": true
            }],
            "stage-0",
            "react"
        ]
      }
  }
}

For my main build I want babel to ignore modules as to allow Webpack 2 tree-shaking but need babel to transpile them in a test context.

Not matter what I tried in pkg.ava.babel I couldn't get it to work. It seems like the original env preset configuration was still being used.

@novemberborn
Copy link
Member

@djskinner did you try specifying the transform-es2015-modules-commonjs plugin in pkg.ava.babel? I'm not sure if redefining presets with different options works the way you're expecting it to.

@djskinner
Copy link

Yes, you're right about the presets getting replace as I'd expected.

I ended up doing this:

// .babelrc
{
  "presets": [
    "./.babelrc.js"
  ]
}

// .babelrc.js
const env = process.env.BABEL_ENV || process.env.NODE_ENV || 'development'
const browserlist = ["last 2 versions"]

const getTargets = (env) => {
    if (env === 'node') return { "node": true };
    if (env === 'production') return { "browsers": browserlist, "uglify": true };
    return { "browsers": browserlist }
}

const targets = getTargets(env)

module.exports = {
    presets: [
        ["env", {
            targets,
            "loose": true,
            "modules": env === 'modules' ? 'commonjs' : false,
            "useBuiltIns": true
        }],
        "stage-0",
        "react"
    ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug current functionality does not work as desired
Projects
None yet
Development

No branches or pull requests

6 participants