head.ready(function(){ var redrawTestrun = function(testrun) { // rerender the suite based on the updated data testrun.html(Mustache.to_html("\ \ \ Test Run Started [{{timestamp}}] - {{status}} \ {{#running}} \ {{currentTest}} \ {{/running}} \ \ \ {{testCount}} total test(s): \ {{#hasfailures}} \ {{failedCount}} failure(s) \ {{#showfaults}} \ Hide Failures \ {{/showfaults}} \ {{^showfaults}} \ Show Failures \ {{/showfaults}} \ {{/hasfailures}} \ {{^hasfailures}} \ no failures \ {{/hasfailures}} \ \ {{#showfaults}} \ \ \ {{#faults}} \ \ {{test}} \ {{detail}} \ \ {{/faults}} \ \ {{#showfaultdetail}} \ {{faultdetail}} \ {{/showfaultdetail}} \ \ {{/showfaults}} \ ", testrun.data())); }; $('testruns').delegate('a.showFaults', 'click', function(){ var testrun = $(this).closest('testrun'); testrun.data().showfaults = true; redrawTestrun(testrun); return false; }); $('testruns').delegate('a.hideFaults', 'click', function(){ var testrun = $(this).closest('testrun'); testrun.data().showfaults = false; redrawTestrun(testrun); return false; }); $('testruns').delegate('fault', 'click', function(){ var testrun = $(this).closest('testrun'); testrun.data().faultdetail = $(this).find('detail').html(); testrun.data().showfaultdetail = true; // mark only this fault as selected - TODO must be a better way to do this _.each(testrun.data().faults, function(fault) { fault.selected = false; }); var details = testrun.find('detail'); var matchingFault = _.detect(details, function(detail) { return $(detail).html() === testrun.data().faultdetail; }); var matchingFaultIdx = _.indexOf(details, matchingFault); testrun.data().faults[matchingFaultIdx].selected = true; redrawTestrun(testrun); return false; }); // TODO don't assume localhost var socket = new WebSocket('ws://localhost:9021/'); var suites = {}; var templates = { "Test::Unit::UI::TestRunnerMediator::STARTED": "[{{timestamp}}]Test Suite Started", "Test::Unit::TestCase::STARTED": "[{{timestamp}}]Test Started: {{args}}", "FAULT": "[{{timestamp}}]{{args}}", "Test::Unit::TestCase::FINISHED": "[{{timestamp}}]Test Completed: {{args}}", "Test::Unit::UI::TestRunnerMediator::FINISHED": "[{{timestamp}}]Test Suite Completed in {{args}} seconds" }; socket.onopen = function (e) { // should indicate that we're connected }; socket.onclose = function (e) { // should indicate that we're disconnected and maybe try to reconnect }; socket.onmessage = function(jsonMessage) { if (jsonMessage && jsonMessage.data) { var message = $.parseJSON(jsonMessage.data); if (_.isEqual(message, ['backfilling'])) { $('appstatus').attr('class', 'backfilling'); } else if (_.isEqual(message,['realtime'])) { $('appstatus').attr('class', 'realtime'); } else { // append message to event log message.timestamp = new Date(message.milliseconds).toLocaleTimeString(); var template = templates[message.event]; $('eventlog') .append(Mustache.to_html(template, message)) .scrollTop($('eventlog').attr('scrollHeight') - $('eventlog').height()); // find or create the corresponding suite var guid = message.guid; if ($('#' + guid).length == 0) { $('testruns').prepend(''); } // update its data based on the event var testrun = $('#' + guid); var testrunData = testrun.data(); if (message.event === "Test::Unit::UI::TestRunnerMediator::STARTED") { testrunData.guid = guid; testrunData.timestamp = new Date(message.milliseconds).toLocaleTimeString(); testrunData.status = 'Initializing'; testrunData.testCount = 0; testrunData.failedCount = 0; testrunData.hasfailures = false; testrunData.faults = []; testrunData.showfaults = false; } else if (message.event === "Test::Unit::TestCase::STARTED") { testrunData.status = 'Running'; testrunData.currentTest = message.args; testrunData.running = true; } else if (message.event === "FAULT") { testrunData.failedCount += 1; testrunData.hasfailures = true; testrunData.faults.push({test: testrunData.currentTest, detail: message.args}); } else if (message.event === "Test::Unit::TestCase::FINISHED") { testrunData.running = false; testrunData.testCount += 1; } else if (message.event === "Test::Unit::UI::TestRunnerMediator::FINISHED") { if (testrunData.failedCount == 0) { testrunData.status = 'Success'; } else { testrunData.status = 'Failed'; } } redrawTestrun(testrun); } } }; });