ilsenem
ilsenem

Reputation: 13

DalekJS and Mithril: Test are too fast

I use Dalek to test my sample to-do application written with help of Mithril framework.

Everything goes fine until .type() comes in.

If I .type() something in input that have bi-directional binding m.prop with m.withAttr and then assert values of that field i get strage behaviour. Instead "test title" I get "tsttle". It seems that test are running too quickly for Mithril to capture changes and render them back to DOM.

If assertions for input equality is removed — all works just fine.

Is there any workaround, can I slow down type process?

P.S. I use Chrome browser as test runner.

Upvotes: 1

Views: 690

Answers (3)

Sebastian Golasch
Sebastian Golasch

Reputation: 686

That definitely is an interesting issue, the problem is though, that Dalek can't control the speed of the letters typed. This is due to the fact that the JSON-Wire Protocol does not give us a way to handle that, see here

One thing you could do, even if it seems like overkill, is to add a long function chain with explicit waits, like this:

.type('#selector', 'H')
.wait(500)
.type('#selector', 'e')
.wait(500)
.type('#selector', 'l')
.wait(500)
.type('#selector', 'l')
.wait(500)
.type('#selector', 'o')

You also could go ahead & write a utility function that handles that for you

function myType (selector, keys, test, wait) {
  var keysArr = keys.split('');
  keysArr.forEach(function (key) {
    test.type(selector, key).wait(wait);
  });

  return test;
}

And then use it in your test like this:

module.exports = {
  'my test': function (test) {
    test.open('http://foobar.com');
    myType('#selector', 'Hello', test, 500);
    test.done();
  }
};

Upvotes: 2

LeoHorie
LeoHorie

Reputation: 1320

Mithril renders asynchronously in response to event handlers (basically so that related groups of events like keypress/input all get a chance to run before redrawing)

You could try a few things:

  • if you have access to your data model from your test, you could run your assertion against that model value (which is updated synchronously), as opposed to using the DOM value which only gets updated on the next animation frame

  • otherwise, you could force a synchronous redraw by explicitly calling m.render (yes, render, not redraw) before running the assertion, to ensure the view is actually in sync w/ the data model

  • alternatively, you could try waiting for one animation frame (or two) before running the assertion

Upvotes: 0

JohnSz
JohnSz

Reputation: 2049

Mithril, as of when I'm writing this, does a re-render on onkey* events. An option to avoid this is coming.

You could use attr::config at present to handle the onkey* events as this will not cause a rerender. For example:

m('input', {config: addHandler});

function addHandler (el, isInitialized, context) {
  if (!isinitialized) {
    el.addEventListener('onkeyup', keyHandler, false);
  }
}
function keyHandler (event) { /* do something with key press */ }

Its possible {config: addHandler, onchange: m.withAttr('value', mpropData)} will do what you want, but I don't know Dalek. If its doesn't, then you can consider updating mpropData inside keyHandler.

Upvotes: 1

Related Questions