QUnit doesn't seem to be an option, and since our needs don't seem particularly intense I decided to write my own drupal-specific JavaScript testing framework. I'm aware of the issues with going down this path, but I've decided that the benefits (a Drupal-specific system) outweigh the costs (developing and maintaining our system). This is, of course, open to debate. I wrote a preliminary patch to spark discussion; barring major objections, I'll develop it further over the week.

Note that some previous work exists at #237566: Automated JavaScript unit testing framework; I just didn't really want to hijack that issue for something that may or may not be the way we end up going. I'll post a note there too, though.

The patch builds on the ideas developed with qunit, and mostly plays around with HTML in an 1x1 iframe so as to avoid messing up the page. This also means that we can theoretically write completely functional tests that test the process over multiple pages, since changing the location of the iframe does not halt the JavaScript processes.

CommentFileSizeAuthor
#1 javascript_testing_framework_01.patch14.98 KBcwgordon7
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

cwgordon7’s picture

And the patch.

chachasikes’s picture

This is super cool. I'm new to the discussions about adding Javascript tests for Drupal - but I am very interested in this.

We are talking about writing some 'test' tests for the modules/user/user.js password checker interaction

And I want to try writing one for the textarea resizer :)

Good work...about to try out the patch on my machine!

dawehner’s picture

 and mostly plays around with HTML in an 1x1 iframe so as to avoid messing up the page.

We could use a non-minized version for something comparable to verbose mode on simpletest.

rfay’s picture

@cwgordon7, Thanks as always for your work!

Could you please write a more detailed description of your vision?
Does it provide functional testing? Can it test something like AJAX forms or the AJAX subsystem? Can it test #states? Does it do any in-browser testing? What infrastructure would be required to use it?

Thanks!
-Randy

cwgordon7’s picture

It could in theory run both functional testing and elaborate in browser testing with workflows spanning multiple pages. It could indeed test AJAX forms and the AJAX subsystem. Note that I have not actually written any tests that would do that yet, so it likely needs to be tweaked for that to work. The next tests I want to write will be some sort of basic functional test and some sort of basic AJAX tests, likely password checker and autocomplete, respectively. This is still in the early stages of development, but any PHP side it needs is not yet available. Also note that if you want to try it out it will currently just spit the results of the tests to the console in firebug.

rfay’s picture

Hope all who are interested in this problem and who are at Drupalcon can come to a BoF today on Javascript functional testing, 4pm, Room 200.

dmitrig01’s picture

Status: Active » Closed (duplicate)
rfay’s picture

Status: Closed (duplicate) » Active

I actually think it's OK to have two competing approaches going.

I've finally spent some time looking at the various approaches that have been proposed, and it seems to me that jquery isn't at all good at simulating user input (things like triggering clicks, etc.). I'm wondering if any of these approaches will get us any kind of functional testing. I had hopes, but fiddling with jquery trying to get it to click a link in an iframe makes me less confident.

@cwgordon7, @dmitrig01: Both of you have spent quite a lot of energy on the two approaches in these two issues. I know that either one of them can result in javascript unit tests (that don't rely on Drupal's back end, or on combined javascript+server behavior). But I'm still unconvinced that they can test things like AJAX forms, where a button click results in a server call which results in a page update. As you say, it has to happen in an iframe. Can you make this work?

I think the real question is not whether we'll use our own testing framework or qunit (or whatever), but do we have a way to test successfully. Can we test an AJAX action and validate that it happens? (Yes on the validate, I think. No, I suspect, the manipulation of form elements may be quite awkward)

Your thoughts?

rfay’s picture

For example,

I just loaded up the Drupal node/add/book page in an iframe. A book exists (#103)

Using firebug I did
$("iframe").contents().find("#edit-book-bid").val(103)

Which properly changed the value of the book... However, an AJAX event was supposed to have been fired (on "change"), which would have caused the book-organizing select to be displayed. However, jQuery just changes the val() directly, and the change event doesn't fire.

rfay’s picture

Update:
I was able to make jquery submit a 'change' successfully where there is no iframe involved:

On node/add/book, with a book id of 103 available:

$("#edit-book-bid").val(103);
$("#edit-book-bid").change();

The above works: On the change() it triggers the ajax behavior and all is good.

Unfortunately, the same thing doesn't work on a page that has node/add/book in an iframe:

$("iframe").contents().find("#edit-book-bid").val(103);
$("iframe").contents().find("#edit-book-bid").change();

In that case nothing happens.

katbailey’s picture

OK, so the challenge that was laid down to me by rfay was whether I could trigger this ajax change event in an iframe, and... well I did achieve this, but I'm not sure it was in an acceptable way. Here's what I put into the fb console:
$("iframe").once(function(){$(this).contents().find("#edit-book-bid").val(2);this.contentWindow.drupalChange('#edit-book-bid')});
... where drupalChange() is a function that exists inside the iframe which calls .change() on whichever selector you pass to it.

So, does that just make me a terrible cheat, or is it of any use? :-P

rfay’s picture

Thanks, @katbailey!

Can you help me on a bit further?

I implemented drupalChange() and it works fine when I'm not in an iframe, but on FF3.6 I get TypeError: this.contentWindow is undefined { message="this.contentWindow is undefined", more...}

It looks like maybe d.o or something ate part of your statement, since it's not valid (trailing "})"

Thanks,
-Randy

katbailey’s picture

Well, I actually had to put it in like this:

(function($){$("iframe").once(function(){$(this).contents().find("#edit-book-bid").val(2);this.contentWindow.drupalChange('#edit-book-bid')});})(jQuery);

... to avoid that TypeError problem, I had figured you had some other way around that which was why you had left it out of your code snippets above ;-)
Let me know if you're still having trouble with it.

rfay’s picture

Just for reference, katbailey's approach does work great, and I tested it in IE8 also, but lower versions. In this case the value we want to change the book to is 103:

jQuery("iframe").contents().find("#edit-book-bid").val(103);
jQuery("iframe").get(0).contentWindow.drupalChange("#edit-book-bid");
rfay’s picture

My current thinking is that a Selenium-based approach will be more robust: #825436: Create selenium-RC PIFR plugin for full functional testing. Your comments and participation are welcome!

kwinters’s picture

Maybe we could use some custom framework to make simple JS tests easy (check_plain result testing), and Selenium to handle things like AJAX? Trying to handle all the special cases seems overly ambitious, but a simple JS testing framework that is easy to run and create tests for might still have value (Selenium has a greater barrier to entry).

We've already been bitten by check_plain etc. bugs, so I'd rather have some basic functionality that works well in D7 than nothing at all.

rfay’s picture

@kwinters, that allows individual developers to run a test in their own browser, which would be a step forward, but it has no way to ever automate the test, so ends up being neglected.

kwinters’s picture

I was under the impression that the test bot was listing similar tests at #237566: Automated JavaScript unit testing framework ("Also, the checkPlain tests don't pass, and this is for good reason, because checkPlain is broken (yay tests!)."), but if you're right and the test bot can't handle this approach then Selenium is a clear victor.

rfay’s picture

When you think about it, in what browser is the testbot going to execute javascript in #237566: Automated JavaScript unit testing framework (or this one)? There just isn't a browser available.

moshe weitzman’s picture

Saw a helpful article about JS unit testing. Maybe it will inspire someone to move this issue along - http://msdn.microsoft.com/en-US/scriptjunkie/gg655487?utm_source=javascr...

ygerasimov’s picture

I have done some work for integration of Selenium Webdriver (not Selenium RC) into simpletest. That allows to test javascript and upload of files. The repo is here http://drupal.org/sandbox/ygerasimov/1131210

I have also written blog post with video demo http://ygerasimov.com/integrating-selenium-to-drupal-simpletest-framework

I would very appreciate review and comments about it.

nod_’s picture

http://drupal.org/project/testswarm is working pretty well for testing (works with qunit) and use the iframe trick, does this issue still needs to exists? what's the benefit of keeping this one around as well as the other?

I do not want to maintain a custom testing framework or anything custom if possible, there is enough issues to keep the little amount of people working on JS busy already.

nod_’s picture

Status: Active » Closed (duplicate)

No reason to keep this one around.