summaryrefslogtreecommitdiff
path: root/tests/FunctionalTests/selenium/selenium-commandhandlers.js
diff options
context:
space:
mode:
authorwei <>2005-12-10 11:49:29 +0000
committerwei <>2005-12-10 11:49:29 +0000
commit98215a603fb798cdb4178e49061977544aaa45b7 (patch)
tree282787037961f7466acbd174ce151cac6de71273 /tests/FunctionalTests/selenium/selenium-commandhandlers.js
parent25f9c45261aafd65477ad526e0b6ad3dca80803a (diff)
Initial import selenium functional test framework.
Diffstat (limited to 'tests/FunctionalTests/selenium/selenium-commandhandlers.js')
-rw-r--r--tests/FunctionalTests/selenium/selenium-commandhandlers.js291
1 files changed, 291 insertions, 0 deletions
diff --git a/tests/FunctionalTests/selenium/selenium-commandhandlers.js b/tests/FunctionalTests/selenium/selenium-commandhandlers.js
new file mode 100644
index 00000000..10e2a518
--- /dev/null
+++ b/tests/FunctionalTests/selenium/selenium-commandhandlers.js
@@ -0,0 +1,291 @@
+/*
+* 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.
+*
+*/
+function CommandHandlerFactory() {
+ this.actions = {};
+ this.asserts = {};
+ this.accessors = {};
+
+ var self = this;
+
+ this.registerAction = function(name, action, wait) {
+ var handler = new ActionHandler(action, wait);
+ this.actions[name] = handler;
+ };
+
+ this.registerAccessor = function(name, accessor) {
+ var handler = new AccessorHandler(accessor);
+ this.accessors[name] = handler;
+ };
+
+ this.registerAssert = function(name, assertion, haltOnFailure) {
+ var handler = new AssertHandler(assertion, haltOnFailure);
+ this.asserts[name] = handler;
+ };
+
+ this.registerAssertUsingMatcherHandler = function(name, matcherHandler, haltOnFailure) {
+ var handler = new AssertUsingMatcherHandler(matcherHandler, haltOnFailure);
+ this.asserts[name] = handler;
+ }
+
+ this.getCommandHandler = function(name) {
+ return this.actions[name] || this.accessors[name] || this.asserts[name] || null;
+ };
+
+ this.registerAll = function(commandObject) {
+ registerAllActions(commandObject);
+ registerAllAsserts(commandObject);
+ registerAllAccessors(commandObject);
+ };
+
+ var registerAllActions = function(commandObject) {
+ for (var functionName in commandObject) {
+ var result = /^do([A-Z].+)$/.exec(functionName);
+ if (result != null) {
+ var actionName = result[1].lcfirst();
+
+ // Register the action without the wait flag.
+ var action = commandObject[functionName];
+ self.registerAction(actionName, action, false);
+
+ // Register actionName + "AndWait" with the wait flag;
+ var waitActionName = actionName + "AndWait";
+ self.registerAction(waitActionName, action, true);
+ }
+ }
+ };
+
+ var registerAllAsserts = function(commandObject) {
+ for (var functionName in commandObject) {
+ var result = /^assert([A-Z].+)$/.exec(functionName);
+ if (result != null) {
+ var assert = commandObject[functionName];
+
+ // Register the assert with the "assert" prefix, and halt on failure.
+ var assertName = functionName;
+ self.registerAssert(assertName, assert, true);
+
+ // Register the assert with the "verify" prefix, and do not halt on failure.
+ var verifyName = "verify" + result[1];
+ self.registerAssert(verifyName, assert, false);
+ }
+ }
+ };
+
+ // Given an accessor function, return a function that matches against the command.value
+ // the value returned by the accessor when applied to a command.target.
+ // Used by commands that take a target and a value (e.g. assertValue | target | value)
+ this.createMatcherHandlerFromSingleArgAccessor = function(accessor) {
+ return function(seleniumApi, command) {
+ var accessorResult = accessor.call(seleniumApi, command.target);
+ if (PatternMatcher.matches(command.value, accessorResult)) {
+ return new MatcherHandlerResult(true, "Actual value '" + accessorResult + "' did match '" + command.value + "'");
+ } else {
+ return new MatcherHandlerResult(false, "Actual value '" + accessorResult + "' did not match '" + command.value + "'");
+ }
+ };
+ };
+
+ // Given an accessor function, return a function that matches against the command.target
+ // the value returned by the (no-arg) accessor returns a value that matches against the command.target
+ // Used by commands that only take a target (e.g. assertTitle | target | &nbsp;)
+ this.createMatcherHandlerFromNoArgAccessor = function(accessor) {
+ return function(seleniumApi, command) {
+ var accessorResult = accessor.call(seleniumApi);
+ if (PatternMatcher.matches(command.target, accessorResult)) {
+ return new MatcherHandlerResult(true, "Actual value '" + accessorResult + "' did match '" + command.target + "'");
+ } else {
+ return new MatcherHandlerResult(false, "Actual value '" + accessorResult + "' did not match '" + command.target + "'");
+ }
+ };
+ };
+
+ // Given a matcherHandler function, return a function that returns the same result
+ // as the matcherHandler, but with the result negated.
+ // Used to create assertNot and verifyNot commands (and soon hopefully waitForNot commands).
+ this.createMatcherHandlerNegator = function(matcherHandler) {
+ return function(seleniumApi, command) {
+ var result = matcherHandler(seleniumApi, command);
+ result.didMatch = ! result.didMatch;
+ return result;
+ };
+ };
+
+ // Register an assertion, a verification, a negative assertion,
+ // and a negative verification based on the specified accessor.
+ this.registerAssertionsBasedOnAccessor = function(accessor, baseName) {
+ if (accessor.length > 1) {
+ return;
+ }
+ var matcherHandler;
+ if (accessor.length == 1) {
+ matcherHandler = self.createMatcherHandlerFromSingleArgAccessor(accessor);
+ } else {
+ matcherHandler = self.createMatcherHandlerFromNoArgAccessor(accessor);
+ }
+ // Register an assert with the "assert" prefix, and halt on failure.
+ self.registerAssertUsingMatcherHandler("assert" + baseName, matcherHandler, true);
+ // Register a verify with the "verify" prefix, and do not halt on failure.
+ self.registerAssertUsingMatcherHandler("verify" + baseName, matcherHandler, false);
+
+ var negativeMatcherHandler = self.createMatcherHandlerNegator(matcherHandler);
+ // Register an assertNot with the "assertNot" prefix, and halt on failure.
+ self.registerAssertUsingMatcherHandler("assertNot"+baseName, negativeMatcherHandler, true);
+ // Register a verifyNot with the "verifyNot" prefix, and do not halt on failure.
+ self.registerAssertUsingMatcherHandler("verifyNot"+baseName, negativeMatcherHandler, false);
+ };
+
+ // Methods of the form getFoo(target) result in commands:
+ // getFoo, assertFoo, verifyFoo, assertNotFoo, verifyNotFoo
+ var registerAllAccessors = function(commandObject) {
+ for (var functionName in commandObject) {
+ var match = /^get([A-Z].+)$/.exec(functionName);
+ if (match != null) {
+ var accessor = commandObject[functionName];
+ var baseName = match[1];
+ self.registerAccessor(functionName, accessor);
+ self.registerAssertionsBasedOnAccessor(accessor, baseName);
+ }
+ }
+ };
+
+
+}
+
+function MatcherHandlerResult(didMatch, message) {
+ this.didMatch = didMatch;
+ this.message = message;
+}
+
+// NOTE: The CommandHandler is effectively an abstract base for ActionHandler,
+// AccessorHandler and AssertHandler.
+function CommandHandler(type, haltOnFailure, executor) {
+ this.type = type;
+ this.haltOnFailure = haltOnFailure;
+ this.executor = executor;
+}
+CommandHandler.prototype.execute = function(seleniumApi, command) {
+ return new CommandResult(this.executor.call(seleniumApi, command.target, command.value));
+};
+
+function ActionHandler(action, wait) {
+ CommandHandler.call(this, "action", true, action);
+ if (wait) {
+ this.wait = true;
+ }
+}
+ActionHandler.prototype = new CommandHandler;
+ActionHandler.prototype.execute = function(seleniumApi, command) {
+ if ( seleniumApi.browserbot.hasAlerts() ) {
+ throw new SeleniumCommandError("There was an unexpected Alert! [" + seleniumApi.browserbot.getNextAlert() + "]");
+ }
+ if ( seleniumApi.browserbot.hasConfirmations() ) {
+ throw new SeleniumCommandError("There was an unexpected Confirmation! [" + seleniumApi.browserbot.getNextConfirmation() + "]");
+ }
+ var processState = this.executor.call(seleniumApi, command.target, command.value);
+ // If the handler didn't return a wait flag, check to see if the
+ // handler was registered with the wait flag.
+ if (processState == undefined && this.wait) {
+ processState = SELENIUM_PROCESS_WAIT;
+ }
+ return new CommandResult(processState);
+};
+
+function AccessorHandler(accessor) {
+ CommandHandler.call(this, "accessor", true, accessor);
+}
+AccessorHandler.prototype = new CommandHandler;
+AccessorHandler.prototype.execute = function(seleniumApi, command) {
+ var returnValue = this.executor.call(seleniumApi, command.target, command.value);
+ var result = new CommandResult();
+ result.result = returnValue;
+ return result;
+};
+
+/**
+ * Abstract handler for assertions and verifications.
+ * Subclasses need to override executeAssertion() which in turn
+ * should throw an AssertFailedError if the assertion is to fail.
+ */
+function AbstractAssertHandler(assertion, haltOnFailure) {
+ CommandHandler.call(this, "assert", haltOnFailure || false, assertion);
+}
+AbstractAssertHandler.prototype = new CommandHandler;
+AbstractAssertHandler.prototype.execute = function(seleniumApi, command) {
+ var result = new CommandResult();
+ try {
+ this.executeAssertion(seleniumApi, command);
+ result.passed = true;
+ } catch (e) {
+ // If this is not a AssertionFailedError, or we should haltOnFailure, rethrow.
+ if (!e.isAssertionFailedError) {
+ throw e;
+ }
+ if (this.haltOnFailure) {
+ var error = new SeleniumCommandError(e.failureMessage);
+ throw error;
+ }
+ result.failed = true;
+ result.failureMessage = e.failureMessage;
+ }
+ return result;
+};
+
+/**
+ * Simple assertion handler whose command is expected to do the actual assertion.
+ */
+function AssertHandler(assertion, haltOnFailure) {
+ CommandHandler.call(this, "assert", haltOnFailure || false, assertion);
+};
+AssertHandler.prototype = new AbstractAssertHandler;
+AssertHandler.prototype.executeAssertion = function(seleniumApi, command) {
+ this.executor.call(seleniumApi, command.target, command.value);
+};
+
+/**
+ * Assertion handler whose command is expected to be a matcher-handler
+ */
+function AssertUsingMatcherHandler(matcherHandler, haltOnFailure) {
+ CommandHandler.call(this, "assert", haltOnFailure || false, matcherHandler);
+};
+AssertUsingMatcherHandler.prototype = new AbstractAssertHandler;
+AssertUsingMatcherHandler.prototype.executeAssertion = function(seleniumApi, command) {
+ var matcherResult = this.executor(seleniumApi, command);
+ if (!matcherResult.didMatch) {
+ Assert.fail(matcherResult.message);
+ }
+};
+
+
+function CommandResult(processState) {
+ this.processState = processState;
+ this.result = "OK";
+}
+
+function SeleniumCommand(command, target, value) {
+ this.command = command;
+ this.target = target;
+ this.value = value;
+}
+
+// TODO: dkemp - This is the same as SeleniumError as defined in selenium-browserbot.js
+// I defined a new error simply to avoid creating a new dependency.
+// Need to revisit to avoid this duplication.
+function SeleniumCommandError(message) {
+ var error = new Error(message);
+ error.isSeleniumError = true;
+ return error;
+};