summaryrefslogtreecommitdiff
path: root/tests/FunctionalTests/selenium/selenium-api.js
diff options
context:
space:
mode:
Diffstat (limited to 'tests/FunctionalTests/selenium/selenium-api.js')
-rw-r--r--tests/FunctionalTests/selenium/selenium-api.js731
1 files changed, 731 insertions, 0 deletions
diff --git a/tests/FunctionalTests/selenium/selenium-api.js b/tests/FunctionalTests/selenium/selenium-api.js
new file mode 100644
index 00000000..5d73e0fd
--- /dev/null
+++ b/tests/FunctionalTests/selenium/selenium-api.js
@@ -0,0 +1,731 @@
+/*
+ * 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.
+ *
+ */
+
+storedVars = new Object();
+
+function Selenium(browserbot) {
+ this.browserbot = browserbot;
+ this.optionLocatorFactory = new OptionLocatorFactory();
+ this.page = function() {
+ return browserbot.getCurrentPage();
+ };
+}
+
+Selenium.createForFrame = function(frame) {
+ return new Selenium(BrowserBot.createForFrame(frame));
+};
+
+/*
+ * Reset the browserbot when an error occurs..
+ */
+Selenium.prototype.reset = function() {
+ storedVars = new Object();
+ this.browserbot.selectWindow("null");
+};
+
+/*
+ * Click on the located element, and attach a callback to notify
+ * when the page is reloaded.
+ */
+Selenium.prototype.doModalDialogTest = function(returnValue) {
+ this.browserbot.doModalDialogTest(returnValue);
+};
+
+/*
+ * Click on the located element, and attach a callback to notify
+ * when the page is reloaded.
+ */
+Selenium.prototype.doClick = function(locator) {
+ var element = this.page().findElement(locator);
+ this.page().clickElement(element);
+};
+
+/**
+ * Overwrite the text in the located text element.
+ * TODO fail if it can't be typed into.
+ */
+Selenium.prototype.doType = function(locator, newText) {
+ var element = this.page().findElement(locator);
+ this.page().replaceText(element, newText);
+};
+
+Selenium.prototype.findToggleButton = function(locator) {
+ var element = this.page().findElement(locator);
+ if (element.checked == null) {
+ Assert.fail("Element " + locator + " is not a toggle-button.");
+ }
+ return element;
+}
+
+/**
+ * Check a toggle-button.
+ */
+Selenium.prototype.doCheck = function(locator) {
+ this.findToggleButton(locator).checked = true;
+};
+
+/**
+ * Uncheck a toggle-button.
+ */
+Selenium.prototype.doUncheck = function(locator) {
+ this.findToggleButton(locator).checked = false;
+};
+
+/**
+ * Select the option from the located select element.
+ */
+Selenium.prototype.doSelect = function(locator, optionLocator) {
+ var element = this.page().findElement(locator);
+ if (!("options" in element)) {
+ throw new SeleniumError("Specified element is not a Select (has no options)");
+ }
+ var locator = this.optionLocatorFactory.fromLocatorString(optionLocator);
+ var option = locator.findOption(element);
+ this.page().selectOption(element, option);
+};
+
+/*
+ * Open the browser to a new location.
+ */
+Selenium.prototype.doOpen = function(newLocation) {
+ this.browserbot.openLocation(newLocation);
+ return SELENIUM_PROCESS_WAIT;
+};
+
+/*
+ * Select the named window to be the active window.
+ */
+Selenium.prototype.doSelectWindow = function(windowName) {
+ this.browserbot.selectWindow(windowName);
+};
+
+/*
+ * Instruct Selenium to click Cancel on the next confirm dialog it encounters
+ */
+Selenium.prototype.doChooseCancelOnNextConfirmation = function() {
+ this.browserbot.cancelNextConfirmation();
+};
+
+/*
+ * Instruct Selenium what to answear on the next prompt dialog it encounters
+ */
+Selenium.prototype.doAnswerOnNextPrompt = function(answer) {
+ this.browserbot.setNextPromptResult(answer);
+};
+
+/*
+ * Simulate the browser back button
+ */
+Selenium.prototype.doGoBack = function() {
+ this.page().goBack();
+};
+
+/*
+ * Close the browser window or tab
+ */
+Selenium.prototype.doClose = function() {
+ this.page().close();
+};
+
+/*
+ * Explicitly fire an event
+ */
+Selenium.prototype.doFireEvent = function(locator, event) {
+ var element = this.page().findElement(locator);
+ triggerEvent(element, event, false);
+};
+
+/*
+ * Get an alert message, or fail if there were no alerts.
+ */
+Selenium.prototype.getAlert = function() {
+ if (!this.browserbot.hasAlerts()) {
+ Assert.fail("There were no alerts");
+ }
+ return this.browserbot.getNextAlert();
+};
+
+/*
+ * Get a confirmation message, or fail if there were no confirmations.
+ */
+Selenium.prototype.getConfirmation = function() {
+ if (!this.browserbot.hasConfirmations()) {
+ Assert.fail("There were no confirmations");
+ }
+ return this.browserbot.getNextConfirmation();
+};
+
+/*
+ * Get a prompt message, or fail if there were no prompts.
+ */
+Selenium.prototype.getPrompt = function() {
+ if (! this.browserbot.hasPrompts()) {
+ Assert.fail("There were no prompts");
+ }
+ return this.browserbot.getNextPrompt();
+};
+
+/*
+ * Get the location of the current page.
+ */
+Selenium.prototype.getAbsoluteLocation = function() {
+ return this.page().location;
+};
+
+/*
+ * Verify the location of the current page ends with the expected location.
+ * If a querystring is provided, this is checked as well.
+ */
+Selenium.prototype.assertLocation = function(expectedLocation) {
+ var docLocation = this.page().location;
+ var searchPos = expectedLocation.lastIndexOf('?');
+
+ if (searchPos == -1) {
+ Assert.matches('*' + expectedLocation, docLocation.pathname);
+ }
+ else {
+ var expectedPath = expectedLocation.substring(0, searchPos);
+ Assert.matches('*' + expectedPath, docLocation.pathname);
+
+ var expectedQueryString = expectedLocation.substring(searchPos);
+ Assert.equals(expectedQueryString, docLocation.search);
+ }
+};
+
+/*
+ * Get the title of the current page.
+ */
+Selenium.prototype.getTitle = function() {
+ return this.page().title();
+};
+
+
+/*
+ * Get the (trimmed) value of a form element.
+ * This is used to generate assertValue, verifyValue, ...
+ */
+Selenium.prototype.getValue = function(locator) {
+ var element = this.page().findElement(locator)
+ return getInputValue(element).trim();
+}
+
+/**
+ * Get the (trimmed) text of a form element.
+ * This is used to generate assertText, verifyText, ...
+ */
+Selenium.prototype.getText = function(locator) {
+ var element = this.page().findElement(locator);
+ return getText(element).trim();
+};
+
+/**
+ * Assert that a toggle-button is checked.
+ */
+Selenium.prototype.assertChecked = function(locator) {
+ var element = this.page().findElement(locator);
+ if (element.checked == null) {
+ Assert.fail("Element " + locator + " is not a toggle-button.");
+ }
+ if (! element.checked) {
+ Assert.fail("Element " + locator + " is not checked.");
+ }
+};
+
+/**
+ * Assert that a toggle-button is NOT checked.
+ */
+Selenium.prototype.assertNotChecked = function(locator) {
+ var element = this.page().findElement(locator);
+ if (element.checked == null) {
+ Assert.fail("Element " + locator + " is not a toggle-button.");
+ }
+ if (element.checked) {
+ Assert.fail("Element " + locator + " is checked.");
+ }
+};
+
+/*
+ * Return the text for a single cell within an HTML table.
+ * The table locator syntax is table.row.column.
+ */
+Selenium.prototype.getTable = function(tableLocator) {
+ // This regular expression matches "tableName.row.column"
+ // For example, "mytable.3.4"
+ pattern = /(.*)\.(\d+)\.(\d+)/;
+
+ if(!pattern.test(tableLocator)) {
+ throw new SeleniumError("Invalid target format. Correct format is tableName.rowNum.columnNum");
+ }
+
+ pieces = tableLocator.match(pattern);
+
+ tableName = pieces[1];
+ row = pieces[2];
+ col = pieces[3];
+
+ var table = this.page().findElement(tableName);
+ if (row > table.rows.length) {
+ Assert.fail("Cannot access row " + row + " - table has " + table.rows.length + " rows");
+ }
+ else if (col > table.rows[row].cells.length) {
+ Assert.fail("Cannot access column " + col + " - table row has " + table.rows[row].cells.length + " columns");
+ }
+ else {
+ actualContent = getText(table.rows[row].cells[col]);
+ return actualContent.trim();
+ }
+};
+
+/**
+ * Verify that the selected option satisfies the option locator.
+ */
+Selenium.prototype.assertSelected = function(target, optionLocator) {
+ var element = this.page().findElement(target);
+ var locator = this.optionLocatorFactory.fromLocatorString(optionLocator);
+ locator.assertSelected(element);
+};
+
+String.prototype.parseCSV = function() {
+ var values = this.replace(/\\,/g, "\n").split(",");
+ // Restore escaped commas
+ for (var i = 0; i < values.length; i++) {
+ values[i] = values[i].replace(/\n/g, ",").trim();
+ }
+ return values;
+};
+
+/**
+ * Verify the label of all of the options in the drop=down.
+ */
+Selenium.prototype.assertSelectOptions = function(target, options) {
+ var element = this.page().findElement(target);
+
+ var expectedOptionLabels = options.parseCSV();
+ Assert.equals("Wrong number of options", expectedOptionLabels.length, element.options.length);
+
+ for (var i = 0; i < element.options.length; i++) {
+ Assert.matches(expectedOptionLabels[i], element.options[i].text);
+ }
+};
+
+/**
+ * Get the value of an element attribute. The syntax for returning an element attribute
+ * is <element-locator>@attribute-name. Used to generate assert, verify, assertNot...
+ */
+Selenium.prototype.getAttribute = function(target) {
+ return this.page().findAttribute(target);
+};
+
+/*
+ * Asserts that the specified text is present in the page content.
+ */
+Selenium.prototype.assertTextPresent = function(expectedText) {
+ var allText = this.page().bodyText();
+
+ if(allText == "") {
+ Assert.fail("Page text not found");
+ } else if(allText.indexOf(expectedText) == -1) {
+ Assert.fail("'" + expectedText + "' not found in page text.");
+ }
+};
+
+/*
+ * Asserts that the specified text is NOT present in the page content.
+ */
+Selenium.prototype.assertTextNotPresent = function(unexpectedText) {
+ var allText = this.page().bodyText();
+
+ if(allText == "") {
+ Assert.fail("Page text not found");
+ } else if(allText.indexOf(unexpectedText) != -1) {
+ Assert.fail("'" + unexpectedText + "' was found in page text.");
+ }
+};
+
+/*
+ * Asserts that the specified element can be found.
+ */
+Selenium.prototype.assertElementPresent = function(locator) {
+ try {
+ this.page().findElement(locator);
+ } catch (e) {
+ Assert.fail("Element " + locator + " not found.");
+ }
+};
+
+/*
+ * Asserts that the specified element cannot be found.
+ */
+Selenium.prototype.assertElementNotPresent = function(locator) {
+ try {
+ this.page().findElement(locator);
+ }
+ catch (e) {
+ return;
+ }
+ Assert.fail("Element " + locator + " found.");
+};
+
+/*
+ * Asserts that the specified element is visible
+ */
+Selenium.prototype.assertVisible = function(locator) {
+ var element;
+ try {
+ element = this.page().findElement(locator);
+ } catch (e) {
+ Assert.fail("Element " + locator + " not present.");
+ }
+ if (! this.isVisible(element)) {
+ Assert.fail("Element " + locator + " not visible.");
+ }
+};
+
+/*
+ * Asserts that the specified element is visible
+ */
+Selenium.prototype.assertNotVisible = function(locator) {
+ var element;
+ try {
+ element = this.page().findElement(locator);
+ } catch (e) {
+ return;
+ }
+ if (this.isVisible(element)) {
+ Assert.fail("Element " + locator + " is visible.");
+ }
+};
+
+Selenium.prototype.isVisible = function(element) {
+ var visibility = this.getEffectiveStyleProperty(element, "visibility");
+ var isDisplayed = this.isDisplayed(element);
+ return (visibility != "hidden" && isDisplayed);
+};
+
+Selenium.prototype.getEffectiveStyleProperty = function(element, property) {
+ var effectiveStyle = this.getEffectiveStyle(element);
+ var propertyValue = effectiveStyle[property];
+ if (propertyValue == 'inherit' && element.parentNode.style) {
+ return this.getEffectiveStyleProperty(element.parentNode, property);
+ }
+ return propertyValue;
+};
+
+Selenium.prototype.isDisplayed = function(element) {
+ var display = this.getEffectiveStyleProperty(element, "display");
+ if (display == "none") return false;
+ if (element.parentNode.style) {
+ return this.isDisplayed(element.parentNode);
+ }
+ return true;
+};
+
+Selenium.prototype.getEffectiveStyle = function(element) {
+ if (element.style == undefined) {
+ return undefined; // not a styled element
+ }
+ var window = this.browserbot.getContentWindow();
+ if (window.getComputedStyle) {
+ // DOM-Level-2-CSS
+ return window.getComputedStyle(element, null);
+ }
+ if (element.currentStyle) {
+ // non-standard IE alternative
+ return element.currentStyle;
+ // TODO: this won't really work in a general sense, as
+ // currentStyle is not identical to getComputedStyle()
+ // ... but it's good enough for "visibility"
+ }
+ throw new SeleniumError("cannot determine effective stylesheet in this browser");
+};
+
+/**
+ * Asserts that the specified element accepts user input visible
+ */
+Selenium.prototype.assertEditable = function(locator) {
+ var element = this.page().findElement(locator);
+ if (element.value == undefined) {
+ Assert.fail("Element " + locator + " is not an input.");
+ }
+ if (element.disabled) {
+ Assert.fail("Element " + locator + " is disabled.");
+ }
+};
+
+/**
+ * Asserts that the specified element does not accept user input
+ */
+Selenium.prototype.assertNotEditable = function(locator) {
+ var element = this.page().findElement(locator);
+ if (element.value == undefined) {
+ return; // not an input
+ }
+ if (element.disabled == false) {
+ Assert.fail("Element " + locator + " is editable.");
+ }
+};
+
+ /*
+ * Return all buttons on the screen.
+ */
+Selenium.prototype.getAllButtons = function() {
+ return this.page().getAllButtons();
+};
+
+ /*
+ * Return all links on the screen.
+ */
+Selenium.prototype.getAllLinks = function() {
+ return this.page().getAllLinks();
+};
+
+ /*
+ * Return all fields on the screen.
+ */
+Selenium.prototype.getAllFields = function() {
+ return this.page().getAllFields();
+};
+
+/*
+ * Set the context for the current Test
+ */
+Selenium.prototype.doContext = function(context) {
+ return this.page().setContext(context);
+};
+
+/*
+ * Store the value of a form input in a variable
+ */
+Selenium.prototype.doStoreValue = function(target, varName) {
+ if (!varName) {
+ // Backward compatibility mode: read the ENTIRE text of the page
+ // and stores it in a variable with the name of the target
+ value = this.page().bodyText();
+ storedVars[target] = value;
+ return;
+ }
+ var element = this.page().findElement(target);
+ storedVars[varName] = getInputValue(element);
+};
+
+/*
+ * Store the text of an element in a variable
+ */
+Selenium.prototype.doStoreText = function(target, varName) {
+ var element = this.page().findElement(target);
+ storedVars[varName] = getText(element);
+};
+
+/*
+ * Store the value of an element attribute in a variable
+ */
+Selenium.prototype.doStoreAttribute = function(target, varName) {
+ storedVars[varName] = this.page().findAttribute(target);
+};
+
+/*
+ * Store the result of a literal value
+ */
+Selenium.prototype.doStore = function(value, varName) {
+ storedVars[varName] = value;
+};
+
+
+/*
+ * Wait for the target to have the specified value by polling.
+ * The polling is done in TestLoop.kickoffNextCommandExecution()
+ */
+Selenium.prototype.doWaitForValue = function (target, value) {
+ var e = this.page().findElement(target);
+ testLoop.waitForCondition = function () {
+ return (e.value == value);
+ };
+};
+
+/**
+ * Evaluate a parameter, performing javascript evaluation and variable substitution.
+ * If the string matches the pattern "javascript{ ... }", evaluate the string between the braces.
+ */
+Selenium.prototype.preprocessParameter = function(value) {
+ var match = value.match(/^javascript\{(.+)\}$/);
+ if (match && match[1]) {
+ return eval(match[1]).toString();
+ }
+ return this.replaceVariables(value);
+};
+
+/*
+ * Search through str and replace all variable references ${varName} with their
+ * value in storedVars.
+ */
+Selenium.prototype.replaceVariables = function(str) {
+ var stringResult = str;
+
+ // Find all of the matching variable references
+ var match = stringResult.match(/\$\{\w+\}/g);
+ if (!match) {
+ return stringResult;
+ }
+
+ // For each match, lookup the variable value, and replace if found
+ for (var i = 0; match && i < match.length; i++) {
+ var variable = match[i]; // The replacement variable, with ${}
+ var name = variable.substring(2, variable.length - 1); // The replacement variable without ${}
+ var replacement = storedVars[name];
+ if (replacement != undefined) {
+ stringResult = stringResult.replace(variable, replacement);
+ }
+ }
+ return stringResult;
+};
+
+
+/**
+ * Factory for creating "Option Locators".
+ * An OptionLocator is an object for dealing with Select options (e.g. for
+ * finding a specified option, or asserting that the selected option of
+ * Select element matches some condition.
+ * The type of locator returned by the factory depends on the locator string:
+ * label=<exp> (OptionLocatorByLabel)
+ * value=<exp> (OptionLocatorByValue)
+ * index=<exp> (OptionLocatorByIndex)
+ * id=<exp> (OptionLocatorById)
+ * <exp> (default is OptionLocatorByLabel).
+ */
+function OptionLocatorFactory() {
+}
+
+OptionLocatorFactory.prototype.fromLocatorString = function(locatorString) {
+ var locatorType = 'label';
+ var locatorValue = locatorString;
+ // If there is a locator prefix, use the specified strategy
+ var result = locatorString.match(/^([a-zA-Z]+)=(.*)/);
+ if (result) {
+ locatorType = result[1];
+ locatorValue = result[2];
+ }
+ if (this.optionLocators == undefined) {
+ this.registerOptionLocators();
+ }
+ if (this.optionLocators[locatorType]) {
+ return new this.optionLocators[locatorType](locatorValue);
+ }
+ throw new SeleniumError("Unkown option locator type: " + locatorType);
+};
+
+/**
+ * To allow for easy extension, all of the option locators are found by
+ * searching for all methods of OptionLocatorFactory.prototype that start
+ * with "OptionLocatorBy".
+ * TODO: Consider using the term "Option Specifier" instead of "Option Locator".
+ */
+OptionLocatorFactory.prototype.registerOptionLocators = function() {
+ this.optionLocators={};
+ for (var functionName in this) {
+ var result = /OptionLocatorBy([A-Z].+)$/.exec(functionName);
+ if (result != null) {
+ var locatorName = result[1].lcfirst();
+ this.optionLocators[locatorName] = this[functionName];
+ }
+ }
+};
+
+/**
+ * OptionLocator for options identified by their labels.
+ */
+OptionLocatorFactory.prototype.OptionLocatorByLabel = function(label) {
+ this.label = label;
+ this.labelMatcher = new PatternMatcher(this.label);
+ this.findOption = function(element) {
+ for (var i = 0; i < element.options.length; i++) {
+ if (this.labelMatcher.matches(element.options[i].text)) {
+ return element.options[i];
+ }
+ }
+ throw new SeleniumError("Option with label '" + this.label + "' not found");
+ };
+
+ this.assertSelected = function(element) {
+ var selectedLabel = element.options[element.selectedIndex].text;
+ Assert.matches(this.label, selectedLabel);
+ };
+};
+
+/**
+ * OptionLocator for options identified by their values.
+ */
+OptionLocatorFactory.prototype.OptionLocatorByValue = function(value) {
+ this.value = value;
+ this.valueMatcher = new PatternMatcher(this.value);
+ this.findOption = function(element) {
+ for (var i = 0; i < element.options.length; i++) {
+ if (this.valueMatcher.matches(element.options[i].value)) {
+ return element.options[i];
+ }
+ }
+ throw new SeleniumError("Option with value '" + this.value + "' not found");
+ };
+
+ this.assertSelected = function(element) {
+ var selectedValue = element.options[element.selectedIndex].value;
+ Assert.matches(this.value, selectedValue);
+ };
+};
+
+/**
+ * OptionLocator for options identified by their index.
+ */
+OptionLocatorFactory.prototype.OptionLocatorByIndex = function(index) {
+ this.index = Number(index);
+ if (isNaN(this.index) || this.index < 0) {
+ throw new SeleniumError("Illegal Index: " + index);
+ }
+
+ this.findOption = function(element) {
+ if (element.options.length <= this.index) {
+ throw new SeleniumError("Index out of range. Only " + element.options.length + " options available");
+ }
+ return element.options[this.index];
+ };
+
+ this.assertSelected = function(element) {
+ Assert.equals(this.index, element.selectedIndex);
+ };
+};
+
+/**
+ * OptionLocator for options identified by their id.
+ */
+OptionLocatorFactory.prototype.OptionLocatorById = function(id) {
+ this.id = id;
+ this.idMatcher = new PatternMatcher(this.id);
+ this.findOption = function(element) {
+ for (var i = 0; i < element.options.length; i++) {
+ if (this.idMatcher.matches(element.options[i].id)) {
+ return element.options[i];
+ }
+ }
+ throw new SeleniumError("Option with id '" + this.id + "' not found");
+ };
+
+ this.assertSelected = function(element) {
+ var selectedId = element.options[element.selectedIndex].id;
+ Assert.matches(this.id, selectedId);
+ };
+};
+
+