|
What this is
Other links
The source code
/*
* Copyright 2004 ThoughtWorks, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
passColor = "#cfffcf";
failColor = "#ffcfcf";
workingColor = "#DEE7EC";
// The current row in the list of commands (test script)
currentCommandRow = 0;
inputTableRows = null;
// The current row in the list of tests (test suite)
currentTestRow = 0;
// Whether or not the jsFT should run all tests in the suite
runAllTests = false;
// Whether or not the current test has any errors;
testFailed = false;
suiteFailed = false;
// Test Suite name got from query string
testSuiteName = "";
// Holds variables that are stored in a script
storedVars = new Object();
// Holds the handlers for each command.
commandHandlers = null;
// The number of tests run
numTestPasses = 0;
// The number of tests that have failed
numTestFailures = 0;
// The number of commands which have passed
numCommandPasses = 0;
// The number of commands which have failed
numCommandFailures = 0;
// The number of commands which have caused errors (element not found)
numCommandErrors = 0;
// The time that the test was started.
startTime = null;
// The current time.
currentTime = null;
// An simple enum for failureType
ERROR = 0;
FAILURE = 1;
runInterval = 0;
function setRunInterval() {
runInterval = this.value;
}
function continueCurrentTest() {
testLoop.finishCommandExecution()
}
function getSuiteFrame() {
return document.getElementById('testSuiteFrame');
}
function getTestFrame(){
return document.getElementById('testFrame');
}
function loadAndRunIfAuto() {
loadSuiteFrame();
}
function loadSuiteFrame() {
var testAppFrame = document.getElementById('myiframe');
browserbot = new BrowserBot(testAppFrame);
selenium = new Selenium(browserbot);
registerCommandHandlers()
document.getElementById("modeRun").onclick = setRunInterval;
document.getElementById('modeWalk').onclick = setRunInterval;
document.getElementById('modeStep').onclick = setRunInterval;
document.getElementById('continueTest').onclick = continueCurrentTest;
testSuiteName = getQueryStringTestName();
if( testSuiteName != "" ) {
addLoadListener(getSuiteFrame(), loadTestFrame);
getSuiteFrame().src = testSuiteName;
} else {
loadTestFrame();
}
//testAppFrame.src = "http://selenium.thoughtworks.com";
}
function loadTestFrame() {
removeLoadListener(getSuiteFrame(), loadTestFrame);
suiteTable = getSuiteFrame().contentWindow.document.getElementsByTagName("table")[0];
// Add an onclick function to each link in the suite table
for(rowNum = 1;rowNum < suiteTable.rows.length; rowNum++) {
addOnclick(suiteTable, rowNum);
}
if (isAutomatedRun())
startTestSuite();
else {
testLink = suiteTable.rows[currentTestRow+1].cells[0].getElementsByTagName("a")[0];
getTestFrame().src = testLink.href;
}
}
// Adds an onclick function to the link in the given row in suite table.
// This function checks whether the test has already been run and the data is
// stored. If the data is stored, it sets the test frame to be the stored data.
// Otherwise, it loads the fresh page.
function addOnclick(suiteTable, rowNum) {
aLink = suiteTable.rows[rowNum].cells[0].getElementsByTagName("a")[0];
aLink.onclick = function(eventObj) {
srcObj = null;
// For mozilla-like browsers
if(eventObj)
srcObj = eventObj.target;
// For IE-like browsers
else if (getSuiteFrame().contentWindow.event)
srcObj = getSuiteFrame().contentWindow.event.srcElement;
// The target row
row = srcObj.parentNode.parentNode.rowIndex;
// If the row has a stored results table, use that
if(suiteTable.rows[row].cells[1]) {
getTestFrame().contentWindow.document.body.innerHTML = getText(suiteTable.rows[row].cells[1]);
}
// Otherwise, just open up the fresh page.
else {
getTestFrame().src = suiteTable.rows[row].cells[0].getElementsByTagName("a")[0].href;
}
return false;
};
}
function getQueryStringTestName() {
testName = "";
myVars = location.search.substr(1).split('&');
for (var i =0;i < myVars.length; i++) {
nameVal = myVars[i].split('=')
if( nameVal[0] == "test" ) {
testName="/" + nameVal[1];
}
}
return testName;
}
function isAutomatedRun() {
myVars = location.search.substr(1).split('&');
for (var i =0;i < myVars.length; i++) {
nameVal = myVars[i].split('=')
if( nameVal[0] == "auto" && nameVal[1].toLowerCase() == "true" )
return true;
}
return false;
}
function resetMetrics() {
numTestPasses = 0;
numTestFailures = 0;
numCommandPasses = 0;
numCommandFailures = 0;
numCommandErrors = 0;
startTime = new Date().getTime();
}
function runSingleTest() {
runAllTests = false;
resetMetrics();
startTest();
}
function startTest() {
removeLoadListener(getTestFrame(), startTest);
getTestFrame().contentWindow.scrollTo(0,0);
inputTable = (getTestFrame().contentWindow.document.getElementsByTagName("table"))[0];
inputTableRows = inputTable.rows;
currentCommandRow = 0;
testFailed = false;
storedVars = new Object();
clearRowColours();
testLoop = initialiseTestLoop();
testLoop.start();
}
function clearRowColours() {
for (var i = 0; i <= inputTableRows.length - 1; i++) {
inputTableRows[i].bgColor = "white";
}
}
function startTestSuite() {
resetMetrics();
currentTestRow = 0;
runAllTests = true;
suiteFailed = false;
runNextTest();
}
function runNextTest() {
if (!runAllTests)
return;
// Scroll the suite frame down by 25 pixels once we get past the first cell.
if(currentTestRow >= 1)
getSuiteFrame().contentWindow.scrollBy(0,25);
suiteTable = (getSuiteFrame().contentWindow.document.getElementsByTagName("table"))[0];
// Do not change the row color of the first row
if(currentTestRow > 0) {
// Make the previous row green or red depending if the test passed or failed
if(testFailed)
setCellColor(suiteTable.rows, currentTestRow, 0, failColor);
else
setCellColor(suiteTable.rows, currentTestRow, 0, passColor);
// Set the results from the previous test run
setResultsData(suiteTable, currentTestRow);
}
currentTestRow++;
// If we are done with all of the tests, set the title bar as pass or fail
if(currentTestRow >= suiteTable.rows.length) {
if(suiteFailed)
setCellColor(suiteTable.rows, 0, 0, failColor);
else
setCellColor(suiteTable.rows, 0, 0, passColor);
// If this is an automated run (i.e., build script), then submit
// the test results by posting to a form
if (isAutomatedRun())
postTestResults(suiteFailed, suiteTable);
}
else {
// Make the current row blue
setCellColor(suiteTable.rows, currentTestRow, 0, workingColor);
testLink = suiteTable.rows[currentTestRow].cells[0].getElementsByTagName("a")[0];
addLoadListener(getTestFrame(), startTest);
getTestFrame().src = testLink.href;
}
}
function setCellColor(tableRows, row, col, colorStr) {
tableRows[row].cells[col].bgColor = colorStr;
}
// Sets the results from a test into a hidden column on the suite table. So,
// for each tests, the second column is set to the HTML from the test table.
function setResultsData(suiteTable, row) {
// Create a text node of the test table
tableContents = suiteTable.ownerDocument.createTextNode(getTestFrame().contentWindow.document.body.innerHTML);
new_column = suiteTable.ownerDocument.createElement("td");
new_column.appendChild(tableContents);
// Set the column to be invisible
new_column.style.cssText = "display: none;";
// Add the invisible column
suiteTable.rows[row].appendChild(new_column);
}
// Post the results to /postResults. The parameters are:
// result: passed/failed depending on whether the suite passed or failed
// totalTime: the total running time in seconds for the suite.
//
// numTestPasses: the total number of tests which passed.
// numTestFailures: the total number of tests which failed.
//
// numCommandPasses: the total number of commands which passed.
// numCommandFailures: the total number of commands which failed.
// numCommandErrors: the total number of commands which errored.
//
// suite: the suite table, including the hidden column of test results
// testTable.1 to testTable.N: the individual test tables
function postTestResults(suiteFailed, suiteTable) {
form = document.createElement("form");
form.id = "resultsForm";
form.action = "/postResults"
form.method="post";
form.enctype="multipart/form-data"
resultInput = createInputField("result", suiteFailed == true ? "failed" : "passed");
form.appendChild(resultInput);
timeInput = createInputField("totalTime", Math.floor((currentTime - startTime) / 1000));
form.appendChild(timeInput);
testPassesInput = createInputField("numTestPasses", numTestPasses);
form.appendChild(testPassesInput);
testFailuresInput = createInputField("numTestFailures", numTestFailures);
form.appendChild(testFailuresInput);
commandPassesInput = createInputField("numCommandPasses", numCommandPasses);
form.appendChild(commandPassesInput);
commandFailuresInput = createInputField("numCommandFailures", numCommandFailures);
form.appendChild(commandFailuresInput);
commandErrorsInput = createInputField("numCommandErrors", numCommandErrors);
form.appendChild(commandErrorsInput);
suiteInput = createInputField("suite", escape(suiteTable.parentNode.innerHTML));
form.appendChild(suiteInput);
// Create an input for each test table. The inputs are named testTable.1, testTable.2, etc.
for (rowNum = 1;rowNum < suiteTable.rows.length;rowNum++) {
// If there is a second column, then add a new input
if (suiteTable.rows[rowNum].cells.length > 1) {
testInput = createInputField("testTable." + rowNum, escape(getText(suiteTable.rows[rowNum].cells[1])));
form.appendChild(testInput);
}
}
document.body.appendChild(form);
form.submit();
}
function createInputField(name, value) {
input = document.createElement("input");
input.type = "hidden";
input.name = name;
input.value = value;
return input;
}
function printMetrics() {
setText(document.getElementById("commandPasses"), numCommandPasses);
setText(document.getElementById("commandFailures"), numCommandFailures);
setText(document.getElementById("commandErrors"), numCommandErrors);
setText(document.getElementById("testRuns"), numTestPasses);
setText(document.getElementById("testFailures"), numTestFailures);
currentTime = new Date().getTime();
timeDiff = currentTime - startTime;
totalSecs = Math.floor(timeDiff / 1000);
minutes = Math.floor(totalSecs / 60);
seconds = totalSecs % 60;
setText(document.getElementById("elapsedTime"), pad(minutes)+":"+pad(seconds));
}
// Puts a leading 0 on num if it is less than 10
function pad (num) {
return (num > 9) ? num : "0" + num;
}
// Search through str and replace all variable references ${varName} with their
// value in storedVars.
function replaceVariables(str) {
//handle the case of ${userid}.toUpper
pattern = /\$\{(\w+)\}\.(.+)/
var variableIndex = str;
var variableFunction='';
if(pattern.test(str)) {
pieces = str.split('.');
variableIndex = pieces[0];
variableFunction = pieces[1];
}
regex = /\$\{(\w+)\}/g;
var variableValue = variableIndex.replace(regex, function(match, word) {
return storedVars[word];
});
if( variableFunction == '')
return variableValue;
else
{
return eval("variableValue."+ eval("variableFunction") + "()" )
}
}
// Register all of the built-in command handlers with the CommandHandlerFactory.
// TODO work out an easy way for people to register handlers without modifying the Selenium sources.
function registerCommandHandlers() {
commandFactory = new CommandHandlerFactory();
commandFactory.registerAll(selenium);
// These actions are overridden for fitrunner, as they still involve some FitRunner smarts,
// because of the wait/nowait behaviour modification. We need a generic solution to this.
commandFactory.registerAction("click", selenium.doClickWithOptionalWait);
}
function initialiseTestLoop() {
testLoop = new TestLoop(commandFactory);
testLoop.getCommandInterval = function() { return runInterval };
testLoop.firstCommand = nextCommand;
testLoop.nextCommand = nextCommand;
testLoop.commandStarted = commandStarted;
testLoop.commandComplete = commandComplete;
testLoop.commandError = commandError;
testLoop.testComplete = testComplete;
return testLoop
}
function nextCommand() {
if (currentCommandRow >= inputTableRows.length - 1) {
return null;
}
currentCommandRow++;
var commandName = getCellText(currentCommandRow, 0);
var target = replaceVariables(getCellText(currentCommandRow, 1));
var value = replaceVariables(getCellText(currentCommandRow, 2));
var command = new SeleniumCommand(commandName, target, value);
return command;
}
function commandStarted() {
// Make the current row blue
inputTableRows[currentCommandRow].bgColor = "#DEE7EC";
// Scroll the test frame down by 25 pixels once we get past the first 5 cells.
if(currentCommandRow >= 5)
getTestFrame().contentWindow.scrollBy(0,25);
printMetrics();
}
function commandComplete(result) {
if (result.failed) {
setRowFailed(result.failureMessage, FAILURE);
} else if (result.passed) {
setRowPassed();
} else {
setRowWhite();
}
}
function commandError(errorMessage) {
setRowFailed(errorMessage, ERROR);
}
function setRowWhite() {
inputTableRows[currentCommandRow].bgColor = "white";
}
function setRowPassed() {
numCommandPasses += 1;
// Set cell background to green
inputTableRows[currentCommandRow].bgColor = passColor;
}
function setRowFailed(errorMsg, failureType) {
if (failureType == ERROR)
numCommandErrors += 1;
else if (failureType == FAILURE)
numCommandFailures += 1;
// Set cell background to red
inputTableRows[currentCommandRow].bgColor = failColor;
// Set error message
inputTableRows[currentCommandRow].cells[2].innerHTML = errorMsg;
inputTableRows[currentCommandRow].title = errorMsg;
testFailed = true;
suiteFailed = true;
}
function testComplete() {
if(testFailed) {
inputTableRows[0].bgColor = failColor;
numTestFailures += 1;
}
else {
inputTableRows[0].bgColor = passColor;
numTestPasses += 1;
}
printMetrics();
window.setTimeout("runNextTest()", 1);
}
function getCellText(rowNumber, columnNumber) {
return getText(inputTableRows[rowNumber].cells[columnNumber]);
}
Selenium.prototype.doPause = function(waitTime) {
testLoop.pauseInterval = waitTime;
}
// Reads the text of the page and stores it in a variable with the name of the target
Selenium.prototype.doStoreValue = function(target) {
value = this.page().bodyText();
storedVars[target] = value;
}
Selenium.prototype.doClickWithOptionalWait = function(target, wait) {
this.doClick(target);
if(wait != "nowait") {
return SELENIUM_PROCESS_WAIT;
}
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.