15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2010 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var ALL_DIRECTORY_PATH = '[all]';
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var STATE_NEEDS_REBASELINE = 'needs_rebaseline';
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var STATE_REBASELINE_FAILED = 'rebaseline_failed';
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var STATE_REBASELINE_SUCCEEDED = 'rebaseline_succeeded';
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var STATE_IN_QUEUE = 'in_queue';
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var STATE_TO_DISPLAY_STATE = {};
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)STATE_TO_DISPLAY_STATE[STATE_NEEDS_REBASELINE] = 'Needs rebaseline';
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)STATE_TO_DISPLAY_STATE[STATE_REBASELINE_FAILED] = 'Rebaseline failed';
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)STATE_TO_DISPLAY_STATE[STATE_REBASELINE_SUCCEEDED] = 'Rebaseline succeeded';
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)STATE_TO_DISPLAY_STATE[STATE_IN_QUEUE] = 'In queue';
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var results;
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var testsByFailureType = {};
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var testsByDirectory = {};
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var selectedTests = [];
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var loupe;
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var queue;
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var shouldSortTestsByMetric = false;
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function main()
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('failure-type-selector').addEventListener('change', selectFailureType);
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('directory-selector').addEventListener('change', selectDirectory);
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('test-selector').addEventListener('change', selectTest);
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('next-test').addEventListener('click', nextTest);
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('previous-test').addEventListener('click', previousTest);
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('toggle-log').addEventListener('click', function() { toggle('log'); });
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    disableSorting();
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loupe = new Loupe();
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    queue = new RebaselineQueue();
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document.addEventListener('keydown', function(event) {
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        switch (event.keyIdentifier) {
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 'Left':
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            event.preventDefault();
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            previousTest();
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 'Right':
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            event.preventDefault();
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            nextTest();
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 'U+0051': // q
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            queue.addCurrentTest();
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 'U+0058': // x
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            queue.removeCurrentTest();
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case 'U+0052': // r
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            queue.rebaseline();
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadText('/platforms.json', function(text) {
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var platforms = JSON.parse(text);
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platforms.platforms.forEach(function(platform) {
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var platformOption = document.createElement('option');
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            platformOption.value = platform;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            platformOption.textContent = platform;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var targetOption = platformOption.cloneNode(true);
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            targetOption.selected = platform == platforms.defaultPlatform;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            $('baseline-target').appendChild(targetOption);
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            $('baseline-move-to').appendChild(platformOption.cloneNode(true));
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadText('/results.json', function(text) {
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        results = JSON.parse(text);
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        displayResults();
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Groups test results by failure type.
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function displayResults()
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var failureTypeSelector = $('failure-type-selector');
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var failureTypes = [];
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var testName in results.tests) {
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var test = results.tests[testName];
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (test.actual == 'PASS') {
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var failureType = test.actual + ' (expected ' + test.expected + ')';
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(failureType in testsByFailureType)) {
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testsByFailureType[failureType] = [];
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            failureTypes.push(failureType);
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        testsByFailureType[failureType].push(testName);
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Sort by number of failures
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    failureTypes.sort(function(a, b) {
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return testsByFailureType[b].length - testsByFailureType[a].length;
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var i = 0, failureType; failureType = failureTypes[i]; i++) {
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var failureTypeOption = document.createElement('option');
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        failureTypeOption.value = failureType;
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        failureTypeOption.textContent = failureType + ' - ' + testsByFailureType[failureType].length + ' tests';
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        failureTypeSelector.appendChild(failureTypeOption);
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selectFailureType();
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    document.body.className = '';
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function enableSorting()
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('toggle-sort').onclick = function() {
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        shouldSortTestsByMetric = !shouldSortTestsByMetric;
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Regenerates the list of tests; this alphabetizes, and
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // then re-sorts if we turned sorting on.
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        selectDirectory();
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('toggle-sort').classList.remove('disabled-control');
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function disableSorting()
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('toggle-sort').onclick = function() { return false; }
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('toggle-sort').classList.add('disabled-control');
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * For a given failure type, gets all the tests and groups them by directory
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (populating the directory selector with them).
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function selectFailureType()
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selectedFailureType = getSelectValue('failure-type-selector');
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var tests = testsByFailureType[selectedFailureType];
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    testsByDirectory = {}
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var displayDirectoryNamesByDirectory = {};
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var directories = [];
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Include a special option for all tests
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    testsByDirectory[ALL_DIRECTORY_PATH] = tests;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    displayDirectoryNamesByDirectory[ALL_DIRECTORY_PATH] = 'all';
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    directories.push(ALL_DIRECTORY_PATH);
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Roll up tests by ancestor directories
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    tests.forEach(function(test) {
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var pathPieces = test.split('/');
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var pathDirectories = pathPieces.slice(0, pathPieces.length -1);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var ancestorDirectory = '';
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pathDirectories.forEach(function(pathDirectory, index) {
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ancestorDirectory += pathDirectory + '/';
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!(ancestorDirectory in testsByDirectory)) {
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                testsByDirectory[ancestorDirectory] = [];
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var displayDirectoryName = new Array(index * 6).join(' ') + pathDirectory;
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                displayDirectoryNamesByDirectory[ancestorDirectory] = displayDirectoryName;
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                directories.push(ancestorDirectory);
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testsByDirectory[ancestorDirectory].push(test);
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    directories.sort();
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var directorySelector = $('directory-selector');
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    directorySelector.innerHTML = '';
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    directories.forEach(function(directory) {
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var directoryOption = document.createElement('option');
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        directoryOption.value = directory;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        directoryOption.innerHTML =
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            displayDirectoryNamesByDirectory[directory] + ' - ' +
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testsByDirectory[directory].length + ' tests';
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        directorySelector.appendChild(directoryOption);
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selectDirectory();
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * For a given failure type and directory and failure type, gets all the tests
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in that directory and populatest the test selector with them.
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function selectDirectory()
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var previouslySelectedTest = getSelectedTest();
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selectedDirectory = getSelectValue('directory-selector');
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selectedTests = testsByDirectory[selectedDirectory];
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selectedTests.sort();
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testsByState = {};
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selectedTests.forEach(function(testName) {
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var state = results.tests[testName].state;
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (state == STATE_IN_QUEUE) {
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            state = STATE_NEEDS_REBASELINE;
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(state in testsByState)) {
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testsByState[state] = [];
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        testsByState[state].push(testName);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var optionIndexByTest = {};
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testSelector = $('test-selector');
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    testSelector.innerHTML = '';
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selectedFailureType = getSelectValue('failure-type-selector');
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var sampleSelectedTest = testsByFailureType[selectedFailureType][0];
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selectedTypeIsSortable = 'metric' in results.tests[sampleSelectedTest];
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (selectedTypeIsSortable) {
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        enableSorting();
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (shouldSortTestsByMetric) {
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var state in testsByState) {
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                testsByState[state].sort(function(a, b) {
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return results.tests[b].metric - results.tests[a].metric
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                })
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        disableSorting();
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var state in testsByState) {
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var stateOption = document.createElement('option');
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stateOption.textContent = STATE_TO_DISPLAY_STATE[state];
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stateOption.disabled = true;
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        testSelector.appendChild(stateOption);
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        testsByState[state].forEach(function(testName) {
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var testOption = document.createElement('option');
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testOption.value = testName;
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var testDisplayName = testName;
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (testName.lastIndexOf(selectedDirectory) == 0) {
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                testDisplayName = testName.substring(selectedDirectory.length);
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testOption.innerHTML = '  ' + testDisplayName;
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            optionIndexByTest[testName] = testSelector.options.length;
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testSelector.appendChild(testOption);
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (previouslySelectedTest in optionIndexByTest) {
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        testSelector.selectedIndex = optionIndexByTest[previouslySelectedTest];
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (STATE_NEEDS_REBASELINE in testsByState) {
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        testSelector.selectedIndex =
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            optionIndexByTest[testsByState[STATE_NEEDS_REBASELINE][0]];
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        selectTest();
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        testSelector.selectedIndex = 1;
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        selectTest();
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selectTest();
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function getSelectedTest()
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return getSelectValue('test-selector');
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function selectTest()
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var selectedTest = getSelectedTest();
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (results.tests[selectedTest].actual.indexOf('IMAGE') != -1) {
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        $('image-outputs').style.display = '';
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        displayImageResults(selectedTest);
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        $('image-outputs').style.display = 'none';
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (results.tests[selectedTest].actual.indexOf('TEXT') != -1) {
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        $('text-outputs').style.display = '';
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        displayTextResults(selectedTest);
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        $('text-outputs').style.display = 'none';
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var currentBaselines = $('current-baselines');
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    currentBaselines.textContent = '';
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var baselines = results.tests[selectedTest].baselines;
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testName = selectedTest.split('.').slice(0, -1).join('.');
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getSortedKeys(baselines).forEach(function(platform, i) {
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (i != 0) {
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            currentBaselines.appendChild(document.createTextNode('; '));
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var platformName = document.createElement('span');
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformName.className = 'platform';
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        platformName.textContent = platform;
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentBaselines.appendChild(platformName);
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentBaselines.appendChild(document.createTextNode(' ('));
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        getSortedKeys(baselines[platform]).forEach(function(extension, j) {
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (j != 0) {
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                currentBaselines.appendChild(document.createTextNode(', '));
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var link = document.createElement('a');
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var baselinePath = '';
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (platform != 'base') {
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                baselinePath += 'platform/' + platform + '/';
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            baselinePath += testName + '-expected' + extension;
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            link.href = getTracUrl(baselinePath);
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (extension == '.checksum') {
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                link.textContent = 'chk';
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else {
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                link.textContent = extension.substring(1);
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            link.target = '_blank';
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (baselines[platform][extension]) {
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                link.className = 'was-used-for-test';
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            currentBaselines.appendChild(link);
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentBaselines.appendChild(document.createTextNode(')'));
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateState();
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loupe.hide();
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    prefetchNextImageTest();
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function prefetchNextImageTest()
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testSelector = $('test-selector');
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (testSelector.selectedIndex == testSelector.options.length - 1) {
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var nextTest = testSelector.options[testSelector.selectedIndex + 1].value;
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (results.tests[nextTest].actual.indexOf('IMAGE') != -1) {
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        new Image().src = getTestResultUrl(nextTest, 'expected-image');
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        new Image().src = getTestResultUrl(nextTest, 'actual-image');
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function updateState()
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testName = getSelectedTest();
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testIndex = selectedTests.indexOf(testName);
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testCount = selectedTests.length
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('test-index').textContent = testIndex + 1;
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('test-count').textContent = testCount;
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('next-test').disabled = testIndex == testCount - 1;
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('previous-test').disabled = testIndex == 0;
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('test-link').href = getTracUrl(testName);
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var state = results.tests[testName].state;
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('state').className = state;
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('state').innerHTML = STATE_TO_DISPLAY_STATE[state];
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    queue.updateState();
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function getTestResultUrl(testName, mode)
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return '/test_result?test=' + testName + '&mode=' + mode;
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var currentExpectedImageTest;
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var currentActualImageTest;
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function displayImageResults(testName)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (currentExpectedImageTest == currentActualImageTest
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        && currentExpectedImageTest == testName) {
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function displayImageResult(mode, callback) {
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var image = $(mode);
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        image.className = 'loading';
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        image.src = getTestResultUrl(testName, mode);
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        image.onload = function() {
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            image.className = '';
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            callback();
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            updateImageDiff();
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    displayImageResult(
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        'expected-image',
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function() { currentExpectedImageTest = testName; });
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    displayImageResult(
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        'actual-image',
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function() { currentActualImageTest = testName; });
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('diff-canvas').className = 'loading';
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('diff-canvas').style.display = '';
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    $('diff-checksum').style.display = 'none';
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Computes a graphical a diff between the expected and actual images by
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * rendering each to a canvas, getting the image data, and comparing the RGBA
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * components of each pixel. The output is put into the diff canvas, with
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * identical pixels appearing at 12.5% opacity and different pixels being
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * highlighted in red.
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function updateImageDiff() {
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (currentExpectedImageTest != currentActualImageTest)
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var expectedImage = $('expected-image');
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var actualImage = $('actual-image');
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function getImageData(image) {
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var imageCanvas = document.createElement('canvas');
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        imageCanvas.width = image.width;
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        imageCanvas.height = image.height;
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        imageCanvasContext = imageCanvas.getContext('2d');
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        imageCanvasContext.fillStyle = 'rgba(255, 255, 255, 1)';
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        imageCanvasContext.fillRect(
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            0, 0, image.width, image.height);
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        imageCanvasContext.drawImage(image, 0, 0);
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return imageCanvasContext.getImageData(
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            0, 0, image.width, image.height);
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var expectedImageData = getImageData(expectedImage);
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var actualImageData = getImageData(actualImage);
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var diffCanvas = $('diff-canvas');
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var diffCanvasContext = diffCanvas.getContext('2d');
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var diffImageData =
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        diffCanvasContext.createImageData(diffCanvas.width, diffCanvas.height);
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Avoiding property lookups for all these during the per-pixel loop below
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // provides a significant performance benefit.
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var expectedWidth = expectedImage.width;
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var expectedHeight = expectedImage.height;
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var expected = expectedImageData.data;
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var actualWidth = actualImage.width;
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var actual = actualImageData.data;
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var diffWidth = diffImageData.width;
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var diff = diffImageData.data;
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var hadDiff = false;
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (var x = 0; x < expectedWidth; x++) {
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var y = 0; y < expectedHeight; y++) {
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var expectedOffset = (y * expectedWidth + x) * 4;
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var actualOffset = (y * actualWidth + x) * 4;
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var diffOffset = (y * diffWidth + x) * 4;
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (expected[expectedOffset] != actual[actualOffset] ||
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expected[expectedOffset + 1] != actual[actualOffset + 1] ||
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expected[expectedOffset + 2] != actual[actualOffset + 2] ||
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expected[expectedOffset + 3] != actual[actualOffset + 3]) {
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                hadDiff = true;
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                diff[diffOffset] = 255;
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                diff[diffOffset + 1] = 0;
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                diff[diffOffset + 2] = 0;
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                diff[diffOffset + 3] = 255;
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else {
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                diff[diffOffset] = expected[expectedOffset];
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                diff[diffOffset + 1] = expected[expectedOffset + 1];
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                diff[diffOffset + 2] = expected[expectedOffset + 2];
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                diff[diffOffset + 3] = 32;
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    diffCanvasContext.putImageData(
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        diffImageData,
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        0, 0,
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        0, 0,
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        diffImageData.width, diffImageData.height);
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    diffCanvas.className = '';
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hadDiff) {
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        diffCanvas.style.display = 'none';
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        $('diff-checksum').style.display = '';
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        loadTextResult(currentExpectedImageTest, 'expected-checksum');
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        loadTextResult(currentExpectedImageTest, 'actual-checksum');
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function loadTextResult(testName, mode, responseIsHtml)
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadText(getTestResultUrl(testName, mode), function(text) {
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (responseIsHtml) {
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            $(mode).innerHTML = text;
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            $(mode).textContent = text;
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    });
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function displayTextResults(testName)
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadTextResult(testName, 'expected-text');
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadTextResult(testName, 'actual-text');
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    loadTextResult(testName, 'diff-text-pretty', true);
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function nextTest()
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testSelector = $('test-selector');
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var nextTestIndex = testSelector.selectedIndex + 1;
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (nextTestIndex == testSelector.options.length) {
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (testSelector.options[nextTestIndex].disabled) {
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            nextTestIndex++;
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testSelector.selectedIndex = nextTestIndex;
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            selectTest();
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function previousTest()
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var testSelector = $('test-selector');
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var previousTestIndex = testSelector.selectedIndex - 1;
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (previousTestIndex == -1) {
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (testSelector.options[previousTestIndex].disabled) {
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            previousTestIndex--;
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            testSelector.selectedIndex = previousTestIndex;
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            selectTest();
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)window.addEventListener('DOMContentLoaded', main);
578