summaryrefslogtreecommitdiff
path: root/tests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js
diff options
context:
space:
mode:
Diffstat (limited to 'tests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js')
-rwxr-xr-xtests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js266
1 files changed, 266 insertions, 0 deletions
diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js b/tests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js
new file mode 100755
index 00000000..14c1a07a
--- /dev/null
+++ b/tests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js
@@ -0,0 +1,266 @@
+/*
+* 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.
+*/
+
+SELENIUM_PROCESS_WAIT = "wait";
+
+function TestLoop(commandFactory) {
+
+ this.commandFactory = commandFactory;
+ this.waitForConditionTimeout = 30 * 1000; // 30 seconds
+
+ this.start = function() {
+ selenium.reset();
+ LOG.debug("testLoop.start()");
+ this.continueTest();
+ };
+
+ /**
+ * Select the next command and continue the test.
+ */
+ this.continueTest = function() {
+ LOG.debug("testLoop.continueTest() - acquire the next command");
+ if (! this.aborted) {
+ this.currentCommand = this.nextCommand();
+ }
+ if (! this.requiresCallBack) {
+ this.beginNextTest();
+ } // otherwise, just finish and let the callback invoke beginNextTest()
+ };
+
+ this.beginNextTest = function() {
+ LOG.debug("testLoop.beginNextTest()");
+ if (this.currentCommand) {
+ // TODO: rename commandStarted to commandSelected, OR roll it into nextCommand
+ this.commandStarted(this.currentCommand);
+ this.resumeAfterDelay();
+ } else {
+ this.testComplete();
+ }
+ }
+
+ /**
+ * Pause, then execute the current command.
+ */
+ this.resumeAfterDelay = function() {
+
+ // Get the command delay. If a pauseInterval is set, use it once
+ // and reset it. Otherwise, use the defined command-interval.
+ var delay = this.pauseInterval || this.getCommandInterval();
+ this.pauseInterval = undefined;
+
+ if (delay < 0) {
+ // Pause: enable the "next/continue" button
+ this.pause();
+ } else {
+ window.setTimeout("testLoop.resume()", delay);
+ }
+ };
+
+ /**
+ * Select the next command and continue the test.
+ */
+ this.resume = function() {
+ LOG.debug("testLoop.resume() - actually execute");
+ try {
+ this.executeCurrentCommand();
+ this.waitForConditionStart = new Date().getTime();
+ this.continueTestWhenConditionIsTrue();
+ } catch (e) {
+ this.handleCommandError(e);
+ this.testComplete();
+ return;
+ }
+ };
+
+ /**
+ * Execute the current command.
+ *
+ * The return value, if not null, should be a function which will be
+ * used to determine when execution can continue.
+ */
+ this.executeCurrentCommand = function() {
+
+ var command = this.currentCommand;
+ LOG.info("Executing: |" + command.command + " | " + command.target + " | " + command.value + " |");
+
+ var handler = this.commandFactory.getCommandHandler(command.command);
+ if (handler == null) {
+ throw new SeleniumError("Unknown command: '" + command.command + "'");
+ }
+
+ command.target = selenium.preprocessParameter(command.target);
+ command.value = selenium.preprocessParameter(command.value);
+ LOG.debug("Command found, going to execute " + command.command);
+ var result = handler.execute(selenium, command);
+ LOG.debug("Command complete");
+ this.commandComplete(result);
+
+ if (result.processState == SELENIUM_PROCESS_WAIT) {
+ this.waitForCondition = function() {
+ LOG.debug("Checking condition: isNewPageLoaded?");
+ return selenium.browserbot.isNewPageLoaded();
+ };
+ }
+ };
+
+ this.handleCommandError = function(e) {
+ if (!e.isSeleniumError) {
+ LOG.exception(e);
+ var msg = "Selenium failure. Please report to selenium-dev@openqa.org, with error details from the log window.";
+ if (e.message) {
+ msg += " The error message is: " + e.message;
+ }
+ this.commandError(msg);
+ } else {
+ LOG.error(e.message);
+ this.commandError(e.message);
+ }
+ };
+
+ /**
+ * Busy wait for waitForCondition() to become true, and then carry on
+ * with test. Fail the current test if there's a timeout or an exception.
+ */
+ this.continueTestWhenConditionIsTrue = function () {
+ LOG.debug("testLoop.continueTestWhenConditionIsTrue()");
+ try {
+ if (this.waitForCondition == null || this.waitForCondition()) {
+ LOG.debug("condition satisfied; let's continueTest()");
+ this.waitForCondition = null;
+ this.waitForConditionStart = null;
+ this.continueTest();
+ } else {
+ LOG.debug("waitForCondition was false; keep waiting!");
+ if (this.waitForConditionTimeout != null) {
+ var now = new Date();
+ if ((now - this.waitForConditionStart) > this.waitForConditionTimeout) {
+ throw new SeleniumError("Timed out after " + this.waitForConditionTimeout + "ms");
+ }
+ }
+ window.setTimeout("testLoop.continueTestWhenConditionIsTrue()", 10);
+ }
+ } catch (e) {
+ var lastResult = new CommandResult();
+ lastResult.failed = true;
+ lastResult.failureMessage = e.message;
+ this.commandComplete(lastResult);
+ this.testComplete();
+ }
+ };
+
+}
+
+/** The default is not to have any interval between commands. */
+TestLoop.prototype.getCommandInterval = function() {
+ return 0;
+};
+
+TestLoop.prototype.nextCommand = noop;
+
+TestLoop.prototype.commandStarted = noop;
+
+TestLoop.prototype.commandError = noop;
+
+TestLoop.prototype.commandComplete = noop;
+
+TestLoop.prototype.testComplete = noop;
+
+TestLoop.prototype.pause = noop;
+
+function noop() {
+
+};
+
+/**
+ * Tell Selenium to expect a failure on the next command execution. This
+ * command temporarily installs a CommandFactory that generates
+ * CommandHandlers that expect a failure.
+ */
+Selenium.prototype.assertFailureOnNext = function(message) {
+ if (!message) {
+ throw new Error("Message must be provided");
+ }
+
+ var expectFailureCommandFactory =
+ new ExpectFailureCommandFactory(testLoop.commandFactory, message, "failure");
+ expectFailureCommandFactory.baseExecutor = executeCommandAndReturnFailureMessage;
+ testLoop.commandFactory = expectFailureCommandFactory;
+};
+
+/**
+ * Tell Selenium to expect an error on the next command execution. This
+ * command temporarily installs a CommandFactory that generates
+ * CommandHandlers that expect a failure.
+ */
+Selenium.prototype.assertErrorOnNext = function(message) {
+ if (!message) {
+ throw new Error("Message must be provided");
+ }
+
+ var expectFailureCommandFactory =
+ new ExpectFailureCommandFactory(testLoop.commandFactory, message, "error");
+ expectFailureCommandFactory.baseExecutor = executeCommandAndReturnErrorMessage;
+ testLoop.commandFactory = expectFailureCommandFactory;
+};
+
+function ExpectFailureCommandFactory(originalCommandFactory, expectedErrorMessage, errorType) {
+ this.getCommandHandler = function(name) {
+ var baseHandler = originalCommandFactory.getCommandHandler(name);
+ var baseExecutor = this.baseExecutor;
+ var expectFailureCommand = {};
+ expectFailureCommand.execute = function() {
+ var baseFailureMessage = baseExecutor(baseHandler, arguments);
+ var result = new CommandResult();
+ if (!baseFailureMessage) {
+ result.failed = true;
+ result.failureMessage = "Expected " + errorType + " did not occur.";
+ }
+ else {
+ if (! PatternMatcher.matches(expectedErrorMessage, baseFailureMessage)) {
+ result.failed = true;
+ result.failureMessage = "Expected " + errorType + " message '" + expectedErrorMessage
+ + "' but was '" + baseFailureMessage + "'";
+ }
+ else {
+ result.passed = true;
+ result.result = baseFailureMessage;
+ }
+ }
+ testLoop.commandFactory = originalCommandFactory;
+ return result;
+ };
+ return expectFailureCommand;
+ };
+};
+
+function executeCommandAndReturnFailureMessage(baseHandler, originalArguments) {
+ var baseResult = baseHandler.execute.apply(baseHandler, originalArguments);
+ if (baseResult.passed) {
+ return null;
+ }
+ return baseResult.failureMessage;
+};
+
+function executeCommandAndReturnErrorMessage(baseHandler, originalArguments) {
+ try {
+ baseHandler.execute.apply(baseHandler, originalArguments);
+ return null;
+ }
+ catch (expected) {
+ return expected.message;
+ }
+};
+