DailyJS

Let's Make a Framework: IE Testing

Alex R. Young

Subscribe

@dailyjs

Facebook

Google+

tutorials frameworks lmaf ie

Let's Make a Framework: IE Testing

Posted by Alex R. Young on .
Featured

tutorials frameworks lmaf ie

Let's Make a Framework: IE Testing

Posted by Alex R. Young on .

Welcome to part 45 of Let's Make a Framework, the ongoing series about
building a JavaScript framework.

If you haven't been following along, these articles are tagged with
lmaf. The project we're creating is called Turing.

IE Testing

The way I usually test my projects in IE is with
IETester. I actually run this in a virtual machine, just to be safe. Some of my clients still
require IE6, some are on 7, and I usually test in 8 and 9 as well.
Supporting IE6 is usually the most difficult thing to do, but I usually
find JavaScript debugging less painful than design glitches.

I opened IETester and tried running Turing's tests in IE6 and found they
didn't run. That's... just life, isn't it?

To focus a little bit more I tried a simple unit test instead of the
whole set. The
alias_test.html seemed like a simple one. It produced this error:

It's probably something to do with the slightly ambitious CommonJS
module style test system we created. Note that you can press the escape
key to quickly close these IE popup Windows. I tried removing the
alias_test.js script and the error didn't appear, which means there isn't a problem parsing the files that the test depends on.

After commenting out the code in the test itself, I figured out
require was failing somewhere. I used the IETester debug
tools to run require('') and the same error popped up. The
problem was here, in the Turing Test library:

head[0].insertBefore(scriptTag, head.firstChild);

IE Script Loading

At this point I found IE wouldn't attach load events to
script tags. I dimly recall something about this from Dean Edwards'
posts on window.onload
.

This is the kind of issue we had to deal with until the post web 2.0
revolution, but I came up with a scheme to use setInterval
to watch for changes on readyState on script tags. This
will work in IE, but not in anything else. That gave rise to this:

function loadIEScript() {
  var id = '__id_' + (new Date()).valueOf(),
      timer,
      scriptTag;
  document.write('');
  scriptTag = document.getElementById(id);

  timer = setInterval(function() {
    if (/loaded|complete/.test(scriptTag.readyState)) {
      clearInterval(timer);
      tt.doneLoading();
    }
  }, 10);
}

function loadOtherScript() {
  var scriptTag = document.createElement('script'),
      head = document.getElementsByTagName('head');
  scriptTag.onload = function() { tt.doneLoading(); };
  scriptTag.setAttribute('type', 'text/javascript');
  scriptTag.setAttribute('src', script);
  head[0].insertBefore(scriptTag, head.firstChild);
}

this.loading();
if (document.attachEvent) {
  loadIEScript();
} else {
  loadOtherScript();
}

The IE code uses document.write to insert a script tag with
a unique ID, then it watches for changes to the readyState
attribute. Confused? Well, it's not too difficult to follow this code,
but it would be nicer if we didn't need it.

Here's the proof it works!

If you're interested in this area, RequireJS is
shaping up to be a good library.

Conclusion

The single unit tests can now actually run in IE, even IE6. There's
still a lot left to do to get full cross-browser support into Turing,
but getting the tests going is an important first step.

To get this update, make sure you run git submodule update
to get the latest version of the Turing
Test
project.

References