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

Running unit tests with Karma - Error: EACCES: permission denied, mkdir '/_karma_webpack_' #435

Closed
davetron5000 opened this Issue May 27, 2017 · 15 comments

Comments

Projects
None yet
5 participants
@davetron5000
Copy link
Contributor

davetron5000 commented May 27, 2017

Posting here to see if others are having this issue and if it's one with the configuration Webpacker creates.

I had this working with many previous versions of the wonderful JavaScript toolchain, but now with the latest of everything, I get

Error: EACCES: permission denied, mkdir '/_karma_webpack_'

The source for karma-webpack seems to be totally wrong, but it's been like that for 10+ months, so I think there's a subtly I'm not aware of.

I'm using the latest Webpacker-generated configuration files, with zero changes.

My devDependencies are:

  "devDependencies": {
    "jasmine": "^2.6.0",
    "jasmine-core": "^2.6.2",
    "karma": "^1.7.0",
    "karma-jasmine": "^1.1.0",
    "karma-phantomjs-launcher": "^1.0.4",
    "karma-webpack": "^2.0.3",
    "testdouble": "^2.1.2"
  }

My karma.conf.js looks like:

module.exports = function(config) {
  config.set({
    frameworks: ['jasmine'],
    files: [
      '**/*.spec.js'
    ],
    preprocessors: {
      '**/*.spec.js': [ 'webpack' ]
    },
    webpack: require('../../config/webpack/test.js'),
    browsers: ['PhantomJS'] })
}

If I sudo mkdir /_karma_webpack_ && sudo chmod 777 /_karma_webpack everything works. This is not a great solution, but i have no idea how to change it or why it's now broken.

Anyone have any ideas?

@davetron5000

This comment has been minimized.

Copy link
Contributor

davetron5000 commented May 27, 2017

To say more, here is the configuration that is produced after karma-webpack has munged it. Again, my assumption is that karma-webpack is correct, because this part of it hasn't changed in a very long time:

{ entry:
   { application: '/Users/davec/Projects/rails-book/shine/app/javascript/packs/application.js',
     customers: '/Users/davec/Projects/rails-book/shine/app/javascript/packs/customers.js',
     hello_angular: '/Users/davec/Projects/rails-book/shine/app/javascript/packs/hello_angular.js' },
  output:
   { filename: '[name]',
     path: '/_karma_webpack_/',
     publicPath: '/_karma_webpack_/',
     chunkFilename: '[id].bundle.js' },
  module: { rules: [ [Object], [Object], [Object], [Object], [Object], [Object] ] },
  plugins:
   [ EnvironmentPlugin { keys: [Object], defaultValues: [Object] },
     ExtractTextPlugin { filename: '[name].css', id: 1, options: {} },
     ManifestPlugin { opts: [Object] } ],
  resolve:
   { extensions:
      [ '.coffee',
        '.erb',
        '.js',
        '.jsx',
        '.ts',
        '.vue',
        '.sass',
        '.scss',
        '.css',
        '.png',
        '.svg',
        '.gif',
        '.jpeg',
        '.jpg' ],
     modules:
      [ '/Users/davec/Projects/rails-book/shine/app/javascript',
        'node_modules' ] },
  resolveLoader: { modules: [ 'node_modules' ] },
  watch: true }
@renchap

This comment has been minimized.

Copy link
Contributor

renchap commented May 27, 2017

output.path must be an absolute path to. In your case, it needs to be something like /Users/davec/Projects/rails-book/shine/public/_karma_webpack_/: https://webpack.js.org/configuration/output/#output-path

@renchap

This comment has been minimized.

Copy link
Contributor

renchap commented May 27, 2017

Can you look at the Webpack config generated in another project where this works fine? Are those other projects also using Webpack 2?

@davetron5000

This comment has been minimized.

Copy link
Contributor

davetron5000 commented May 27, 2017

Important note if it wasn't obvious - karma-webpack overwrites the webpack configuration when you run karam (see the linked code in my first comment), so I have literally no option to change the value for output.path. What I'm wondering is what else contributes to the actual use of that path.

To answer you questions, though:

The previous version I had working was with Rails 5.1.0.RC1, and the configuration Webpacker generated as of that release. This still works. The configuration file after karma-webpack munges it still has the absolute paths:

{ entry:
   { 'angular-test': '/Users/davec/Projects/rails-book/dcbang2/Book/code/testing/setup-karma/shine/app/javascript/packs/angular-test.js',
     application: '/Users/davec/Projects/rails-book/dcbang2/Book/code/testing/setup-karma/shine/app/javascript/packs/application.js',
     customers: '/Users/davec/Projects/rails-book/dcbang2/Book/code/testing/setup-karma/shine/app/javascript/packs/customers.js' },
  output:
   { filename: '[name]',
     path: '/_karma_webpack_/',
     pathinfo: true,
     publicPath: '/_karma_webpack_/',
     chunkFilename: '[id].bundle.js' },
  module: { rules: [ [Object], [Object], [Object], [Object], [Object] ] },
  plugins:
   [ EnvironmentPlugin { keys: [Object], defaultValues: {} },
     LoaderOptionsPlugin { options: [Object] } ],
  resolve:
   { extensions: [ '.js', '.coffee' ],
     modules:
      [ '/Users/davec/Projects/rails-book/dcbang2/Book/code/testing/setup-karma/shine/app/javascript',
        '/Users/davec/Projects/rails-book/dcbang2/Book/code/testing/setup-karma/shine/node_modules' ] },
  resolveLoader: { modules: [ '/Users/davec/Projects/rails-book/dcbang2/Book/code/testing/setup-karma/shine/node_modules' ] },
  devtool: 'sourcemap',
  stats: { errorDetails: true },
  watch: true }

I will keep iterating on moving this working config to the latest versions and see what breaks.

@renchap

This comment has been minimized.

Copy link
Contributor

renchap commented May 27, 2017

It is weird that it worked, because Webpack's documentation (cf the link above) highlights that output.path must be an absolute path…

@davetron5000

This comment has been minimized.

Copy link
Contributor

davetron5000 commented May 27, 2017

It is an absolute path, it's just one that makes no sense (in the root dir). All I can figure is that something in my old configuration was not ever attempting to write to that path, so it's oddness was never noticed. Still investigating…

@renchap

This comment has been minimized.

Copy link
Contributor

renchap commented May 27, 2017

Yes, it is treated as an absolute path, but I guess the intent (to be consistent with output.publicPath) is for it to be relative to the root directory karma-webpack uses. Either nothing was written to it before as you suggest, or something / Webpack changed it behind the scene to prepend an absolute path and make it point to the correct directory.

@davetron5000

This comment has been minimized.

Copy link
Contributor

davetron5000 commented May 27, 2017

OK, I think I have the culprit. The ManifestPlugin is what is attempting to write to this path. If I remove that, everything works, and in older versions of webpacker, this plugin was not configured.

It seems to be the writeToFileEmit: true. If I set this to false, everything works.

Since Webpacker doesn't seem to do much in the way of customization in the test environment, I may create a PR to address this, or at least make it configurable per environment.

This is also just testing a tautological spec, so not really even testing the code webpack is managing. I'll report back here when I've done that and either make a PR or close this.

Thanks for the engagement - just typing out what was going on helped me figure this out!

@davetron5000

This comment has been minimized.

Copy link
Contributor

davetron5000 commented May 27, 2017

Oh, and to be specific about what I did:

--- a/config/webpack/shared.js
+++ b/config/webpack/shared.js
@@ -40,8 +40,8 @@ module.exports = {
     new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
     new ManifestPlugin({
       publicPath: output.publicPath,
-      writeToFileEmit: true
-    })
+      writeToFileEmit: env.NODE_ENV !== 'test'
+     })
   ],

(edited, based on @renchap 's comment)

@renchap

This comment has been minimized.

Copy link
Contributor

renchap commented May 27, 2017

Nice find!

Be careful, this will break if you use webpack-dev-server (the only case when writeFoFileEmit is used). You might want to use env.NODE_ENV !== 'test'.

@gauravtiwari

This comment has been minimized.

Copy link
Collaborator

gauravtiwari commented May 31, 2017

@davetron5000 Why using karma-webpack when webpacker already configured using webpacker? Pardon me, I haven't used Karma before so don't know much :)

Can you not just use Karma like Jest - https://karma-runner.github.io/1.0/config/configuration-file.html?

const { join, resolve } = require('path')
const { env } = require('process')
const { safeLoad } = require('js-yaml')
const { readFileSync } = require('fs')

const configPath = resolve('config', 'webpacker.yml')
const settings = safeLoad(readFileSync(configPath), 'utf8')[env.NODE_ENV]

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [join(settings.source_path, settings.source_entry_path)],
    exclude: [],
    preprocessors: {},
    reporters: ['dots'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['PhantomJS'],
    singleRun: true
  })
}
@davetron5000

This comment has been minimized.

Copy link
Contributor

davetron5000 commented May 31, 2017

My understanding is the only way to use karma on files that have been run through webpack is to use the karma-webpack preprocessor. My understanding is that it tells karma "use webpack on the files and then make them available to tests".

I'm not sure what your alternative is - where does the JS you posted go and what is it intended to do? Could be ignorance - I only know what I've been able to get to function and what I posted above achieves that after many hours of frustration :)

@mcmire

This comment has been minimized.

Copy link

mcmire commented Jun 22, 2017

Thanks @davetron5000! I also ran into this issue and your fix worked for me. This should definitely be incorporated into Webpacker.

@jnfeinstein

This comment has been minimized.

Copy link

jnfeinstein commented Sep 12, 2017

Just ran into this. It is indeed the ManifestPlugin. My solution was to create a separate webpack config for karma like so:

const { module: m, resolve, resolveLoader } = require('./config/webpack/shared');

module.exports = {
  module: m,
  resolve,
  resolveLoader,
  devtool: 'inline-source-map'
};

This leaves you with the portions of the configuration that are used for processing files, and nothing more.

@gauravtiwari

This comment has been minimized.

Copy link
Collaborator

gauravtiwari commented Oct 1, 2017

Docs added #882

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