unit-testingmeteorvelocitypublish-subscribeiron-router

Meteor js, iron-router, unit testing with Route.go('...') in server side doesn't work


I need to go to a specific router to test publish behavior, I'm using iron router package, Router.go('...'), but doesn't work in server side , it throw me an error:

   //XXX this assumes no other routers on the parent stack which we should probably fix      // 14
   I20150220-18:47:00.749(-4)?     router.dispatch(req.url, {                                                                // 15
   I20150220-18:47:00.750(-4)?       request: req,                                                                           // 16
   I20150220-18:47:00.750(-4)?       response: res                                                                           // 17
   I20150220-18:47:00.750(-4)?     }, next);                                                                                 // 18
   I20150220-18:47:00.750(-4)?   } has no method 'go'
   I20150220-18:47:00.750(-4)?     at packages/velocity:test-proxy/tests/mocha/server/publish/folders-publisher-tests.js:23:1
   I20150220-18:47:00.750(-4)?     at wrappedFunc (packages/mike:mocha/server.js:204:1)
   I20150220-18:47:00.751(-4)?     at runWithEnvironment (packages/mike:mocha/server.js:156:1)

My routers files are in lib, and I've already tried calling a method in my routers controller, but also doesn't work, does some one has a clue what it could be???? please


Solution

  • Iron router is a client/server library and is easily testable with a client test.

    This is how I make test using Meteor + Velocity + Mocha + chai :

    First, you need to create a file _lib.js containing a function which will wait while the router and your template is loading (idea I found there : https://stackoverflow.com/a/28782406/2294168)

    this.afterRendered = function(template, f) {
      var cb = template.rendered;
      template.rendered = function() {
        if (typeof cb === "function") {
          cb();
        }
        template.rendered = cb;
        if (typeof f === "function") {
          f();
        }
      }
    }
    

    And now you can write your clientTest.js

    if (Mochaweb) {
      MochaWeb.testOnly(function () {
        describe("what you test", function () {
          // If the argument done is specified, it means that you have 
          // something async in your test : afterRendered, setTimeout, setInterval ...
          it("Should do something", function (done) { 
            try {
              Router.go("user.login"); // which will load the page localhost/user/login and not localhost/user.login
    
              afterRendered(Template.userlogin, function() {
                chai.expect($("#something:visible")[0]).to.not.be.undefined;
                $("#magical-button").click();
                setTimeout(function() {
                    chai.expect($("magical-text:visible").html()).to.be.equal("I can handle async process");
                    done();
                },100);
              })
            } catch (e) {
              done(e);
            }
          });
          it("will test something else after the previous test, function () {
             ...
          });
        });
      });
    }