Mocking meteor package imports in Jest?

I have a test that imports a React component which uses a Meteor package (meteor/universe:i18n). How does one go about mocking that? I tried starting my Jest test file with:

jest.mock('meteor/universe:i18n');

But it doesn’t work. @sam or @sanjo, you might have an answer for this?

1 Like

In case others find this question, here is a link to a helpful issue that @ffxsam raised on the jest repo-- https://github.com/facebook/jest/issues/1388. Long story short, use the moduleNameMapper property in your jest config, and it “just works” :slight_smile: Here’s an example config:

// jest-config.json
{
  "collectCoverage": true,
  "coverageDirectory": "tests/jest-coverage",
  "moduleNameMapper": {
    "^meteor/kadira:flow-router$": "<rootDir>/tests/jest-meteor-stubs/FlowRouter.js"
  },
  "resetMocks": true,
  "testRegex": "((tests\/jest/.*|\\.(test|spec))\\.(js|jsx)$)",
  "verbose": true
}

a function that uses FlowRouter:

// imports/startup/client/globalUIHelpers/cjfPathFor.js

import { FlowRouter } from 'meteor/kadira:flow-router';

export default function cjfPathFor(routeName) {
  return FlowRouter.path(routeName);
}

the test…

// tests/jest/ui-helpers/cjfPathFor-test.js

/* eslint-env jest */
/* eslint-disable no-console, global-require, import/first */
import { FlowRouter } from 'meteor/kadira:flow-router';
import cjfPathFor from '../../../imports/startup/client/globalUIHelpers/cjfPathFor';

describe('cjfPathFor', () => {
  it('calls FlowRouter.path', () => {
    const testPath = 'Signup';
    cjfPathFor(testPath);
    expect(FlowRouter.path).toBeCalledWith(testPath);
  });
});

and the stub…

// tests/jest-meteor-stubs/FlowRouter.js

/* eslint-env jest */
module.exports = {
  FlowRouter: {
    path: jest.fn(),
  },
};

Thanks for sharing! Though in my example in the GitHub issue, I’ve used a regexp pattern for moduleNameMapper, which allows one to just put new mock files in a folder, rather than modifying package.json every time you want to mock a Meteor package.

Got that regex handy?

Nevermind, just saw it was in the Github issue, missed that part.

For future ref:

    "moduleNameMapper": {
      "^meteor/(.*)": "<rootDir>/__mocks__/meteor/$1.js"
    }
1 Like

Don’t use __mocks__ though (as I was advised by someone who works on Jest).

meteor/(.*)": "<rootDir>/.meteor-mocks/$1.js"

I can’t seem to get it to work either way, keeps saying it can’t find ‘meteor/http’ despite me having an http.js file in the folder in question…

Need to escape the ‘/’ in the package name:

“moduleNameMapper”: {
“meteor/(.*)”: “/tests/mocks/$1.js”
},

Strange. I haven’t had time to revisit this, but last I checked, it did work. In my case, I have universe:i18n.js inside the meteor mocks folder, which looks like this:

exports._i18n = {
  __: function(value) { return value },
};

So when I import this and use, e.g. _i18n.__('okButton') for localization, it should use the mock.

Also, the line should be:

"^meteor/(.*)": "<rootDir>/.meteor-mocks/$1.js"

Sorry. I think the beginning got lost last time.

I don’t think you do. It’s likely that jest is using RegExp to create the pattern, which automatically escapes slashes for you.

> s = 'old/new';
'old/new'
> rx = new RegExp('old/new');
/old\/new/
> rx.test(s)
true
>

I don’t think you do. It’s likely that jest is using RegExp to create the pattern, which automatically escapes slashes for you.

Indeed. I had added the escape at one point, which appeared to work… then ended up breaking other things.

This pattern is working well for me:

"moduleNameMapper": {
      "meteor/(.*)": "<rootDir>/tests/mocks/$1.js"
    },

Do note the export in the object should be named the same way you’re importing the asset. EG the ‘okgrow:analytics.js’ file would contain

module.exports = {
  'analytics': {
    track: jest.fn(),
  },
};
2 Likes

I’m creating a module to stub out the prominent Meteor packages including Mongo and Meteor at the core, since this is being used all over the place in multiple apps we have.
Check it out: https://github.com/orangecms/jest-meteor-stubs

If you like it, feel free to contribute, file PRs, wishes, etc. etc. :slight_smile:

I’m looking into this exact question right now. I’d like to use import { Email } from 'meteor/email' and then jest.mock('Email'), however Meteor imports are not recognized.

With a search I found https://github.com/jedwards1211/babel-plugin-meteor-imports, however there’s not documentation on how to use it. (Perhaps it’s easy?)

I haven’t heard of another package system within JavaScript other than npm and Meteor. With ES6 modules, it seems like Meteor should do more to support

import <module> from 'meteor/*'

outside of

meteor *

tools.