Anybody else had this? "Error: Cannot find module 'meteor/xolvio:cleaner'"

Before flagging this as an issue on the xolvio/cleaner github repo, I thought I’d post here since there’s a good chance it’s just a newbie error and maybe someone else has had the same thing (although google searches have come up empty so far)

As per the meteor testing guide I recently installed chimp to try out some end-to-end testing. It seems to be working fine.

I also used meteor add xolvio:cleaner to get access to the resetDatabase function, and of course added

import { resetDatabase } from 'meteor/xolvio:cleaner';

to the top of my test file. When using chimp-watch (and chimp-test) I get the following error message on test startup and no tests run:

/...../language-tracker/node_modules/chimp/dist/lib/mocha/mocha-wrapper.js:62 
  throw e;
  ^
Error: Cannot find module 'meteor/xolvio:cleaner'
at Function.Module._resolveFilename (module.js:325:15)
at Function.Module._load (module.js:276:25)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)
at Object.<anonymous> (signup.js:1:1)
at Module._compile (module.js:409:26)
at loader (/...../language-tracker/node_modules/babel-register/lib/node.js:148:5)
at Object.require.extensions.(anonymous function) [as .js] (/...../language-tracker/node_modules/babel-register/lib/node.js:158:7)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)
at /...../language-tracker/node_modules/mocha/lib/mocha.js:220:27
at Array.forEach (native)
at Mocha.loadFiles (/...../language-tracker/node_modules/mocha/lib/mocha.js:217:14)
at Mocha.run (/...../language-tracker/node_modules/mocha/lib/mocha.js:469:10)
Mocha failed

`
Clearly, Mocha doesn’t like something about the import and it is failing. I have tried this with cleaner 0.3.1 as well as the previous version (0.3.0) with the exact same error. I have I have an npm-debug.log file as well which I could post if that was helpful as well as my complete package list. I am using meteor 1.4.0.1 with node 4.4.7 and npm 3.10.5. I don’t know much about node at all.

Sounds like an issue with chimp. Seems like it’s not evaluating Meteor modules (the ones that don’t come from NPM) properly.

But I don’t think it’s related to xolvio:cleaner.

thanks @sashko - you are right. I tried doing something else:

import { Meteor } from 'meteor/meteor';)

and got the same error. I now realise that I don’t actually have access to the Meteor stack in these chimp tests - as per this article on the forum. I’d have to use the xolvio:backdoor package and server.execute. In hindsight, in my case I think I need to actually write a full-app integration test rather than the chimp acceptance tests.

Hey @chabekah

This is the most common newbie mistake :slight_smile:

So the tests that run in the Chimp context do not run in Meteor, they run outside Meteor and talk to the app. They run in a completely different node.js process.

So to do a reset, you can use the server.execute method, which works like this:

HTH

2 Likes

Thanks for that. Just for the record, this is VERY confusing… I have spent all night trying to get this working trying to use the Meteor guide and the Chimp help - with no joy till you replied. So thanks, but I am really struggling to get end-to-end testing working with access to my Meteor app!

BTW, how come server.call('logout') works, but when I try server.call('user') a few lines later in the same code block, I get an error message:

Uncaught Error: Method 'user' not found [404]

I was assuming that your logout was some kind of shorthand for Meteor.logout() - but clearly not.

Glad that helped

server.call('logout') is actually calling a DDP endpoint that is added by the Meteor accounts system. There is not a user Meteor method.

if you want to get the current user, you do this:

const userInTestContext = server.execute(function() {
  // this function runs in the Meteor context
  return Meteor.user();
});
// this runs in the test context
console.log(userInTestContext);

stick with it, it’ll all make more sense as you struggle with it :slight_smile:

1 Like

Thanks for that @sam. I was actually grasping at straws with the server.call(‘logout’) thing, so thanks for the clarification. I had actually tried what you suggest to return the current user - but Meteor.user() is returning null, although I can see (by following the action on the browser window that pops up) that my test script code for logging out, trashing the DB, creating a new user and logging them in is running fine. The new user gets into mongo as well. My code looks like this:

describe('signing up @watch', function () {
  describe('with good data', function () {

    beforeEach(function () {
      server.call('logout');
      server.execute(function () {
        Package['xolvio:cleaner'].resetDatabase();
      });

      browser.url("localhost:3000/signup");
      browser.setValue('[name="email"]', "test@examples.com");
      browser.setValue('[name="password"]', 's3cr3t!');
      browser.click('input[type=submit]');
    });

    it('logs user into system', function () {
      const userInTestContext = server.execute(function () {
        return Meteor.user();
      });
      console.log(userInTestContext);  // this line prints "null" to the console
    });
  });
});

Is it a synchronous issue I wonder? Or is there something else incredibly obvious and newbie that I am still missing?

You might need to wait for the login to actually happen. The brute force of doing it is to use browser.pause(2000), which you can use to see if that’s the problem.

The better way is to wait for something to actually tell you that the login happened, like browser.waitForVisible('someSelector').

Also, you’re better off using this to login rather than the browser:

browser.executeAsync(function(done) {
  Meteor.loginWithPassword('test@examples.com', 's3cr3t!', function(err) {
    if (err) {
      console.error('Could not login', err);
    } else {
      done();
    }
  })
});

this will do the login programmatically and wait for the login to complete

Well, I’m still stumped… None of these things (brute force 2 second wait, wait for visible or the async code) seem to have made any difference. With all three techniques, I am able to successfully log in, but when it comes time to tell me who the Meteor.user() is, I just get “null”. BTW, for other folks who come after me, the async code needed a slight amendment at the start to stop timeouts.

browser
    .timeoutsAsyncScript(1000)
    .executeAsync(function ( done) {
      Accounts.createUser({ email: 'test@examples.com', password: 's3cr3t!' }); 
      Meteor.loginWithPassword('test@examples.com', 's3cr3t!', function (err) {
        if (err) {
          console.error('Could not login', err);
         } else {
           done();
         }
       });
     });

It seems to do the log-in - I can see the extra fields that are added when a user logs in are in Mongo. So, although this code (and my less elegant previous attempts too) were successful at logging in, my inability to access Meteor.user() after log in (and probably other Meteor collections after I add them to my app) is going to limit the usefulness of this testing system to testing what appears on the browser window. But I guess that’s the focus of this testing technique anyway; I can always use unit tests for checking the internals. Thanks Sam - I’m giving up for now.

    it('logs user into system', function () {
      const userInTestContext = server.execute(function () {
        console.log(Meteor.user()); // **** check this in the browser console
        return Meteor.user();
      });
      console.log(userInTestContext);  // this line prints "null" to the console
    });

If you have the patience, try the above code - I’m curious as to what is happening on the browser side at test time

Both console.logs return null. Using return Meteor.xxuser() with the obvious syntax error throws

Uncaught Error: Error in server.executeTypeError: Meteor.xxuser is not a function

as expected, so the code is being run. Using console.log(Meteor) inside the server.execute function returns a big fat juicy Meteor object - so it is accessing Meteor internals, it’s just that Meteor.user() is returning null. Weird.

Yep, that’s the real issue. Definitely in the app code and not the test/backdoor code.

Perhaps you don’t have the accounts package?

I have accounts-password. As it turns out, I didn’t have accounts-base - although running Meteor.user() from the browser console returns a user… I added the package, but it makes no difference. Thanks for the suggestions…

Well now I’m intrigued! PM me and add me to a repo and I can have a look if you like.

I know this is a dead thread, but for anyone else that may encounter the same problem (null being returning for this.userId()), here is the solution.

The reason that it returns null is because Chimp is connecting to the Meteor app via a different DDP connection than the browser. Hence, if you login through the browser - and call server.execute, these are completely isolated DDP connections!

To fix this, you need to login inside your tests, in this way:

        server.call('login', {
            user: {email: "kim@mail.com"},
            password: "password"
        });

NB: server.call(‘login’, …) is a built in method by Chimp! All, you have to do is pass in an email address and password.

Now, if you call Meteor.user() or this.userId() inside server.execute or call a Meteor method with server.apply then this will happen under the context of kim@mail.com being logged in and it will work fine.

Also, the following Github issue is about the exact same problem:

1 Like

Thanks for that @kimeshan. I will return to this testing stuff eventually and try out your suggestion.