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

Integration with proxyquireify #2

Closed
loicplaire opened this Issue Apr 16, 2015 · 15 comments

Comments

Projects
None yet
4 participants
@loicplaire

loicplaire commented Apr 16, 2015

I use browserify/react/proxyquireify on my project. I got the first two working but whenever I use proxyquire in my specs, i get errors like the one below:

Error: Cannot find module '../../../../app/components/Ads/PolarNativeAdTeaser'
    at app-test/specs/components/Ads/PolarNativeAdTeaserSpec.js:17

I believe I call the proxyquireify plugin correct in wallaby.js is:

'use strict';

var wallabify = require('wallabify');
var proxyquireify = require('proxyquireify');

var wallabyPostprocessor = wallabify({},
    function(b){
        return b.plugin(proxyquireify.plugin);
    }
);

module.exports = function () {
    return {
        files: [
            'node_modules/react-tools/src/test/phantomjs-shims.js',
            {
                pattern: 'app/**/*.js',
                load: false
            },
            {
                pattern: 'app-mock/**/*.js',
                load: false,
                instrument: false
            }
        ],

        tests: [
            {
                pattern: 'app-test/**/*Spec.js',
                load: false
            }
        ],

        testFramework: 'mocha@2.0.1',

        preprocessors: {
            'app*/**/*.js': function(file) {
                return require('babel').transform(file.content, {sourceMap: true});
            }
        },

        postprocessor: wallabyPostprocessor,

        bootstrap: function () {
            window.__moduleBundler.loadTests();
        }
    };
};

My spec is:

var proxyquire = require('proxyquireify')(require);
var PolarAdSlotTeaser = proxyquire('../../../../app/components/Ads/PolarNativeAdTeaser', {
    'react': Context.React,
    '../../utils/mixins/PolarNativeAdMixin': {}
});

A similar karma config using the proxyquireify plugin works without any issue with the exact same specs.

Am I doing something wrong?

@ArtemGovorov ArtemGovorov added the bug label Apr 16, 2015

@ArtemGovorov

This comment has been minimized.

Show comment
Hide comment
@ArtemGovorov

ArtemGovorov Apr 16, 2015

Member

Confirmed, reproduced it, thanks for the sample code. Looks like proxyquireify is replacing browserify default prelude script, investigating why wallabify doesn't work with it.

Member

ArtemGovorov commented Apr 16, 2015

Confirmed, reproduced it, thanks for the sample code. Looks like proxyquireify is replacing browserify default prelude script, investigating why wallabify doesn't work with it.

@ArtemGovorov

This comment has been minimized.

Show comment
Hide comment
@ArtemGovorov

ArtemGovorov Apr 16, 2015

Member

So proxyquireify works by replacing default browserify prelude code during pack phase and adding a transform to add normal require for everything that was proxyquireify-ed.

First, wallaby.js removes the pack phase of browserify as it doesn't serve bundles, so no need to pack anything. To address this issue I have added an option to pass a prelude code via options. Please make sure to update to wallabify@0.0.6.

Second, wallaby.js changes the original code (instruments it) and proxyquireify transform dependency search only works for simple cases, like

var proxy = require('proxyquireify')
var proxy = require('proxyquireify')(require)

In case of wallaby instrumentation, they become something like

var proxy = (w(...), require('proxyquireify'))
var proxy = (w(...), require('proxyquireify')(require))

and that makes proxyquireify not find these vars anymore.

To address this issue I have patched proxyquireify below. Ideally, I should send a PR to https://github.com/thlorenz/proxyquireify/blob/master/lib/find-dependencies.js to handle more complex scenarios, such as in wallaby case. But for now, all you need to do is to list variables that you assign to require('proxyquireify')(require), it is proxyquire in you example code, in one place in the patch. If you are using the same proxyquire name everywhere, then it's even easier.

So the config file that should work for you is:

'use strict';

var wallabify = require('wallabify');
var proxyquireify = require('proxyquireify');

// proxyquireify patch
var proxyquireifyPrelude = require('fs').readFileSync(require('path').join(__dirname, 'node_modules/proxyquireify/lib/prelude.js')).toString();
require('proxyquireify/lib/find-dependencies');
require.cache[require.resolve('proxyquireify/lib/find-dependencies')].exports = function (src) {
  if (!/require\(.+proxyquireify.+\)/.test(src)) return [];
  // IMPORTANT: list all variables that you assign like var proxyquire = require('proxyquireify')(require);
  var hash = ['proxyquire']
    .map(function (name) {
      return require('proxyquireify/node_modules/detective')(src, {word: name});
    })
    .reduce(function (acc, arr) {
      arr.forEach(function (x) {
        acc[x] = true;
      });
      return acc;
    }, {});

  return Object.keys(hash);
};

var wallabyPostprocessor = wallabify({
        // passing proxyquireify prelude code
        prelude: proxyquireifyPrelude
    },
    function(b){
        // we don't need anything but proxyquireify transform
        return b.transform(require('proxyquireify/lib/transform'));
    }
);

// the rest of your config didn't change

Please let me know if it works for you.

Member

ArtemGovorov commented Apr 16, 2015

So proxyquireify works by replacing default browserify prelude code during pack phase and adding a transform to add normal require for everything that was proxyquireify-ed.

First, wallaby.js removes the pack phase of browserify as it doesn't serve bundles, so no need to pack anything. To address this issue I have added an option to pass a prelude code via options. Please make sure to update to wallabify@0.0.6.

Second, wallaby.js changes the original code (instruments it) and proxyquireify transform dependency search only works for simple cases, like

var proxy = require('proxyquireify')
var proxy = require('proxyquireify')(require)

In case of wallaby instrumentation, they become something like

var proxy = (w(...), require('proxyquireify'))
var proxy = (w(...), require('proxyquireify')(require))

and that makes proxyquireify not find these vars anymore.

To address this issue I have patched proxyquireify below. Ideally, I should send a PR to https://github.com/thlorenz/proxyquireify/blob/master/lib/find-dependencies.js to handle more complex scenarios, such as in wallaby case. But for now, all you need to do is to list variables that you assign to require('proxyquireify')(require), it is proxyquire in you example code, in one place in the patch. If you are using the same proxyquire name everywhere, then it's even easier.

So the config file that should work for you is:

'use strict';

var wallabify = require('wallabify');
var proxyquireify = require('proxyquireify');

// proxyquireify patch
var proxyquireifyPrelude = require('fs').readFileSync(require('path').join(__dirname, 'node_modules/proxyquireify/lib/prelude.js')).toString();
require('proxyquireify/lib/find-dependencies');
require.cache[require.resolve('proxyquireify/lib/find-dependencies')].exports = function (src) {
  if (!/require\(.+proxyquireify.+\)/.test(src)) return [];
  // IMPORTANT: list all variables that you assign like var proxyquire = require('proxyquireify')(require);
  var hash = ['proxyquire']
    .map(function (name) {
      return require('proxyquireify/node_modules/detective')(src, {word: name});
    })
    .reduce(function (acc, arr) {
      arr.forEach(function (x) {
        acc[x] = true;
      });
      return acc;
    }, {});

  return Object.keys(hash);
};

var wallabyPostprocessor = wallabify({
        // passing proxyquireify prelude code
        prelude: proxyquireifyPrelude
    },
    function(b){
        // we don't need anything but proxyquireify transform
        return b.transform(require('proxyquireify/lib/transform'));
    }
);

// the rest of your config didn't change

Please let me know if it works for you.

@loicplaire

This comment has been minimized.

Show comment
Hide comment
@loicplaire

loicplaire Apr 17, 2015

Thanks for the quick feedback and update! That works perfectly.

loicplaire commented Apr 17, 2015

Thanks for the quick feedback and update! That works perfectly.

@ArtemGovorov

This comment has been minimized.

Show comment
Hide comment
@ArtemGovorov

ArtemGovorov Apr 17, 2015

Member

Awesome, thanks.

Member

ArtemGovorov commented Apr 17, 2015

Awesome, thanks.

@Almenit

This comment has been minimized.

Show comment
Hide comment
@Almenit

Almenit Dec 4, 2015

Any idés how to be able to use it with typescript? Is this the way to go?

import proxy from "proxyquireify";
var proxyquireify = proxy(require);

Almenit commented Dec 4, 2015

Any idés how to be able to use it with typescript? Is this the way to go?

import proxy from "proxyquireify";
var proxyquireify = proxy(require);
@ArtemGovorov

This comment has been minimized.

Show comment
Hide comment
@ArtemGovorov

ArtemGovorov Dec 4, 2015

Member

@Almenit As mentioned it my comment, you need to list variables that you assign. My patch is using proxyquire variable, your is using proxyquireify variable, so you may need:

...
var hash = ['proxyquire', 'proxyquireify']
...
Member

ArtemGovorov commented Dec 4, 2015

@Almenit As mentioned it my comment, you need to list variables that you assign. My patch is using proxyquire variable, your is using proxyquireify variable, so you may need:

...
var hash = ['proxyquire', 'proxyquireify']
...
@Almenit

This comment has been minimized.

Show comment
Hide comment
@Almenit

Almenit Dec 4, 2015

Yes I know that and I tried that. And It maybe right, but when I use proxyquireify() it can find my module. It is a bit hard to debug and find the error.

Almenit commented Dec 4, 2015

Yes I know that and I tried that. And It maybe right, but when I use proxyquireify() it can find my module. It is a bit hard to debug and find the error.

@ArtemGovorov

This comment has been minimized.

Show comment
Hide comment
@ArtemGovorov

ArtemGovorov Dec 4, 2015

Member

Does it work without wallaby? Try looking into the compiled files in wallaby cache, perhaps it could shed some light.

Member

ArtemGovorov commented Dec 4, 2015

Does it work without wallaby? Try looking into the compiled files in wallaby cache, perhaps it could shed some light.

@Almenit

This comment has been minimized.

Show comment
Hide comment
@Almenit

Almenit Dec 4, 2015

I will try that on monday. I will let you know :-)

Almenit commented Dec 4, 2015

I will try that on monday. I will let you know :-)

@ArtemGovorov

This comment has been minimized.

Show comment
Hide comment
@ArtemGovorov

ArtemGovorov Dec 4, 2015

Member

@Almenit Cool, let me know how it goes. If it doesn't work for you, please try reproducing it on the repo I have created for you earlier - https://github.com/wallabyjs/typescript-es6-babel and I'll have a look how to make it work.

Member

ArtemGovorov commented Dec 4, 2015

@Almenit Cool, let me know how it goes. If it doesn't work for you, please try reproducing it on the repo I have created for you earlier - https://github.com/wallabyjs/typescript-es6-babel and I'll have a look how to make it work.

@Almenit

This comment has been minimized.

Show comment
Hide comment
@Almenit

Almenit Dec 5, 2015

I will do that. Thanks @ArtemGovorov for your help.

Almenit commented Dec 5, 2015

I will do that. Thanks @ArtemGovorov for your help.

@Almenit

This comment has been minimized.

Show comment
Hide comment
@Almenit

Almenit Dec 7, 2015

Now it works! I had to fake a require in typescript and do a

var proxyquireify = require("proxyquireify")(require);

Almenit commented Dec 7, 2015

Now it works! I had to fake a require in typescript and do a

var proxyquireify = require("proxyquireify")(require);
@ArtemGovorov

This comment has been minimized.

Show comment
Hide comment
@ArtemGovorov

ArtemGovorov Dec 8, 2015

Member

@Almenit Awesome, thanks for the update! I'm guessing it's because proxyquireify expects certain code structures, but with separate import proxy from "proxyquireify"; TypeScript compiler generates the code that proxyquireify doesn't expect.

Member

ArtemGovorov commented Dec 8, 2015

@Almenit Awesome, thanks for the update! I'm guessing it's because proxyquireify expects certain code structures, but with separate import proxy from "proxyquireify"; TypeScript compiler generates the code that proxyquireify doesn't expect.

@elevatebart

This comment has been minimized.

Show comment
Hide comment
@elevatebart

elevatebart Mar 9, 2017

If someone is interested I created a quick npm package to prepackage this solution
wallabify-proxyquire-postprocessor

elevatebart commented Mar 9, 2017

If someone is interested I created a quick npm package to prepackage this solution
wallabify-proxyquire-postprocessor

@ArtemGovorov

This comment has been minimized.

Show comment
Hide comment
@ArtemGovorov
Member

ArtemGovorov commented Mar 9, 2017

@elevatebart Awesome, thanks for sharing! I have added your solution to our recipes list.

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