fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2011-02-24 05:21 am

[dw-free] Create page to run multiple test pages using our js test framework

[commit: http://hg.dwscoalition.org/dw-free/rev/c7966d7a04db]

http://bugs.dwscoalition.org/show_bug.cgi?id=3534

Run multiple tests on the same page. /dev/tests now runs all tests that are
available; /dev/tests/testname runs the different libraries for /testname.

Patch by [personal profile] exor674.

Files modified:
  • cgi-bin/DW/Controller/Dev.pm
  • htdocs/js/tests/qunit-all.js
  • htdocs/stc/tests/qunit-all.css
  • views/dev/tests-all.tt
  • views/dev/tests.tt
--------------------------------------------------------------------------------
diff -r b79f5e330c01 -r c7966d7a04db cgi-bin/DW/Controller/Dev.pm
--- a/cgi-bin/DW/Controller/Dev.pm	Thu Feb 24 12:08:50 2011 +0800
+++ b/cgi-bin/DW/Controller/Dev.pm	Thu Feb 24 13:21:25 2011 +0800
@@ -22,16 +22,37 @@ use DW::Routing;
 
 DW::Routing->register_static( '/dev/classes', 'dev/classes.tt', app => 1 );
 
+if ( $LJ::IS_DEV_SERVER ) {
+    DW::Routing->register_string( '/dev/tests/index', \&tests_index_handler, app => 1 );
+    DW::Routing->register_regex( '/dev/tests/([^/]+)(?:/(.*))?', \&tests_handler, app => 1 )
+}
 
-DW::Routing->register_regex( '/dev/tests/([^/]+)(?:/(.*))?', \&tests_handler, app => 1 )
-    if $LJ::IS_DEV_SERVER;
+sub tests_index_handler {
+    my ( $opts ) = @_;
 
+    my $r = DW::Request->get;
+
+    $r->note( bml_use_scheme => "global" );
+    return DW::Template->render_template( "dev/tests-all.tt", {
+        all_tests => [ map { $_ =~ m!tests/([^/]+)\.js!; } glob("$LJ::HOME/views/dev/tests/*.js") ]
+    } );
+}
+    
 sub tests_handler {
     my ( $opts ) = @_;
     my $test = $opts->subpatterns->[0];
-    my $lib = $opts->subpatterns->[1] || "";
+    my $lib = $opts->subpatterns->[1];
 
     my $r = DW::Request->get;
+
+    if ( ! defined $lib ) {
+        return $r->redirect("$LJ::SITEROOT/dev/tests/$test/");
+    } elsif ( ! $lib ) {
+        $r->note( bml_use_scheme => "global" );
+        return DW::Template->render_template( "dev/tests-all.tt", {
+            test => $test,
+        } );
+    }
 
     my @includes;
     my $testcontent = eval{ DW::Template->template_string( "dev/tests/${test}.js" ) } || "";
diff -r b79f5e330c01 -r c7966d7a04db htdocs/js/tests/qunit-all.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/js/tests/qunit-all.js	Thu Feb 24 13:21:25 2011 +0800
@@ -0,0 +1,172 @@
+var _r = {
+    all_tests: [],
+    all_libs: ['old','jquery'],
+    next_test_idx: 0,
+    next_lib_idx: 0,
+    init: function() {
+        _r.next_test_idx = 0;
+        _r.next_lib_idx = 0;
+        _r.test_container = $("#qunit-tests");
+        _r.test_results = $("#qunit-testresult");
+        _r.test_banner = $("#qunit-banner");
+
+        _r.passed = 0;
+        _r.failed = 0;
+        _r.total  = 0;
+        _r.test_time = 0;
+
+        _r.start_time = new Date().getTime();
+
+        $("#qunit-filter-pass").attr("disabled",true);
+        $("#qunit-testresult .line1").text("Pending...");
+        _r.update_counts();
+    },
+    run_next: function() {
+        if ( _r.next_lib_idx >= _r.all_libs.length ) {
+            _r.next_lib_idx = 0;
+            _r.next_test_idx++;
+        }
+        if ( _r.next_test_idx >= _r.all_tests.length ) {
+            _r.done();
+            return;
+        }
+        if ( _r.next_lib_idx < _r.all_libs.length ) {
+            _r.run_test( _r.all_tests[_r.next_test_idx], _r.all_libs[_r.next_lib_idx++] );
+        }
+    },
+    skip_test: function() {
+        _r._next_lib_idx = 0;
+        _r.next_test_idx++;
+        _r.run_next();
+    },
+    update_counts: function() {
+        $("#qunit-testresult .passed").text(_r.passed);
+        $("#qunit-testresult .failed").text(_r.failed);
+        $("#qunit-testresult .total").text(_r.total);
+        var banner_class = "qunit-pass";
+        if ( _r.failed ) {
+            banner_class = "qunit-fail";
+        }
+        _r.test_banner.attr("class",banner_class);
+    },
+    run_test: function(test,lib) {
+        $("#qunit-testresult .line1").text("Running test: " + test + ", lib: " + lib + "...");
+        _r.cur_test = test;
+        _r.cur_lib = lib;
+
+        var url = "/dev/tests/"+test+"/"+lib;
+        var li = $("<li>");
+        li.attr("id","test-"+test+"-"+lib);
+        _r.current_li = li;
+        _r.test_container.append(li);
+
+        var strong = $("<strong>");
+        li.append(strong);
+
+        var module_name = $("<span>");
+        module_name.addClass("module-name");
+        module_name.text(test + "-" + lib);
+        strong.append(module_name);
+
+        strong.append(": ");
+
+        var counts = $("<span>");
+        counts.addClass("counts");
+        counts.text("Running...");
+        strong.append(counts);
+
+        var iframe = $("<iframe>");
+        li.append(iframe);
+        _r.current_iframe = iframe;
+
+        iframe.hide();
+        iframe.attr("src",url);
+
+
+        iframe.load(function () {
+            _r.poll_iframe();
+        });
+        strong.click(function () {
+            iframe.toggle();
+        })
+    },
+    done: function () {
+        var end_time = new Date().getTime();
+        var ms = Math.round(end_time - _r.start_time);
+        $("#qunit-testresult .line1").text("Tests completed in " + ms + " milliseconds (" + _r.test_time + " milliseconds in tests).");
+        $("#qunit-filter-pass").removeAttr("disabled");
+    },
+    poll_iframe: function () {
+        var iframe = _r.current_iframe;
+        var content = iframe.contents();
+
+        var notests = content.find("#notests");
+        if( notests.size() > 0 ) {
+            _r.current_li
+                .find(".counts").text("No tests defined for " + _r.cur_test).end()
+                .find("iframe").remove();
+            _r.skip_test();
+            return;
+        }
+
+        var results = content.find("#qunit-testresult");
+
+        if ( results.size() == 0 ) {
+            setTimeout(_r.poll_iframe, 10);
+            return;
+        }
+
+        var passed_i = results.find(".passed");
+        var total_i  = results.find(".total");
+        var failed_i = results.find(".failed");
+
+        var tct = passed_i.size() + total_i.size() + failed_i.size();
+
+        if ( tct != 3 ) {
+            setTimeout(_r.poll_iframe, 10);
+            return;
+        }
+
+        _r.passed += parseInt( passed_i.text(), 10 );
+        _r.failed += parseInt( failed_i.text(), 10 );
+        _r.total  += parseInt( total_i.text(),  10 );
+        _r.update_counts();
+
+        var match_result = /in ([0-9]+) millisecond/.exec(results.text());
+        _r.test_time += parseInt( match_result[1], 10 );
+
+        var nodes = content.find("#qunit-tests > li");
+        nodes.detach();
+        _r.test_container.append(nodes);
+        nodes.each( function(_,node_d) {
+            var node = $(node_d);
+            node.addClass("test-"+_r.cur_test);
+            node.addClass("lib-"+_r.cur_lib);
+            node.addClass("testlib-"+_r.cur_test+"-"+_r.cur_lib);
+            node.attr("id",node.attr("id")+"-"+_r.cur_test+"-"+_r.cur_lib)
+            var element = node.find(".module-name");
+            var lib = $("<span class='lib-type'>");
+            lib.text(" (" +_r.cur_test + "/" + _r.cur_lib + ")");
+            element.append(lib);
+        });
+        _r.current_li.remove();
+        _r.run_next();
+    },
+    hide_passed: function (hide) {
+        _r.test_container.find("> li").show();
+        if ( hide ) {
+            _r.test_container.find("> li.pass").hide();
+        }
+    }
+}
+
+function register_all_tests(t) {
+    _r.all_tests = _r.all_tests.concat(t);
+}
+
+$(function () {
+    _r.init();
+    $("#qunit-userAgent").text( navigator.userAgent );
+    $("#qunit-filter-pass").change( function() { _r.hide_passed( this.checked ) })
+    _r.run_next();
+});
diff -r b79f5e330c01 -r c7966d7a04db htdocs/stc/tests/qunit-all.css
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/stc/tests/qunit-all.css	Thu Feb 24 13:21:25 2011 +0800
@@ -0,0 +1,4 @@
+#qunit-tests > li .module-name .lib-type {
+    color: #111;
+    font-size: .85em;
+}
\ No newline at end of file
diff -r b79f5e330c01 -r c7966d7a04db views/dev/tests-all.tt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/views/dev/tests-all.tt	Thu Feb 24 13:21:25 2011 +0800
@@ -0,0 +1,25 @@
+[%-
+    # it's all right to require jquery here because the other tests load up in a sandbox
+    # and the different js library versions can't interfere with one another
+    dw.need_res( { group => "jquery" }, "stc/tests/qunit.css", "stc/tests/qunit-all.css", "js/tests/qunit-all.js" );
+    CALL dw.active_resource_group( "jquery" );
+    sections.head = BLOCK -%]
+<script type="text/javascript">
+[%- IF all_tests -%]
+register_all_tests([ [% FOREACH test IN all_tests; UNLESS loop.first %],[% END %]"[% test %]"[% END %] ]);
+[%- ELSE -%]
+register_all_tests([ "[% test %]" ]);
+[%- END -%]
+</script>
+[%- END -%]
+
+<h1 id="qunit-header">[%- IF all_tests -%]
+All Tests
+[%- ELSE -%]
+All Libraries for [% test | html %]
+[%- END -%]</h1>
+<h2 id="qunit-banner"></h2>
+<div id="qunit-testrunner-toolbar"><input type="checkbox" id="qunit-filter-pass"/><label for="qunit-filter-pass">Hide passed tests</label></div>
+<h2 id="qunit-userAgent"></h2>
+<p id="qunit-testresult" class="result"><span class="line1"></span><br/><span class="line2"><span class="passed">0</span> test(s) of <span class="total">0</span> passed, <span class="failed">0</span> failed.</span></p>
+<ol id="qunit-tests"></ol>
diff -r b79f5e330c01 -r c7966d7a04db views/dev/tests.tt
--- a/views/dev/tests.tt	Thu Feb 24 12:08:50 2011 +0800
+++ b/views/dev/tests.tt	Thu Feb 24 13:21:25 2011 +0800
@@ -65,4 +65,5 @@ if ( lib && ! location.search ) {
     </div>
 [% ELSE %]
     <h1 id="qunit-header">No tests for [% testname %]</h1>
+    <ol id="notests"></ol>
 [%- END -%]
--------------------------------------------------------------------------------