Rant: IE and local JavaScript

So I’m writing a JavaScript-heavy application and testing it on my local machine. No problem, I think: just save the .html file on my disk and open it in a browser. Nothing could be simpler… if you’re using FireFox or Chrome.

IE, on the other hand, throws a hissy fit. “Danger!” it screams. “There’s a file on your local hard drive with JavaScript in it! Cower! Panic! The end is near!”

Okay, I took a bit of poetic license. What it actually says is, “To help protect your security, Internet Explorer has restricted this webpage from running scripts or ActiveX controls that could access your computer. Click here for options…”

Same thing.

It’s so bad that, if I type a path to a local file into the address bar, IE won’t even open it in the same window. It has to open a new window. Opening a local file involves opening IE, typing the path, clicking OK to its “sky is falling” dialog, letting it open its new window, Alt+Tabbing back to the original window, and closing it. All to open a file that’s under my complete control, completely trusted, doesn’t even require a network access.

Oookay. I guess I get it: IE is a claustrophobe. It panics when it feels the four walls of the local hard drive closing in on it. The remedy, obviously, is to let it out, and make it feel like it’s actually accessing the network. So I installed IIS, set up a virtual directory, and browsed to the web server on my local machine.

FireFox works fine. Chrome works fine. IE runs screaming in horror. “Oh noes!” it cries. “You’re trying to access an intranet! Oh, will nobody save me from the unspeakable dangers lurking on the private, firewalled network?”

Yeah, yeah, poetic license again, but honestly, that boy could use some Prozac*. Or heavy drugs. Or group hugs.

* Actually, anti-depression meds aren’t a good fit for the symptoms. Anti-anxiety might be better. Or possibly a good anti-psychotic.

At least it does run JavaScript now. And you can tell it to shut up about the many perils of the Intranet zone. (For that matter, yes, I could configure it to allow JavaScript for local files. But that doesn’t answer the question of why it’s got ridiculous settings to begin with.)

I just don’t get it. When IE runs across JavaScript on the big bad Internet, it trusts it unquestioningly. Sure, there are zone settings; it won’t let it do anything dangerous. But how is that less worthy of abject terror than something on my own hard drive? If I opened an EXE from my hard drive, Windows would quite happily let it install all the spyware it wants. But heaven forbid I open a Web page with some JavaScript animation. That might be bad.

Can’t we treat a Web page like a Web page and just open the damn thing? Is that too much to ask?

(Apparently not, because everybody but IE can do it just fine…)

Fumbling toward automation: running JavaScript tests with Watir

A group at work is doing some web-app development, and they’re using a tool called WatiN for end-to-end tests. I’m aware of that but didn’t think much of it.

Last night I went to Brian Marick‘s talk at the odynug meeting, and in passing, he mentioned Watir, which it turns out is infinitely cooler than WatiN, because Watir (a) came first, (b) is in Ruby, and (c) can automate IE, FireFox, and (via a separate library) Chrome.

I’m working on a JavaScript-based video-game development kit, and I spend a lot of time Alt+Tabbing to a browser, Ctrl+Tabbing to the tab with the automated test runner, refreshing the page, waiting (especially in IE) for the tests to finish, and (in Chrome) deciding whether the failures are actual test failures or just Chrome failures. Then it’s Alt+Tab to the next browser in the round-robin to try it again.

It shouldn’t be this hard to run all the tests. And with Watir, it looks like it won’t be. I think I’ll be able to write a Ruby script that

  • finds the Chrome tab that’s already open to the test URL (or opens a new tab);
  • reloads the Screw.Unit test page;
  • waits for the tests to complete;
  • scrapes the HTML to decide whether the tests passed or failed; and
  • repeats with FireFox and then with IE.

It won’t be trivial, because the Watir documentation really has nothing to say about finding stuff in the DOM. They’re heavily oriented toward clicking links and filling in forms, so if you want to manipulate a button or a hyperlink or a text field, they’ve got you covered. A myriad of examples, cheat sheets, and FAQs will get you on your way using methods like text_field and button. But if you want to find an <h3> with a particular CSS class, I wish you a lot of luck. The documentation does not go there. You need a lot of Google searches, a lot of luck, and a lot of lucky guessing.

I did scrape together something useful, and I’m noting it here. My tests currently report their results in an <h3>, which happens to be the only h3 on the page. This snippet of Ruby code will display the contents of that h3 (assuming the variable ie already refers to a Watir::IE instance):

ie.document.getElementsByTagName("h3")["0"].innerHTML

Huh. I get it that getElementsByTagName would return an array, so I would understand — and expect — having to do [0] on it. But [0] gives me an error: “TypeError: can’t convert Fixnum into String”. ["0"] works fine, though. I do not understand why, but as long as it works, I’ll accept that for now.

That’s just a start, though, because that snippet only works for classic Watir (for IE). FireWatir (the FireFox version, which is part of the same install but apparently not a compatible Ruby API) fails with “NoMethodError: undefined method `getElementsByTagName'”, and ChromeWatir (separate install) fails with “NoMethodError: undefined method `document'”.

Ah well. I came up with the above snippet by stealing shamelessly from the code for Watir’s show_spans method. Maybe I can do the same for the FireWatir and ChromeWatir versions of show_spans (if they have it). We shall see.

Credit Card Freedom Day

We got our state tax refund today. And after work, Jennie and I mailed what will be the last credit card payment we’ll ever make.

We’d hoped to be done by the end of last year, but life happened. There were a lot of things we hadn’t planned for, and even with Jennie and me both working part-time, it took us longer than we thought. But we made it. We’ve been in debt together for longer than we’ve been married, and finally, after something like fourteen years, a big, big part of that debt is gone. (And I put in my two week’s notice at my part-time job the day after I filed the tax returns. Tomorrow I work my last weekend there.)

Whew.

No more credit card payments. Ever.

In some ways it feels like starting our life together all over again.

Zombies Ahead

Zombies AheadSomebody hacked some digital road signs to say “Zombies ahead.”

No, I’m not making this up. More footage.

Despite what some articles are saying, criminal charges will not be filed. The signs are owned by a private company, not by the city, so that company would have to press charges; and the owner said, “It’s Austin. We have a sense of humor. Let it go.

Too funny.

And before you ask, I was nowhere near Austin this weekend.

jQuery lesson learned: Close your tags

I’ve been playing around with JavaScript, so of course I’ve been looking for a JavaScript unit-testing framework — or better yet, a BDD framework, since they tend to make the assertions much more readable. I found Screw.Unit, and fell in love with it for its nested describes, which definitely merit their own blog post.

But I kept using JSSpec for a while, because Screw.Unit is still pretty buggy. JSSpec isn’t a resounding win by any means; its assertion syntax is merely okay, and it leaves you stuck with the traditional test-suite mentality. But it’s got a fantastic test-runner GUI that scales well as you add lots of tests.

Well, this weekend, after writing tests for one of my classes in both JSSpec and Screw.Unit, I finally decided the nested describes were so worth it. So I checked the Screw.Unit distro into my svn repository and started making the Screw.Unit runner better. I made it so you can tell when the tests are done, and whether any failed. I made it automatically scroll to the first failure on the page. I converted all my tests over to Screw.Unit. And I checked it all into my repository.

Then I tried running it in IE. Whoops. Blank page with nothing but some Roman numerals. Guess I should’ve done some cross-browser checking a little sooner…

I did some digging and some troubleshooting, and found that this jQuery syntax:

$('#myDiv').append($('<h2>'));

doesn’t work in IE. Dynamically-created nodes (the $('<h2>')) weren’t being added to the page — the append was doing nothing.

So I posted a question yesterday night on the jQuery list (“append() not working on dynamically-created nodes in IE”), and by this morning, I already had an answer: close the tag.

$('#myDiv').append($('<h2></h2>'));

Explains why some of my own code that created images was working in IE — I was using XHTML <img/> syntax, so my tags were closed.

I tried closing all the tags Screw.Unit was dynamically creating, and it worked like a champ. So there’s my jQuery lesson learned for today: always close your tags. If you don’t, things May Not Just Work.