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

rewire does not work with babel #62

Open
panuhorsmalahti opened this issue Jun 11, 2015 · 26 comments
Open

rewire does not work with babel #62

panuhorsmalahti opened this issue Jun 11, 2015 · 26 comments

Comments

@panuhorsmalahti
Copy link

ES6 modules (compiled with babel) don't work with rewire.

@jhnns
Copy link
Owner

jhnns commented Jun 24, 2015

Same as jhnns/rewire-webpack#12

This is not an ES6 issue, but caused by the way how babel emulates the new module system.

@jhnns jhnns changed the title ES6 support rewire does not work with babel Jun 24, 2015
@jhnns
Copy link
Owner

jhnns commented Jun 24, 2015

Further insights: babel/babel#1337

Unfortunately, it's not easy to solve, because it requires a major rewrite. And tbh: I'm not very motivated, because babel's change, which is causing the problem, was driven by the misconception eval() was deprecated in ES6.

@mikaturunen
Copy link

👍 for being honest and saying it's not motivating.
You ok with the idea that someone else does it and sends you a PR about it?

@jhnns
Copy link
Owner

jhnns commented Jul 12, 2015

Definitely 👍

The tests, however, should stay the same (and they should still run afterwards). Since it would be a great rewrite, I'd appreciate if you could do this in close consultation. @speedskater has already contacted me.

@jabhishek
Copy link

Is anybody working on this?

@GreenGremlin
Copy link

@trodrigues
Copy link
Contributor

Just landed here after headbutting my code for a while and then looking for information on this. Wondering if it would be a good idea to have a paragraph about this in the readme to avoid people trying to do this with rewire in the first place. I can submit a PR :)

@jhnns
Copy link
Owner

jhnns commented Nov 11, 2015

@trodrigues you can do that. However, it should not sound like it's impossible to use rewire with ES2015 modules. I just have to figure out a good way how to hook-in rewire. I'll probably also have to refactor the public API so that rewire "ports" like rewireify are easier to integrate (also see #78)

@trodrigues
Copy link
Contributor

Right. But I think the main issue here is not ES6 modules in themselves but transpiled ES6 modules. I think that's always going to be a case specific to babel users.

@adjavaherian
Copy link

I think I might be having a similar issue.

     TypeError: Filename must be a string
      at internalRewire (node_modules/rewire/lib/rewire.js:19:15)
      at rewire (node_modules/rewire/lib/index.js:11:12)

This seems to happen only when I webpack my test files and their es6 deps and run them in mocha / node. I don't see any issues when I run the same tests thru my karma config and run them in the browser. The funny thing is that the webpack config should be about the same for both karma and mocha. I'll check for differences, but any suggestions would be greatly appreciated.

Thanks!

@jamlen
Copy link

jamlen commented Sep 5, 2016

Just FYI, my approach to 'fix' this is:

import _config from '../config';
let config = _config;

Then rewire as normal:

const thing = rewire('./path/to/thing');
thing.__set__('config', testConfig);

It's a little dirty as I don't like changing production code for test purposes. I normally add a comment like // This is to allow rewire its hooks

@mdunisch
Copy link

@jamlen Thank you - that really solves my problem for now!

@gregorydrake
Copy link

gregorydrake commented May 9, 2017

@jamlen Good solution!!

My assumption is that import modules in ES6 are frozen - thus Rewire can't dynamically modify what's being imported - hence why your solution, @jamlen, works?

@pilphil
Copy link

pilphil commented Aug 15, 2017

@jamlen - pardon my ignorance, but is the rewire('./path/to/thing') the workaround for rewire('../config')?

@jamlen
Copy link

jamlen commented Aug 15, 2017

@pilphil the rewire('./path/to/thing') is just the path to the class under test.

So if you have:

.
├── lib
│   └── thing.js
└── test
    └── test-thing.js

and you are writing the test file ./test/test-thing.js, then this would be rewire('../lib/thing')

@robertmain
Copy link

robertmain commented Oct 17, 2017

Is this the right place/issue to ask about support for mocking out calls to imported dependencies like fs etc.?

@jamlen
Copy link

jamlen commented Oct 17, 2017

@robrtmain you could check out this answer of mine if stackoverflow...
https://stackoverflow.com/a/30730818/2140627

@robertmain
Copy link

@jamlen that's fine but it looks like you're using require(), rather than import which is what I was asking :)

I know it works with require - what I was trying to figure out was if I could use it with import in TypeScript

@jamlen
Copy link

jamlen commented Oct 18, 2017

@robertmain I have some examples somewhere... let me dig them out :) it does work (although I wasn't using TypeScript)

@jamlen
Copy link

jamlen commented Oct 18, 2017

My class looks like this:

import { EventEmitter } from 'events';

import _logger from './logger';
import { stock as mappers } from './mappers';
import { stock as _StockStore} from './stores';

let StockStore = _StockStore;
let logger = _logger;

let store, _debug;

/** StockMigrator */
module.exports = class StockMigrator extends EventEmitter {

    /** Create a StockMigrator. */
    constructor () {
        super();
        store = new StockStore();
        store.on('write_data', (type, key, duration) => {
            this.emit('progress', 'write', key, duration);
        });
    }
  // other methods here...
}

My tests look like this:

import rewire from 'rewire';
import deride from 'deride';

const Migrator = rewire('../../../src/stockMigrator');
import { stock as mappers } from '../../../src//mappers';
import data from '../../data/stock';
import config from '../../config';

describe('Unit tests', () => {
    describe('Stock Migration', () => {
        let migrator, store;

        describe('stockMigrator', () => {
            before(() => {
                store = deride.stub([ 'writeDocuments' ]);
                store.setup.writeDocuments.toDoThis(() => {
                    store.emit('status', 'write_data', 'doc123');
                    return Promise.resolve();
                });
                Migrator.__set__({
                    StockStore: () => store,
                    logger: deride.stub(['debug', 'info', 'warn', 'error', 'audit'])
                });
                migrator = new Migrator();
            });
  // describes here...

@robertmain
Copy link

robertmain commented Oct 18, 2017

@jamlen so you got rewire to work with import then?

@jamlen
Copy link

jamlen commented Oct 19, 2017

@robertmain Yes, but with the caveat that you need to add a let to allow rewire to be able to substitute the mock.

@robertmain
Copy link

ah!

@robertmain
Copy link

@jamlen The problem I'm running up against at the moment with this in TypeScript is that it seems I have to load the thing I'm testing with rewire....which doesn't return the correct kind of object (it has no constructor) and then the ts language server gets upset.

@jamlen
Copy link

jamlen commented Oct 23, 2017

@robertmain at a guess I'd say this is a TS specific issue and probably raise a new issue for it.

@johnthad
Copy link

Using rewire 4.0.1, my attempt to call import { rewire } from 'rewire'; is met with the error:

HeadlessChrome 74.0.3729 (Mac OS X 10.14.4) ERROR
  Uncaught SyntaxError: The requested module '../node_modules/rewire/lib/index.js' does not provide an export named 'rewire'
  at http://localhost:9876/context.html:0:0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests