thlorenz / proxyquireify

browserify >= v2 version of proxyquire. Mocks out browserify's require to allow stubbing out dependencies while testing.
MIT License
152 stars 24 forks source link

Problems with aliasify: "Error: Cannot find module ..." #53

Closed cape-dev closed 8 years ago

cape-dev commented 8 years ago

Hi guys.

I have a problem using proxyquireify alongside aliasify in my tests. I have checked if this problem comes from aliasify but I am pretty sure it doesn't.

I am replacing the paths with an regex and in my production code everything works fine. In the test were I require my src files (also replaced with an regex) it says that it cannot find the module although aliasify has correctly replaced the path. I checked that with some console.logs in aliasify prod code.

My setup: Karma + Jasmine + Browserify + Stringify + Babelify + Aliasify + Proxyquireify That is my karma conf: PS: I have tested many configurations of the browserify part of my karma conf. First I had just transforms and plugin instructions. Then I realized that the problem could be the interaction of proxyquireify and aliasify. Therefor I put them all in a configure block in order to determine a specific execution order.

'use strict';

var aliasify       = require('aliasify');
var aliasifyConfig = require('./aliasify.js');

var stringify = require('stringify');
var stringifyConfig = require('./stringify');

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '.',

    plugins: [
      'karma-browserify',
      'karma-jasmine',
      'karma-chrome-launcher'
    ],

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['browserify', 'jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'tests/spec/**/*.spec.js',
      'tests/spec/**/*Spec.js',
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'tests/spec/**/*.spec.js': ['browserify'],
      'tests/spec/**/*Spec.js': ['browserify'],
    },

    browserify: {
      debug: true,
      bundleDelay: 2500,
      configure: function(bundle) {
        bundle.once('prebundle', function() {
          bundle
            .transform(stringify(stringifyConfig.extensions), {global: true})
            .transform('babelify')
            .plugin('proxyquireify/plugin')
            .transform(aliasify, aliasifyConfig);
        });
      }
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    // reporters: ['progress', 'html'],
    reporters: ['progress'],

    // the default configuration
    htmlReporter: {
      outputDir: 'build/karma_html',
      templatePath: 'node_modules/karma-html-reporter/jasmine_template.html'
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

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

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,
    autoWatchBatchDelay: 2500,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false
  });
};
bendrucker commented 8 years ago

You're almost certainly going to need to put proxyquireify last so that all other transforms, especially those that change code around, run before it. Proxyquireify inserts a transform that causes Browserify to include the files you call proxyquireify with.

cape-dev commented 8 years ago

After long debugging now I do not think that proxyquireify is directly causing this problem. The core of the problem is that proxyquireify builds a wrapper around the 'require' calls and therefore aliasify is not capable of replacing the require paths. Aliasify is using browserify-tranform-tools in order to replace the require paths. The problem with browserify-transform-tools is that it fails on all modules which wrap node's 'require' because the function call to require something is not 'require' anymore. In the case of proxyquireify it is 'require_' and the transform-tools only act if node.callee.name is 'require'.

Hence this fix has to be made on browserify-transform-tools and aliasify in order to support path replacements with aliases for node's require'. I am about to implement this feature and make a PR to aliasify and the transform tools.

I hope @jwalton will look at this issue and confirm my assumptions.

bendrucker commented 8 years ago

Ah okay I see what aliasify does now. The two definitely will not be compatible.

jwalton commented 8 years ago

@kamekazemaster Yeah, I think if you provide a list of "require"ish functions to aliasify/browserify-transform-tools, you can probably get this going. So long as proxyquire and the actual requires end up with the exact same string at the end of the day, is should work. Looking forward to your PR. :)