Meteor method timing out in cypress

We’re running our end-to-end tests with cypress and we added this little helper to run methods from our tests directly:

Cypress.Commands.add('getMeteor', () =>
  cy.window().then(({ Meteor }) => {
    if (!Meteor) {
      // We visit the app so that we get the Window instance of the app
      // from which we get the `Meteor` instance used in tests
      cy.visit('/');
      return cy.window().then(({ Meteor: MeteorSecondTry }) => MeteorSecondTry);
    }
    return Meteor;
  }));

Cypress.Commands.add('callMethod', (method, ...params) => {
  Cypress.log({
    name: 'Calling method',
    consoleProps: () => ({ name: method, params }),
  });

  cy.getMeteor().then(Meteor =>
    new Cypress.Promise((resolve, reject) => {
      Meteor.call(
        method,
        ...params,
        (err, result) => {
          if (err) {
            reject(err);
          }

          resolve(result);
        },
      );
    }));
});

// Use it like this for example
beforeEach(() => {
  cy.callMethod('resetDatabase');
  cy.callMethod('generateTestData');
})

The issue we have, is that sometimes this Meteor.call never returns, i.e. the callback is never fired, even though on the meteor server, the code has been executed and the method has reached the end without errors.

It only happens for one specific method. I moved it to be server-only which made it run fine a few times, then it didn’t work again. I tried to use Meteor.apply and play around with the options which helped for a few runs and then it started failing again.

I really have no idea what I can try, which package might be causing some kind of error to be swallowed, or whatever else might be happening.

When a meteor method finishes executing, what happens next? Who/what could be preventing the callback from being fired?

2 Likes

There is a more involved version at https://raw.githubusercontent.com/peer/doc/devel/tests/cypress/support/commands.js

maybe it could help in your case. or not.

In our case, I’m just doing it like:

const myFunc = function(win) {
  win.Meteor.call(myMethod, args, function () { /* whatever */ }`
}
describe("some test", () => {
  it("some subtest", () => {
    cy.server();
    cy.route('/sockjs/**', {});
    cy.visit('/');
    cy.window().then(myFunc);
    // ...more code
  }
}
1 Like

Thanks for the link!

I found the issue, it turns out that in the setup of the test we were redirecting the user to a different page, which created a new, second, websockets connection. Meaning the method was called on the first connection, and then was supposed to be returned on a new websocket connection, which was blocked by the socket library!

Making sure that the websocket connection is stable before calling meteor methods solved it! (i.e. waiting for the redirects to be over).