1/* 2 * Copyright (c) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31function RebaselineQueue() 32{ 33 this._selectNode = $('queue-select'); 34 this._rebaselineButtonNode = $('rebaseline-queue'); 35 this._toggleNode = $('toggle-queue'); 36 this._removeSelectionButtonNode = $('remove-queue-selection'); 37 38 this._inProgressRebaselineCount = 0; 39 40 var self = this; 41 $('add-to-rebaseline-queue').addEventListener( 42 'click', function() { self.addCurrentTest(); }); 43 this._selectNode.addEventListener('change', updateState); 44 this._removeSelectionButtonNode.addEventListener( 45 'click', function() { self._removeSelection(); }); 46 this._rebaselineButtonNode.addEventListener( 47 'click', function() { self.rebaseline(); }); 48 this._toggleNode.addEventListener( 49 'click', function() { toggle('queue'); }); 50} 51 52RebaselineQueue.prototype.updateState = function() 53{ 54 var testName = getSelectedTest(); 55 56 var state = results.tests[testName].state; 57 $('add-to-rebaseline-queue').disabled = state != STATE_NEEDS_REBASELINE; 58 59 var queueLength = this._selectNode.options.length; 60 if (this._inProgressRebaselineCount > 0) { 61 this._rebaselineButtonNode.disabled = true; 62 this._rebaselineButtonNode.textContent = 63 'Rebaseline in progress (' + this._inProgressRebaselineCount + 64 ' tests left)'; 65 } else if (queueLength == 0) { 66 this._rebaselineButtonNode.disabled = true; 67 this._rebaselineButtonNode.textContent = 'Rebaseline queue'; 68 this._toggleNode.textContent = 'Queue'; 69 } else { 70 this._rebaselineButtonNode.disabled = false; 71 this._rebaselineButtonNode.textContent = 72 'Rebaseline queue (' + queueLength + ' tests)'; 73 this._toggleNode.textContent = 'Queue (' + queueLength + ' tests)'; 74 } 75 this._removeSelectionButtonNode.disabled = 76 this._selectNode.selectedIndex == -1; 77}; 78 79RebaselineQueue.prototype.addCurrentTest = function() 80{ 81 var testName = getSelectedTest(); 82 var test = results.tests[testName]; 83 84 if (test.state != STATE_NEEDS_REBASELINE) { 85 log('Cannot add test with state "' + test.state + '" to queue.', 86 log.WARNING); 87 return; 88 } 89 90 var queueOption = document.createElement('option'); 91 queueOption.value = testName; 92 queueOption.textContent = testName; 93 this._selectNode.appendChild(queueOption); 94 test.state = STATE_IN_QUEUE; 95 updateState(); 96}; 97 98RebaselineQueue.prototype.removeCurrentTest = function() 99{ 100 this._removeTest(getSelectedTest()); 101}; 102 103RebaselineQueue.prototype._removeSelection = function() 104{ 105 if (this._selectNode.selectedIndex == -1) 106 return; 107 108 this._removeTest( 109 this._selectNode.options[this._selectNode.selectedIndex].value); 110}; 111 112RebaselineQueue.prototype._removeTest = function(testName) 113{ 114 var queueOption = this._selectNode.firstChild; 115 116 while (queueOption && queueOption.value != testName) { 117 queueOption = queueOption.nextSibling; 118 } 119 120 if (!queueOption) 121 return; 122 123 this._selectNode.removeChild(queueOption); 124 var test = results.tests[testName]; 125 test.state = STATE_NEEDS_REBASELINE; 126 updateState(); 127}; 128 129RebaselineQueue.prototype.rebaseline = function() 130{ 131 var testNames = []; 132 for (var queueOption = this._selectNode.firstChild; 133 queueOption; 134 queueOption = queueOption.nextSibling) { 135 testNames.push(queueOption.value); 136 } 137 138 this._inProgressRebaselineCount = testNames.length; 139 updateState(); 140 141 testNames.forEach(this._rebaselineTest, this); 142}; 143 144RebaselineQueue.prototype._rebaselineTest = function(testName) 145{ 146 var baselineTarget = getSelectValue('baseline-target'); 147 var baselineMoveTo = getSelectValue('baseline-move-to'); 148 149 var xhr = new XMLHttpRequest(); 150 xhr.open('POST', 151 '/rebaseline?test=' + encodeURIComponent(testName) + 152 '&baseline-target=' + encodeURIComponent(baselineTarget) + 153 '&baseline-move-to=' + encodeURIComponent(baselineMoveTo)); 154 155 var self = this; 156 function handleResponse(logType, newState) { 157 log(xhr.responseText, logType); 158 self._removeTest(testName); 159 self._inProgressRebaselineCount--; 160 results.tests[testName].state = newState; 161 updateState(); 162 // If we're done with a set of rebaselines, regenerate the test menu 163 // (which is grouped by state) since test states have changed. 164 if (self._inProgressRebaselineCount == 0) { 165 selectDirectory(); 166 } 167 } 168 169 function handleSuccess() { 170 handleResponse(log.SUCCESS, STATE_REBASELINE_SUCCEEDED); 171 } 172 function handleFailure() { 173 handleResponse(log.ERROR, STATE_REBASELINE_FAILED); 174 } 175 176 xhr.addEventListener('load', function() { 177 if (xhr.status < 400) { 178 handleSuccess(); 179 } else { 180 handleFailure(); 181 } 182 }); 183 xhr.addEventListener('error', handleFailure); 184 185 xhr.send(); 186}; 187