diff options
author | xue <> | 2006-07-07 14:54:15 +0000 |
---|---|---|
committer | xue <> | 2006-07-07 14:54:15 +0000 |
commit | 61bb16ee2e5f0a66234e1575242169a10fde47b5 (patch) | |
tree | 3ee24dcc36ceae2c213130df1ea3d5c9fc110a27 /tests/FunctionalTests | |
parent | 7b84938b1b5964f2274d66e28ba17435924ffe35 (diff) |
Merge from 3.0 branch till 1253.
Diffstat (limited to 'tests/FunctionalTests')
51 files changed, 96 insertions, 13005 deletions
diff --git a/tests/FunctionalTests/PradoTester.php b/tests/FunctionalTests/PradoTester.php deleted file mode 100644 index 0c83217e..00000000 --- a/tests/FunctionalTests/PradoTester.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php
-
-$SIMPLE_TEST = dirname(__FILE__).'/../UnitTests';
-
-require_once($SIMPLE_TEST.'/simpletest/unit_tester.php');
-require_once($SIMPLE_TEST.'/simpletest/web_tester.php');
-require_once($SIMPLE_TEST.'/simpletest/mock_objects.php');
-require_once($SIMPLE_TEST.'/simpletest/reporter.php');
-require(dirname(__FILE__).'/selenium/php/selenium.php');
-
-class PradoTester
-{
- private $_name;
- private $_basePath;
-
- public function __construct($basePath,$name='All Tests')
- {
- $this->_name=$name;
- if($basePath==='' || ($this->_basePath=realpath($basePath))===false)
- throw new Exception('Invalid base path '.$basePath);
- $this->_basePath=strtr($this->_basePath,'\\','/');
- }
-
- public function run($simpleReporter)
- {
- $groupTest=new GroupTest($this->_name);
- $this->collectTestFiles($groupTest,$this->_basePath);
- $groupTest->run($simpleReporter);
-
- $server=SimpleSeleniumProxyServer::getInstance(dirname(__FILE__));
- $server->handleRequest();
- }
-
- protected function collectTestFiles($groupTest,$basePath)
- {
- $folder=@opendir($basePath);
- while($entry=@readdir($folder))
- {
- $fullPath=strtr($basePath.'/'.$entry,'\\','/');
- if(is_file($fullPath) && $this->isValidFile($entry))
- $groupTest->addTestFile($fullPath);
- else if($entry[0]!=='.')
- $this->collectTestFiles($groupTest,$fullPath);
- }
- @closedir($folder);
- }
-
- protected function isValidFile($entry)
- {
- return preg_match('/\w+\.php$/',$entry);
- }
-}
-
-?>
\ No newline at end of file diff --git a/tests/FunctionalTests/README.txt b/tests/FunctionalTests/README.txt deleted file mode 100644 index 06519092..00000000 --- a/tests/FunctionalTests/README.txt +++ /dev/null @@ -1,532 +0,0 @@ -== PRADO Functional Tests ==
-
-Functional tests are browser based that tests the overall functional of a Prado application. The tests can be written in PHP, see "framework/..." within this directory to see some examples. To run the tests, open your browser to "../tests/FunctionalTests/index.php" and click on the "All" button.
-
-
-=== Writing Tests ===
-Lets test some part of a Prado application. Create a new php file, e.g.
-
-testExample1.php
-
-<php>
-<?php
-class testExample1 extends SeleniumTestCase
-{
- function setup()
- {
- $this->open('../examples/myexample/index.php');
- }
-
- function testButtonClickExample()
- {
- //using xpath to find the button with value "Click Me!"
- $this->click('//input[@value="Click Me!"]');
-
- //..more commands and assertions
- }
-}
-?>
-</php>
-
-=== Tests as part of Example code ===
-Tests can also be place within the example page, e.g. suppose we have an example call MyButtonExample.
-
-File: MyButtonExample.php
-<php>
-<?php
-//Example class, changes the Text of a button when clicked.
-class MyButtonExample extends TPage
-{
- function button_clicked($sender, $param)
- {
- $sender->Text = "Hello World!";
- }
-}
-
-
-class testMyButtonExample extends SeleniumTestCase
-{
- function setup()
- {
- //get the test page url
- $page = Prado::getApplication()->getTestPage(__FILE__);
-
- //open MyButtonExample page
- $this->open($page);
- }
-
- function testButtonClick()
- {
- $this->assertTextPresent("My Button Example");
- $this->click('//input[@value="Click Me!"]');
- $this->click('//input[@value="Hello World!"]');
- }
-}
-?>
-</php>
-
-File: MyButtonExample.tpl
-<prado>
-<com:TForm>
- <h1>My Button Example</h1>
- <com:TButton Text="Click Me!"
- Click="button_clicked" />
-</com:TForm>
-</prado>
-
-== Selenium Reference ==
-
-A '''command''' is what tells Selenium what to do. Selenium commands come in two 'flavors', '''Actions''' and '''Assertions'''. Each command call has the following syntax
-<php>
- $this->[command]([target], [value]);
-</php>
-Note that some commands does not need a [value].
-
-'''Actions''' are commands that generally manipulate the state of the application. They do things like "click this link" and "select that option". If an Action fails, or has an error, the execution of the current test is stopped.
-
-
-'''Checks''' verify the state of the application conforms to what is expected. Examples include "make sure the page title is X" and "check that this checkbox is checked". It is possible to tell Selenium to stop the test when an Assertion fails, or to simply record the failure and continue.
-
-'''Element Locators''' tell Selenium which HTML element a command refers to. Many commands require an Element Locator as the "target" attribute. Examples of Element Locators include "elementId" and "document.forms[0].element". These are described more clearly in the next section.
-
-'''Patterns''' are used for various reasons, e.g. to specify the expected value of an input field, or identify a select option. Selenium supports various types of pattern, including regular-expressions, all of which are described in more detail below.
-
-=== Element Locators ===
-
-Element Locators allow Selenium to identify which HTML element a command refers to. Selenium support the following strategies for locating elements:
-
-==== '''id='''''id'' ====
-Select the element with the specified @id attribute.
-
-==== '''name='''''name'' ====
-Select the first element with the specified @name attribute.
-
-==== '''identifier='''''id''====
-Select the element with the specified @id attribute. If no match is found, select the first element whose @name attribute is ''id''.
-
-==== '''dom='''''javascriptExpression''====
-Find an element using JavaScript traversal of the HTML Document Object Model. DOM locators ''must'' begin with "document.".
-* dom=document.forms['myForm'].myDropdown
-* dom=document.images[56]
-
-==== '''xpath='''''xpathExpression''====
-Locate an element using an XPath expression. XPath locators ''must'' begin with "//".
-* xpath=//img[@alt='The image alt text']
-* xpath=//table[@id='table1']//tr[4]/td[2]
-
-==== '''link='''''textPattern'' ====
-Select the link (anchor) element which contains text matching the specified ''pattern''.
-* link=The link text
-
-Without a locator prefix, Selenium uses:
-
-* dom, for locators starting with "document."
-* xpath, for locators starting with "//"
-* identifier, otherwise
-
-
-=== Select Option Specifiers ===
-
-Select Option Specifiers provide different ways of specifying options of an HTML Select element (e.g. for selecting a specific option, or for asserting that the selected option satisfies a specification). There are several forms of Select Option Specifier.
-
-==== label=labelPattern ====
-matches options based on their labels, i.e. the visible text.
-* label=regexp:^[Oo]ther
-
-==== value=valuePattern ====
-matches options based on their values.
-* value=other
-
-==== id=id ====
-matches options based on their ids.
-* id=option1
-
-==== index=index ====
-matches an option based on its index (offset from zero).
-* index=2
-
-Without a prefix, the default behaviour is to only match on labels.
-
-String-match Patterns
-
- Various Pattern syntaxes are available for matching string values:
-
- glob:pattern
- Match a string against a "glob" (aka "wildmat") pattern. "Glob" is a kind of limited regular-expression syntax typically used in command-line shells. In a glob pattern, "*" represents any sequence of characters, and "?" represents any single character. Glob patterns match against the entire string.
- regexp:regexp
- Match a string using a regular-expression. The full power of JavaScript regular-expressions is available.
- exact:string
- Match a string exactly, verbatim, without any of that fancy wildcard stuff.
-
- If no pattern prefix is specified, Selenium assumes that it's a "glob" pattern.
-
-Selenium Actions
-
- Actions tell Selenium to do something in the application. They generally represent something a user would do.
-
- Many Actions can be called with the "AndWait" suffix. This suffix tells Selenium that the action will cause the browser to make a call to the server, and that Selenium should wait for a new page to load. The exceptions to this pattern are the "open" and "click" actions, which will both wait for a page to load by default.
-
- open( url )
-
- Opens a URL in the test frame. This accepts both relative and absolute URLs.
-
- Note: The URL must be on the same site as Selenium due to security restrictions in the browser (Cross Site Scripting).
-
- examples:
-
- open /mypage
- open http://localhost/
-
- click( elementLocator )
-
- Clicks on a link, button, checkbox or radio button. If the click action causes a new page to load (like a link usually does), use "clickAndWait".
-
- examples:
-
- click aCheckbox
- clickAndWait submitButton
- clickAndWait anyLink
-
- note:
- Selenium will always automatically click on a popup dialog raised by the alert() or confirm() methods. (The exception is those raised during 'onload', which are not yet handled by Selenium). You must use [verify|assert]Alert or [verify|assert]Confirmation to tell Selenium that you expect the popup dialog. You may use chooseCancelOnNextConfirmation to click 'cancel' on the next confirmation dialog instead of clicking 'OK'.
-
- type( inputLocator, value )
-
- Sets the value of an input field, as though you typed it in.
-
- Can also be used to set the value of combo boxes, check boxes, etc. In these cases, value should be the value of the option selected, not the visible text.
-
- examples:
-
- type nameField John Smith
- typeAndWait textBoxThatSubmitsOnChange newValue
-
- select( dropDownLocator, optionSpecifier )
-
- Select an option from a drop-down, based on the optionSpecifier. If more than one option matches the specifier (e.g. due to the use of globs like "f*b*", or due to more than one option having the same label or value), then the first matches is selected.
-
- examples:
-
- select dropDown Australian Dollars
- select dropDown index=0
- selectAndWait currencySelector value=AUD
- selectAndWait currencySelector label=Aus*lian D*rs
-
- selectWindow( windowId )
-
- Selects a popup window. Once a popup window has been selected, all commands go to that window. To select the main window again, use "null" as the target.
-
- target: The id of the window to select.
-
- value: ignored
-
- examples:
-
- selectWindow myPopupWindow
- selectWindow null
-
- goBack()
-
- Simulates the user clicking the "back" button on their browser.
-
- examples:
-
- goBack
-
- close()
-
- Simulates the user clicking the "close" button in the titlebar of a popup window.
-
- examples:
-
- close
-
- pause( milliseconds )
-
- Pauses the execution of the test script for a specified amount of time. This is useful for debugging a script or pausing to wait for some server side action.
-
- examples:
-
- pause 5000
- pause 2000
-
- fireEvent( elementLocator, eventName )
-
- Explicitly simulate an event, to trigger the corresponding "onevent" handler.
-
- examples:
-
- fireEvent textField focus
- fireEvent dropDown blur
-
- waitForValue( inputLocator, value )
-
- Waits for a specified input (e.g. a hidden field) to have a specified value. Will succeed immediately if the input already has the value. This is implemented by polling for the value. Warning: can block indefinitely if the input never has the specified value.
-
- example:
-
- waitForValue finishIndication isfinished
-
- store( valueToStore, variableName )
-
- Stores a value into a variable. The value can be constructed using either variable substitution or javascript evaluation, as detailed in 'Parameter construction and Variables' (below).
-
- examples:
-
- store Mr John Smith fullname
- store ${title} ${firstname} ${surname} fullname
- store javascript{Math.round(Math.PI * 100) / 100} PI
-
- storeValue( inputLocator, variableName )
-
- Stores the value of an input field into a variable.
-
- examples:
-
- storeValue userName userID
- type userName ${userID}
-
- storeText( elementLocator, variableName )
-
- Stores the text of an element into a variable.
-
- examples:
-
- storeText currentDate expectedStartDate
- verifyValue startDate ${expectedStartDate}
-
- storeAttribute( elementLocator@attributeName, variableName )
-
- Stores the value of an element attribute into a variable.
-
- examples:
-
- storeAttribute input1@class classOfInput1
- verifyAttribute input2@class ${classOfInput1}
-
- chooseCancelOnNextConfirmation()
-
- Instructs Selenium to click Cancel on the next javascript confirmation dialog to be raised. By default, the confirm function will return true, having the same effect as manually clicking OK. After running this command, the next confirmation will behave as if the user had clicked Cancel.
-
- examples:
-
- chooseCancelOnNextConfirmation
-
- answerOnNextPrompt( answerString )
-
- Instructs Selenium to return the specified answerString in response to the next prompt.
-
- examples:
-
- answerOnNextPrompt Kangaroo
-
-Selenium Checks
-
- Checks are used to verify the state of the application. They can be used to check the value of a form field, the presense of some text, or the URL of the current page.
-
- All Selenium Checks can be used in 2 modes, "assert" and "verify". These behave identically, except that when an "assert" check fails, the test is aborted. When a "verify" check fails, the test will continue execution. This allows a single "assert" to ensure that the application is on the correct page, followed by a bunch of "verify" checks to test form field values, labels, etc.
-
- assertLocation( relativeLocation )
-
- examples:
-
- verifyLocation /mypage
- assertLocation /mypage
-
- assertTitle( titlePattern )
-
- Verifies the title of the current page.
-
- examples:
-
- verifyTitle My Page
- assertTitle My Page
-
- assertValue( inputLocator, valuePattern )
-
- Verifies the value of an input field (or anything else with a value parameter). For checkbox/radio elements, the value will be "on" or "off" depending on whether the element is checked or not.
-
- examples:
-
- verifyValue nameField John Smith
- assertValue document.forms[2].nameField John Smith
-
- assertSelected( selectLocator, optionSpecifier )
-
- Verifies that the selected option of a drop-down satisfies the optionSpecifier.
-
- examples:
-
- verifySelected dropdown2 John Smith
- verifySelected dropdown2 value=js*123
- assertSelected document.forms[2].dropDown label=J* Smith
- assertSelected document.forms[2].dropDown index=0
-
- assertSelectOptions( selectLocator, optionLabelList )
-
- Verifies the labels of all options in a drop-down against a comma-separated list. Commas in an expected option can be escaped as ",".
-
- examples:
-
- verifySelectOptions dropdown2 John Smith,Dave Bird
- assertSelectOptions document.forms[2].dropDown Smith\, J,Bird\, D
-
- assertText( elementLocator, textPattern )
-
- Verifies the text of an element. This works for any element that contains text. This command uses either the textContent (Mozilla-like browsers) or the innerText (IE-like browsers) of the element, which is the rendered text shown to the user.
-
- examples:
-
- verifyText statusMessage Successful
- assertText //div[@id='foo']//h1 Successful
-
- assertAttribute( elementLocator@attributeName, valuePattern )
-
- Verifies the value of an element attribute.
-
- examples:
-
- verifyAttribute txt1@class bigAndBold
- assertAttribute document.images[0]@alt alt-text
- verifyAttribute //img[@id='foo']/@alt alt-text
-
- assertTextPresent( text )
-
- Verifies that the specified text appears somewhere on the rendered page shown to the user.
-
- examples:
-
- verifyTextPresent You are now logged in.
- assertTextPresent You are now logged in.
-
- assertTextNotPresent( text )
-
- Verifies that the specified text does NOT appear anywhere on the rendered page.
-
- assertElementPresent( elementLocator )
-
- Verifies that the specified element is somewhere on the page.
-
- examples:
-
- verifyElementPresent submitButton
- assertElementPresent //img[@alt='foo']
-
- assertElementNotPresent( elementLocator )
-
- Verifies that the specified element is NOT on the page.
-
- examples:
-
- verifyElementNotPresent cancelButton
- assertElementNotPresent cancelButton
-
- assertTable( cellAddress, valuePattern )
-
- Verifies the text in a cell of a table. The cellAddress syntax tableName.row.column, where row and column start at 0.
-
- examples:
-
- verifyTable myTable.1.6 Submitted
- assertTable results.0.2 13
-
- assertVisible( elementLocator )
-
- Verifies that the specified element is both present and visible. An element can be rendered invisible by setting the CSS "visibility" property to "hidden", or the "display" property to "none", either for the element itself or one if its ancestors.
-
- examples:
-
- verifyVisible postcode
- assertVisible postcode
-
- assertNotVisible( elementLocator )
-
- Verifies that the specified element is NOT visible. Elements that are simply not present are also considered invisible.
-
- examples:
-
- verifyNotVisible postcode
- assertNotVisible postcode
-
- verifyEditable / assertEditable( inputLocator )
-
- Verifies that the specified element is editable, ie. it's an input element, and hasn't been disabled.
-
- examples:
-
- verifyEditable shape
- assertEditable colour
-
- assertNotEditable( inputLocator )
-
- Verifies that the specified element is NOT editable, ie. it's NOT an input element, or has been disabled.
-
- assertAlert( messagePattern )
-
- Verifies that a javascript alert with the specified message was generated. Alerts must be verified in the same order that they were generated.
-
- Verifying an alert has the same effect as manually clicking OK. If an alert is generated but you do not verify it, the next Selenium action will fail.
-
- NOTE: under Selenium, javascript alerts will NOT pop up a visible alert dialog.
-
- NOTE: Selenium does NOT support javascript alerts that are generated in a page's onload() event handler. In this case a visible dialog WILL be generated and Selenium will hang until you manually click OK.
-
- examples:
-
- verifyAlert Invalid Phone Number
- assertAlert Invalid Phone Number
-
- assertConfirmation( messagePattern )
-
- Verifies that a javascript confirmation dialog with the specified message was generated. Like alerts, confirmations must be verified in the same order that they were generated.
-
- By default, the confirm function will return true, having the same effect as manually clicking OK. This can be changed by prior execution of the chooseCancelOnNextConfirmation command (see above). If an confirmation is generated but you do not verify it, the next Selenium action will fail.
-
- NOTE: under Selenium, javascript confirmations will NOT pop up a visible dialog.
-
- NOTE: Selenium does NOT support javascript confirmations that are generated in a page's onload() event handler. In this case a visible dialog WILL be generated and Selenium will hang until you manually click OK.
-
- examples:
-
- assertConfirmation Remove this user?
- verifyConfirmation Are you sure?
-
- assertPrompt( messagePattern )
-
- Verifies that a javascript prompt dialog with the specified message was generated. Like alerts, prompts must be verified in the same order that they were generated.
-
- Successful handling of the prompt requires prior execution of the answerOnNextPrompt command (see above). If a prompt is generated but you do not verify it, the next Selenium action will fail.
-
- examples:
-
- answerOnNextPrompt Joe
- click id=delegate
- verifyPrompt Delegate to who?
-
-Parameter construction and Variables
-
- All Selenium command parameters can be constructed using both simple variable substitution as well as full javascript. Both of these mechanisms can access previously stored variables, but do so using different syntax.
-
- Stored Variables
-
- The commands store, storeValue and storeText can be used to store a variable value for later access. Internally, these variables are stored in a map called "storedVars", with values keyed by the variable name. These commands are documented in the command reference.
-
- Variable substitution
-
- Variable substitution provides a simple way to include a previously stored variable in a command parameter. This is a simple mechanism, by which the variable to substitute is indicated by ${variableName}. Multiple variables can be substituted, and intermixed with static text.
-
- Example:
-
- store Mr title
- storeValue nameField surname
- store ${title} ${surname} fullname
- type textElement Full name is: ${fullname}
-
- Javascript evaluation
-
- Javascript evaluation provides the full power of javascript in constructing a command parameter. To use this mechanism, the entire parameter value must be prefixed by 'javascript{' with a trailing '}'. The text inside the braces is evaluated as a javascript expression, and can access previously stored variables using the storedVars map detailed above. Note that variable substitution cannot be combined with javascript evaluation.
-
- Example:
-
- store javascript{'merchant' + (new Date()).getTime()} merchantId
- type textElement javascript{storedVars['merchantId'].toUpperCase()}
\ No newline at end of file diff --git a/tests/FunctionalTests/config.php b/tests/FunctionalTests/config.php deleted file mode 100644 index 358fb8e2..00000000 --- a/tests/FunctionalTests/config.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php - -//error_reporting(E_ALL); -//restore_error_handler(); - -$SIMPLE_TEST = dirname(__FILE__).'/../UnitTests'; - -require_once($SIMPLE_TEST.'/simpletest/unit_tester.php'); -require_once($SIMPLE_TEST.'/simpletest/web_tester.php'); -require_once($SIMPLE_TEST.'/simpletest/mock_objects.php'); -require_once($SIMPLE_TEST.'/simpletest/reporter.php'); -require(dirname(__FILE__).'/selenium/php/selenium.php'); -//require_once(PradoTestConfig::framework().'/prado.php'); - -/** test configurations , OVERRIDE to suite your enviornment !!! **/ -class PradoTestConfig -{ - //directories containing test files - public function unit_test_groups() - { - return array(); - } - - //test directory base - public function tests_directory() - { - return dirname(__FILE__).'/protected/'; - } - - //prado frame work directory - public static function framework() - { - return realpath(dirname(__FILE__).'/../../framework/'); - } - - //do test that require mysql database connection? - public function doMySQLTests() - { - return false; - } - - //run the prado application - public function runApplication($appUrl='tests.php', $class='PradoApplicationTester') - { - $app = new $class($this, $appUrl); - $app->run(); - } - - //file patterns to accept for test - public function acceptPattern() - { - return '/\w+\.php/'; - } - - public function rejectPattern() - { - return null; - } - - public function getTestCase() - { - return isset($_GET['file']) ? $_GET['file'] : ''; - } -} - -//set up the PradoApplication Testing stub. - -class PradoApplicationTester -{ - protected $appUrl; - protected $testConfig; - - public function __construct($config, $appUrl) - { - $this->appUrl = $appUrl; - $this->testConfig = $config; - } - - public function run() - { - } - - public function getTestPage($file) - { - $parameter = $this->getTestServiceParameter($file); - return $this->appUrl.'?page='.$parameter; - } - - protected function getTestServiceParameter($file) - { - $file = strtr(realpath($file),'\\','/'); - $base = strtr(realpath($this->testConfig->tests_directory().'/pages/'),'\\','/'); - $search = array($base, '.php'); - $replace = array('', ''); - $pagePath = str_replace($search, $replace, $file); - return strtr(trim($pagePath,'/'),'/','.'); - } -} - -/** set up the tests **/ - -class PradoSimpleTester -{ - protected $tester; - - function __construct($tester) - { - $this->tester = $tester; - $this->tester->runApplication(); - } - - function getTests($name='All Tests') - { - $unit_tests = new GroupTest($name); - - foreach($this->tester->unit_test_groups() as $group => $dir) - { - $unit_tests->addTestCase($this->testSuits($group, $dir)); - } - return $unit_tests; - } - - protected function testSuits($group, $path) - { - $suite = new GroupTest($group); - $dir = dir($path); - - while (false !== ($entry = $dir->read())) - { - $file = strtr(realpath($path.'/'.$entry),'\\','/'); - $matchFile = $this->tester->getTestCase(); - if(is_file($file) && $this->filePatternMatch($file)) - { - if(empty($matchFile) || - (!empty($matchFile) - && is_int(strpos($file, $matchFile)))) - $suite->addTestFile($file); - } - - } - $dir->close(); - return $suite; - } - - protected function filePatternMatch($file) - { - $accept = $this->tester->acceptPattern(); - $reject = $this->tester->rejectPattern(); - - $valid = true; - if(!is_null($accept)) - $valid = $valid && preg_match($accept, $file); - if(!is_null($reject)) - $valid = $valid && !preg_match($reject, $file); - return $valid; - } -} - -?>
\ No newline at end of file diff --git a/tests/FunctionalTests/features.php b/tests/FunctionalTests/features.php index 8a3c87a6..9005db14 100644 --- a/tests/FunctionalTests/features.php +++ b/tests/FunctionalTests/features.php @@ -1,8 +1,8 @@ <?php -require(dirname(__FILE__).'/PradoTester.php'); +require('../test_tools/functional_tests.php'); -$tester=new PradoTester(dirname(__FILE__).'/features/tests'); +$tester=new PradoFunctionalTester(dirname(__FILE__).'/features/tests'); $tester->run(new SimpleReporter()); ?>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/protected/pages/CompositeControl.page b/tests/FunctionalTests/features/protected/pages/CompositeControl.page deleted file mode 100644 index b135445a..00000000 --- a/tests/FunctionalTests/features/protected/pages/CompositeControl.page +++ /dev/null @@ -1,12 +0,0 @@ -<com:TContent ID="Content">
-<h1>Composite Control Test</h1>
- <com:LabeledTextBox id="user" Label.Text="username:" /><br />
- <com:LabeledTextBox id="pass" Label.Text="password:" /><br />
- <com:TButton Text="Submit" />
-
-<com:TPanel Visible=<%= $this->user->TextBox->Text != "" %> >
-<h2>Result</h2>
- User: <%= $this->user->TextBox->Text %> Pass: <%= $this->pass->TextBox->Text %>
-</com:TPanel>
-
-</com:TContent>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/protected/pages/DatePicker.page b/tests/FunctionalTests/features/protected/pages/DatePicker.page deleted file mode 100644 index 261a6994..00000000 --- a/tests/FunctionalTests/features/protected/pages/DatePicker.page +++ /dev/null @@ -1,61 +0,0 @@ -<com:TContent ID="Content">
-
-<h1>TDatePicker Samples</h1>
-
-<table class="sampletable">
-
-<tr>
- <td class="samplenote">Default TDatePicker</td>
- <td class="sampleaction">
- <com:TDatePicker />
- </td>
-</tr>
-
-<tr>
- <td class="samplenote">Button Mode, pre-selected date</td>
- <td class="sampleaction">
- <com:TDatePicker Mode="Button" Date="20-10-2005"/>
- </td>
-</tr>
-
-<tr>
- <td class="samplenote">InputMode="DropDownList", custom DateFormat</td>
- <td class="sampleaction">
- <com:TDatePicker DateFormat="yyyy/MMM" InputMode="DropDownList"/>
- </td>
-</tr>
-
-<tr>
- <td class="samplenote">InputMode="DropDownList", custom DateFormat, Culture</td>
- <td class="sampleaction">
- <com:TDatePicker DateFormat="MMM/yyyy" Culture="fr" InputMode="DropDownList"/>
- </td>
-</tr>
-
-
-<tr>
- <td class="samplenote">Custom DateFormat, culture, ImageButton mode, pre-selected date</td>
- <td class="sampleaction">
- <com:TDatePicker Mode="ImageButton" Culture="zh_CN"
- DateFormat="日期:yyyy年M月d日"
- Timestamp=<%= @strtotime("-1 year") %>/>
- </td>
-</tr>
-
-<tr>
- <td class="samplenote">Custom DateFormat, DropDownList, pre-selected date set in as Text</td>
- <td class="sampleaction">
- <com:TDatePicker DateFormat="yyyy/MMMM/dd" Date="2005/05/15" InputMode="DropDownList"/>
- </td>
-</tr>
-
-<tr>
- <td class="samplenote">DropDownList, pre-selected date as integer</td>
- <td class="sampleaction">
- <com:TDatePicker InputMode="DropDownList" Timestamp=<%= @strtotime("-1 month") %>/>
- </td>
-</tr>
-
-</table>
-
-</com:TContent>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/protected/pages/HtmlArea.page b/tests/FunctionalTests/features/protected/pages/HtmlArea.page deleted file mode 100644 index 3936e68c..00000000 --- a/tests/FunctionalTests/features/protected/pages/HtmlArea.page +++ /dev/null @@ -1,25 +0,0 @@ -
-<com:TContent ID="Content">
-
- <com:THtmlArea ID="text1" />
-
- <com:TRequiredFieldValidator
- ControlToValidate="text1"
- ErrorMessage="*" />
-
- <com:TButton ID="button1" Text="submit 1" />
-
- <com:TButton ID="button2" Text="submit 2" />
-
- <com:THtmlArea ID="text2" />
-
- <com:TRequiredFieldValidator
- ControlToValidate="text2"
- ValidationGroup="group2"
- ErrorMessage="*" />
-
- <com:TButton ID="button3" ValidationGroup="group2" Text="submit 3" />
-
- <com:TButton ID="button4" ValidationGroup="group2" Text="submit 4" />
-
-</com:TContent>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page b/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page index 1a97a249..7fca0f56 100644 --- a/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page +++ b/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page @@ -93,5 +93,14 @@ </fieldset>
+<com:TLinkButton ID="linkButton1"
+ Text="Click Me"
+ OnClick="linkButton1_Clicked">
+ <prop:Attributes.onclick>
+ if(!confirm('<%= Prado::localize("Confirm Delete") %>'))
+ return false;
+ </prop:Attributes.onclick>
+</com:TLinkButton>
+
</com:TContent>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/tests/CompositeControlTestCase.php b/tests/FunctionalTests/features/tests/CompositeControlTestCase.php deleted file mode 100644 index dda3f63b..00000000 --- a/tests/FunctionalTests/features/tests/CompositeControlTestCase.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php
-/*
- * Created on 28/04/2006
- */
-
-class CompositeControlTestCase extends SeleniumTestCase
-{
-
- function test()
- {
- $base = "ctl0_Content_";
- $this->open("features/index.php?page=CompositeControl", "");
- $this->verifyTextPresent("Composite Control Test", "");
- $this->type("{$base}user_textbox", "Hello");
- $this->type("{$base}pass_textbox", "world");
- $this->clickAndWait("//input[@type='submit' and @value='Submit']", "");
- $this->verifyTextPresent("Result", "");
- $this->verifyTextPresent("User: Hello Pass: world", "");
- }
-
-}
-
-?>
diff --git a/tests/FunctionalTests/quickstart.php b/tests/FunctionalTests/quickstart.php index aa6dc119..3493a907 100644..100755 --- a/tests/FunctionalTests/quickstart.php +++ b/tests/FunctionalTests/quickstart.php @@ -1,8 +1,8 @@ <?php -require(dirname(__FILE__).'/PradoTester.php'); +require('../test_tools/functional_tests.php'); -$tester=new PradoTester(dirname(__FILE__).'/quickstart'); +$tester=new PradoFunctionalTester(dirname(__FILE__).'/quickstart'); $tester->run(new SimpleReporter()); ?>
\ No newline at end of file diff --git a/tests/FunctionalTests/selenium/core/SeleneseRunner.html b/tests/FunctionalTests/selenium/core/SeleneseRunner.html deleted file mode 100755 index 49eef6f6..00000000 --- a/tests/FunctionalTests/selenium/core/SeleneseRunner.html +++ /dev/null @@ -1,111 +0,0 @@ -<html> - -<!-- -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. ---> -<HTA:APPLICATION ID="SeleniumHTARunner" APPLICATIONNAME="Selenium" > -<head> -<meta content="text/html; charset=ISO-8859-1" -http-equiv="content-type"> -<title>Selenium Functional Test Runner</title> -<link rel="stylesheet" type="text/css" href="selenium.css" /> -<script language="JavaScript" type="text/javascript" src="jsunit/app/jsUnitCore.js"></script> -<script type="text/javascript" src="scripts/xmlextras.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-browserdetect.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-browserbot.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/prototype-1.4.0.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/find_matching_child.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-api.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-commandhandlers.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-executionloop.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-seleneserunner.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-logging.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-version.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/htmlutils.js"></script> -<script language="JavaScript" type="text/javascript" src="xpath/misc.js"></script> -<script language="JavaScript" type="text/javascript" src="xpath/dom.js"></script> -<script language="JavaScript" type="text/javascript" src="xpath/xpath.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/user-extensions.js"></script> -<script language="JavaScript" type="text/javascript"> - function openDomViewer() { - var autFrame = document.getElementById('myiframe'); - var autFrameDocument = getIframeDocument(autFrame); - var domViewer = window.open(getDocumentBase(document) + 'domviewer/domviewer.html'); - domViewer.rootDocument = autFrameDocument; - return false; - } - - function cleanUp() { - if (LOG != null) { - LOG.close(); - } - } - -</script> -<script> -</script> -</head> - -<body onLoad="runTest()" onUnload="cleanUp()"> - -<table border="1" style="height: 100%;"> - <tr> - <td width="50%" height="30%"> - <table> - <tr> - <td> - <img src="selenium-logo.png"> - </td> - <td> - <h1><a href="http://selenium.thoughtworks.com" >Selenium</a> Functional Testing for Web Apps</h1> - Open Source From <a href="http://www.thoughtworks.com">ThoughtWorks, Inc</a> and Friends - <form action=""> - <br/>Slow Mode:<INPUT TYPE="CHECKBOX" NAME="FASTMODE" VALUE="YES" onmouseup="slowClicked()"> - - <fieldset> - <legend>Tools</legend> - - <button type="button" id="domViewer1" onclick="openDomViewer();"> - View DOM - </button> - <button type="button" onclick="LOG.show();"> - Show Log - </button> - </fieldset> - - </form> - - </td> - </tr> - </table> - <form action=""> - <label id="context" name="context"></label> - </form> - </td> - <td width="50%" height="30%"> - <b>Last Four Test Commands:</b><br/> - <div id="commandList"></div> - </td> - </tr> - <tr> - <td colspan="2" height="70%"> - <iframe name="myiframe" id="myiframe" src="" height="100%" width="100%"></iframe> - </td> - </tr> -</table> - -</body> -</html> - diff --git a/tests/FunctionalTests/selenium/core/SeleniumLog.html b/tests/FunctionalTests/selenium/core/SeleniumLog.html deleted file mode 100755 index 291e1f77..00000000 --- a/tests/FunctionalTests/selenium/core/SeleniumLog.html +++ /dev/null @@ -1,79 +0,0 @@ -<html> - -<head> -<title>Selenium Log Console</title> -<link id="cssLink" rel="stylesheet" href="selenium.css" /> - -</head> -<body id="logging-console"> - -<script language="JavaScript"> - -var logLevels = { - debug: 0, - info: 1, - warn: 2, - error: 3 -}; - -var logLevelThreshold = null; - -function getThresholdLevel() { - var buttons = document.getElementById('logLevelChooser').level; - for (var i = 0; i < buttons.length; i++) { - if (buttons[i].checked) { - return buttons[i].value; - } - } -} - -function setThresholdLevel(logLevel) { - logLevelThreshold = logLevel; - var buttons = document.getElementById('logLevelChooser').level; - for (var i = 0; i < buttons.length; i++) { - if (buttons[i].value==logLevel) { - buttons[i].checked = true; - } - else { - buttons[i].checked = false; - } - } -} - -function append(message, logLevel) { - if (logLevelThreshold==null) { - logLevelThreshold = getThresholdLevel(); - } - if (logLevels[logLevel] < logLevels[logLevelThreshold]) { - return; - } - var log = document.getElementById('log'); - var newEntry = document.createElement('li'); - newEntry.className = logLevel; - newEntry.appendChild(document.createTextNode(message)); - log.appendChild(newEntry); - if (newEntry.scrollIntoView) { - newEntry.scrollIntoView(); - } -} - -</script> - -<div id="banner"> - <form id="logLevelChooser"> - <input id="level-error" type="radio" name="level" - value="error" /><label for="level-error">Error</label> - <input id="level-warn" type="radio" name="level" - value="warn" /><label for="level-warn">Warn</label> - <input id="level-info" type="radio" name="level" checked="yes" - value="info" /><label for="level-info">Info</label> - <input id="level-debug" type="radio" name="level" - value="debug" /><label for="level-debug">Debug</label> - </form> - <h1>Selenium Log Console</h1> -</div> - -<ul id="log"></ul> - -</body> -</html> diff --git a/tests/FunctionalTests/selenium/core/TestPrompt.html b/tests/FunctionalTests/selenium/core/TestPrompt.html deleted file mode 100755 index f62bad87..00000000 --- a/tests/FunctionalTests/selenium/core/TestPrompt.html +++ /dev/null @@ -1,93 +0,0 @@ -<html>
-<!--
-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.
--->
-
-<head>
-<meta content="text/html; charset=ISO-8859-1"
-http-equiv="content-type">
-<title>Select a Test Suite</title>
-<script language="JavaScript" type="text/javascript" src="scripts/selenium-browserdetect.js"></script>
-<script>
-
-function load() {
- if (browserVersion.isHTA) {
- document.getElementById("save-div").style.display = "inline";
- }
-}
-
-function autoCheck() {
- var auto = document.getElementById("auto");
- var autoDiv = document.getElementById("auto-div");
- if (auto.checked) {
- autoDiv.style.display = "inline";
-
- } else {
- autoDiv.style.display = "none";
- }
-}
-
-function saveCheck() {
- var results = document.getElementById("results");
- var check = document.getElementById("save").checked;
- if (check) {
- results.firstChild.nodeValue = "Results file ";
- document.getElementById("resultsUrl").value = "results.html";
- } else {
- results.firstChild.nodeValue = "Results URL ";
- document.getElementById("resultsUrl").value = "../postResults";
- }
-}
-
-function go() {
-
- var inputs = document.getElementsByTagName("input");
- var queryString = "";
- for (var i = 0; i < inputs.length; i++) {
- var elem = inputs[i];
- var name = elem.name;
- var value = elem.value;
- if (elem.checked) {
- value = "true";
- }
- queryString += escape(name) + "=" + escape(value);
- if (i < (inputs.length - 1)) {
- queryString += "&";
- }
- }
-
- window.parent.queryString = queryString;
- window.parent.loadSuiteFrame();
- return false;
-}
-</script>
-</head>
-<body onload="load()" style="font-size: x-small">
-<form id="prompt" target="_top" method="GET" onsubmit="return go();" action="TestRunner.html">
-<p>Select an HTML test suite:</p>
-<input id="test" name="test" size="30" value="../tests/TestSuite.html"/>
-<p><label for="auto">Auto-run </label><input id="auto" type="checkbox" name="auto" value="false" onclick="autoCheck();"/>
-<div id="auto-div" style="display: none">
-<label for="close" >Close afterwards </label><input id="close" type="checkbox" name="close" />
-<div id="save-div" style="display: none">
- <br/><label for="save">Save to file </label><input id="save" type="checkbox" name="save" onclick="saveCheck();"/>
-</div>
-</p>
-<p id="results" >Results URL <input id="resultsUrl" name="resultsUrl" value="../postResults"/></p>
-</div>
-<p><input type="submit" value="go"/></p>
-</form>
-</body>
-</html>
\ No newline at end of file diff --git a/tests/FunctionalTests/selenium/core/TestRunner-splash.html b/tests/FunctionalTests/selenium/core/TestRunner-splash.html deleted file mode 100755 index da2acdce..00000000 --- a/tests/FunctionalTests/selenium/core/TestRunner-splash.html +++ /dev/null @@ -1,55 +0,0 @@ -<!--
-Copyright 2005 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.
--->
-
-<html>
-<link rel="stylesheet" type="text/css" href="selenium.css" />
-<body>
-<table width="100%">
-
-<tr>
- <th>↑</th>
- <th>↑</th>
- <th>↑</th>
-</tr>
-<tr>
- <th width="25%">Test Suite</th>
- <th width="50%">Current Test</th>
- <th width="25%">Control Panel</th>
-</tr>
-<tr><td> </td></tr>
-
-<tr>
-<td></td>
-<td class="selenium splash">
-
-<img src="selenium-logo.png" align="right">
-
-<h1>Selenium</h1>
-<h2>by <a href="http://www.thoughtworks.com">ThoughtWorks</a> and friends</h2>
-
-<p>
-For more information on Selenium, visit
-
-<pre>
- <a href="http://selenium.openqa.org" target="_blank">http://selenium.openqa.org</a>
-</pre>
-
-</td>
-<tr>
-
-</table>
-</body>
-</html>
diff --git a/tests/FunctionalTests/selenium/core/TestRunner.html b/tests/FunctionalTests/selenium/core/TestRunner.html deleted file mode 100755 index f933ab9f..00000000 --- a/tests/FunctionalTests/selenium/core/TestRunner.html +++ /dev/null @@ -1,157 +0,0 @@ -<html> - -<head> -<HTA:APPLICATION ID="SeleniumHTARunner" APPLICATIONNAME="Selenium" > -<!-- the previous line is only relevant if you rename this - file to "TestRunner.hta" --> - -<!-- The copyright notice and other comments have been moved to after the HTA declaration, - to work-around a bug in IE on Win2K whereby the HTA application doesn't function correctly --> -<!-- -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. ---> -<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" /> - -<title>Selenium Functional Test Runner</title> -<link rel="stylesheet" type="text/css" href="selenium.css" /> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-browserdetect.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-browserbot.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/prototype-1.4.0.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/find_matching_child.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-api.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-commandhandlers.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-executionloop.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-testrunner.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-logging.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/selenium-version.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/htmlutils.js"></script> -<script language="JavaScript" type="text/javascript" src="xpath/misc.js"></script> -<script language="JavaScript" type="text/javascript" src="xpath/dom.js"></script> -<script language="JavaScript" type="text/javascript" src="xpath/xpath.js"></script> -<script language="JavaScript" type="text/javascript" src="scripts/user-extensions.js"></script> -<script language="JavaScript" type="text/javascript"> - function openDomViewer() { - var autFrame = document.getElementById('myiframe'); - var autFrameDocument = getIframeDocument(autFrame); - this.rootDocument = autFrameDocument; - var domViewer = window.open(getDocumentBase(document) + 'domviewer/domviewer.html'); - return false; - } -</script> -</head> - -<body onLoad="start();"> - - <table class="layout"> - <form action="" name="controlPanel"> - - <!-- Suite, Test, Control Panel --> - - <tr class="selenium"> - <td width="25%" height="30%" ><iframe name="testSuiteFrame" id="testSuiteFrame" src="./TestPrompt.html" application="yes"></iframe></td> - <td width="50%" height="30%" ><iframe name="testFrame" id="testFrame" application="yes"></iframe></td> - - <td width="25%"> - <table class="layout"> - <tr class="selenium"> - <th width="25%" height="1" class="header"> - <h1><a href="http://selenium.thoughtworks.com" title="The Selenium Project">Selenium</a> TestRunner</h1> - </th> - </tr> - <tr> - <td width="25%" height="30%" id="controlPanel"> - - <fieldset> - <legend>Execute Tests</legend> - - <div> - <input id="modeRun" type="radio" name="runMode" value="0" checked="checked"/><label for="modeRun">Run</label> - <input id="modeWalk" type="radio" name="runMode" value="500" /><label for="modeWalk">Walk</label> - <input id="modeStep" type="radio" name="runMode" value="-1" /><label for="modeStep">Step</label> - </div> - - <div> - <button type="button" id="runSuite" onClick="startTestSuite();" - title="Run the entire Test-Suite"> - <strong>All</strong> - </button> - <button type="button" id="runTest" onClick="runSingleTest();" - title="Run the current Test"> - <em>Selected</em> - </button> - <button type="button" id="continueTest" disabled="disabled" - title="Continue the Test"> - Continue - </button> - </div> - - </fieldset> - - <table id="stats" align="center"> - <tr> - <td colspan="2" align="right">Elapsed:</td> - <td id="elapsedTime" colspan="2">00.00</td> - </tr> - <tr> - <th colspan="2">Tests</th> - <th colspan="2">Commands</th> - </tr> - <tr> - <td class="count" id="testRuns">0</td> - <td>run</td> - <td class="count" id="commandPasses">0</td> - <td>passed</td> - </tr> - <tr> - <td class="count" id="testFailures">0</td> - <td>failed</td> - <td class="count" id="commandFailures">0</td> - <td>failed</td> - </tr> - <tr> - <td colspan="2"></td> - <td class="count" id="commandErrors">0</td> - <td>incomplete</td> - </tr> - </table> - - <fieldset> - <legend>Tools</legend> - - <button type="button" id="domViewer1" onClick="openDomViewer();"> - View DOM - </button> - <button type="button" onClick="LOG.show();"> - Show Log - </button> - - </fieldset> - - </td> - </tr> - </table> - </td> - </tr> - - <!-- AUT --> - - <tr> - <td colspan="3" height="70%"><iframe name="myiframe" id="myiframe" src="TestRunner-splash.html"></iframe></td> - </tr> - </form> - </table> - -</body> -</html> diff --git a/tests/FunctionalTests/selenium/core/domviewer/butmin.gif b/tests/FunctionalTests/selenium/core/domviewer/butmin.gif Binary files differdeleted file mode 100755 index 7b7cefd5..00000000 --- a/tests/FunctionalTests/selenium/core/domviewer/butmin.gif +++ /dev/null diff --git a/tests/FunctionalTests/selenium/core/domviewer/butplus.gif b/tests/FunctionalTests/selenium/core/domviewer/butplus.gif Binary files differdeleted file mode 100755 index 6d68cfa9..00000000 --- a/tests/FunctionalTests/selenium/core/domviewer/butplus.gif +++ /dev/null diff --git a/tests/FunctionalTests/selenium/core/domviewer/domviewer.css b/tests/FunctionalTests/selenium/core/domviewer/domviewer.css deleted file mode 100755 index b64b2435..00000000 --- a/tests/FunctionalTests/selenium/core/domviewer/domviewer.css +++ /dev/null @@ -1,298 +0,0 @@ -/******************************************************************************
-* Defines default styles for site pages. *
-******************************************************************************/
-.hidden {
- display: none;
-}
-
-img{
- display: inline;
- border: none;
-}
-
-.box{
- background: #fcfcfc;
- border: 1px solid #000;
- border-color: blue;
- color: #000000;
- margin: 10px auto;
- padding: 3px;
- vertical-align: bottom;
-}
-a {
- text-decoration: none;
-}
-
-body {
- background-color: #ffffff;
- color: #000000;
- font-family: Arial, Helvetica, sans-serif;
- font-size: 10pt;
-}
-
-h2 {
- font-size: 140%;
-}
-
-h3 {
- font-size: 120%;
-}
-
-h4 {
- font-size: 100%;
-}
-
-pre {
- font-family: Courier New, Courier, monospace;
- font-size: 80%;
-}
-
-td, th {
- font-family: Arial, Helvetica, sans-serif;
- font-size: 10pt;
- text-align: left;
- vertical-align: top;
-}
-
-th {
- font-weight: bold;
- vertical-align: bottom;
-}
-
-ul {
- list-style-type: square;
-}
-
-#demoBox {
- border-color: #000000;
- border-style: solid;
- border-width: 1px;
- padding: 8px;
- width: 24em;
-}
-
-.footer {
- margin-bottom: 0px;
- text-align: center;
-}
-
-/* Boxed table styles */
-
-table.boxed {
- border-spacing: 2px;
- empty-cells: hide;
-}
-
-td.boxed, th.boxed, th.boxedHeader {
- background-color: #ffffff;
- border-color: #000000;
- border-style: solid;
- border-width: 1px;
- color: #000000;
- padding: 2px;
- padding-left: 8px;
- padding-right: 8px;
-}
-
-th.boxed {
- background-color: #c0c0c0;
-}
-
-th.boxedHeader {
- background-color: #808080;
- color: #ffffff;
-}
-
-a.object {
- color: #0000ff;
-}
-
-li {
- white-space: nowrap;
-}
-
-ul {
- list-style-type: square;
- margin-left: 0px;
- padding-left: 1em;
-}
-
-.boxlevel1{
- background: #FFD700;
-}
-
-.boxlevel2{
- background: #D2691E;
-}
-
-.boxlevel3{
- background: #DCDCDC;
-}
-
-.boxlevel4{
- background: #F5F5F5;
-}
-
-.boxlevel5{
- background: #BEBEBE;
-}
-
-.boxlevel6{
- background: #D3D3D3;
-}
-
-.boxlevel7{
- background: #A9A9A9;
-}
-
-.boxlevel8{
- background: #191970;
-}
-
-.boxlevel9{
- background: #000080;
-}
-
-.boxlevel10{
- background: #6495ED;
-}
-
-.boxlevel11{
- background: #483D8B;
-}
-
-.boxlevel12{
- background: #6A5ACD;
-}
-
-.boxlevel13{
- background: #7B68EE;
-}
-
-.boxlevel14{
- background: #8470FF;
-}
-
-.boxlevel15{
- background: #0000CD;
-}
-
-.boxlevel16{
- background: #4169E1;
-}
-
-.boxlevel17{
- background: #0000FF;
-}
-
-.boxlevel18{
- background: #1E90FF;
-}
-
-.boxlevel19{
- background: #00BFFF;
-}
-
-.boxlevel20{
- background: #87CEEB;
-}
-
-.boxlevel21{
- background: #B0C4DE;
-}
-
-.boxlevel22{
- background: #ADD8E6;
-}
-
-.boxlevel23{
- background: #00CED1;
-}
-
-.boxlevel24{
- background: #48D1CC;
-}
-
-.boxlevel25{
- background: #40E0D0;
-}
-
-.boxlevel26{
- background: #008B8B;
-}
-
-.boxlevel27{
- background: #00FFFF;
-}
-
-.boxlevel28{
- background: #E0FFFF;
-}
-
-.boxlevel29{
- background: #5F9EA0;
-}
-
-.boxlevel30{
- background: #66CDAA;
-}
-
-.boxlevel31{
- background: #7FFFD4;
-}
-
-.boxlevel32{
- background: #006400;
-}
-
-.boxlevel33{
- background: #556B2F;
-}
-
-.boxlevel34{
- background: #8FBC8F;
-}
-
-.boxlevel35{
- background: #2E8B57;
-}
-
-.boxlevel36{
- background: #3CB371;
-}
-
-.boxlevel37{
- background: #20B2AA;
-}
-
-.boxlevel38{
- background: #00FF7F;
-}
-
-.boxlevel39{
- background: #7CFC00;
-}
-
-.boxlevel40{
- background: #90EE90;
-}
-
-.boxlevel41{
- background: #00FF00;
-}
-
-.boxlevel41{
- background: #7FFF00;
-}
-
-.boxlevel42{
- background: #00FA9A;
-}
-
-.boxlevel43{
- background: #ADFF2F;
-}
-
-.boxlevel44{
- background: #32CD32;
-}
\ No newline at end of file diff --git a/tests/FunctionalTests/selenium/core/domviewer/domviewer.html b/tests/FunctionalTests/selenium/core/domviewer/domviewer.html deleted file mode 100755 index 9158a50f..00000000 --- a/tests/FunctionalTests/selenium/core/domviewer/domviewer.html +++ /dev/null @@ -1,16 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - <head> - <title>DOM Viewer</title> - <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> - <link rel="stylesheet" type="text/css" href="domviewer.css"/> - <script type="text/javascript" src="selenium-domviewer.js"></script> - </head> - <body onload="loadDomViewer();"> - <h3>DOM Viewer</h3> - <p> This page is generated using JavaScript. If you see this text, your - browser doesn't support JavaScript.</p> - </body> - -</html> diff --git a/tests/FunctionalTests/selenium/core/domviewer/selenium-domviewer.js b/tests/FunctionalTests/selenium/core/domviewer/selenium-domviewer.js deleted file mode 100755 index 941aab16..00000000 --- a/tests/FunctionalTests/selenium/core/domviewer/selenium-domviewer.js +++ /dev/null @@ -1,205 +0,0 @@ -var HIDDEN="hidden"; -var LEVEL = "level"; -var PLUS_SRC="butplus.gif"; -var MIN_SRC="butmin.gif"; -var newRoot; -var maxColumns=1; - -function loadDomViewer() { - // See if the rootDocument variable has been set on this window. - var rootDocument = window.rootDocument; - - // If not look to the opener for an explicity rootDocument variable, otherwise, use the opener document - if (!rootDocument && window.opener) { - rootDocument = window.opener.rootDocument || window.opener.document; - } - - if (rootDocument) { - document.body.innerHTML = displayDOM(rootDocument); - } - else { - document.body.innerHTML = "<b>Must specify rootDocument for window. This can be done by setting the rootDocument variable on this window, or on the opener window for a popup window.</b>"; - } -} - - -function displayDOM(root){ - var str = ""; - str+="<table>"; - str += treeTraversal(root,0); - // to make table columns work well. - str += "<tr>"; - for (var i=0; i < maxColumns; i++) { - str+= "<td> </td>"; - } - str += "</tr>"; - str += "</table>"; - return str; -} - -function checkForChildren(element){ - if(!element.hasChildNodes()) - return false; - - var nodes = element.childNodes; - var size = nodes.length; - var count=0; - - for(var i=0; i< size; i++){ - var node = nodes.item(i); - //if(node.toString()=="[object Text]"){ - //this is equalent to the above - //but will work with more browsers - if(node.nodeType!=1){ - count++; - } - } - - if(count == size) - return false; - else - return true; -} - -function treeTraversal(root, level){ - var str = ""; - var nodes= null; - var size = null; - //it is supposed to show the last node, - //but the last node is always nodeText type - //and we don't show it - if(!root.hasChildNodes()) - return "";//displayNode(root,level,false); - - nodes = root.childNodes; - size = nodes.length; - - for(var i=0; i< size; i++){ - var element = nodes.item(i); - //if the node is textNode, don't display - if(element.nodeType==1){ - str+= displayNode(element,level,checkForChildren(element)); - str+=treeTraversal(element, level+1); - } - } - return str; -} - -function displayNode(element, level, isLink){ - nodeContent = getNodeContent(element); - columns = Math.round((nodeContent.length / 12) + 0.5); - if (columns + level > maxColumns) { - maxColumns = columns + level; - } - var str ="<tr class='"+LEVEL+level+"'>"; - for (var i=0; i < level; i++) - str+= "<td> </td>"; - str+="<td colspan='"+ columns +"' class='box"+" boxlevel"+level+"' >"; - if(isLink){ - str+='<a onclick="hide(this);return false;" href="javascript:void();">'; - str+='<img src="'+MIN_SRC+'" />'; - } - str += nodeContent; - if(isLink) - str+="</a></td></tr>"; - return str; -} - -function getNodeContent(element) { - - str = ""; - id =""; - if (element.id != null && element.id != "") { - id = " ID(" + element.id +")"; - } - name =""; - if (element.name != null && element.name != "") { - name = " NAME(" + element.name + ")"; - } - value =""; - if (element.value != null && element.value != "") { - value = " VALUE(" + element.value + ")"; - } - href =""; - if (element.href != null && element.href != "") { - href = " HREF(" + element.href + ")"; - } - clazz = ""; - if (element.className != null && element.className != "") { - clazz = " CLASS(" + element.className + ")"; - } - src = ""; - if (element.src != null && element.src != "") { - src = " SRC(" + element.src + ")"; - } - alt = ""; - if (element.alt != null && element.alt != "") { - alt = " ALT(" + element.alt + ")"; - } - type = ""; - if (element.type != null && element.type != "") { - type = " TYPE(" + element.type + ")"; - } - text =""; - if (element.text != null && element.text != "" && element.text != "undefined") { - text = " #TEXT(" + trim(element.text) +")"; - } - str+=" <b>"+ element.nodeName + id + alt + type + clazz + name + value + href + src + text + "</b>"; - return str; - -} - -function trim(val) { - val2 = val.substring(0,40) + " "; - var spaceChr = String.fromCharCode(32); - var length = val2.length; - var retVal = ""; - var ix = length -1; - - while(ix > -1){ - if(val2.charAt(ix) == spaceChr) { - } else { - retVal = val2.substring(0, ix +1); - break; - } - ix = ix-1; - } - if (val.length > 40) { - retVal += "..."; - } - return retVal; -} - -function hide(hlink){ - var isHidden = false; - var image = hlink.firstChild; - if(image.src.toString().indexOf(MIN_SRC)!=-1){ - image.src=PLUS_SRC; - isHidden=true; - }else{ - image.src=MIN_SRC; - } - var rowObj= hlink.parentNode.parentNode; - var rowLevel = parseInt(rowObj.className.substring(LEVEL.length)); - - var sibling = rowObj.nextSibling; - var siblingLevel = sibling.className.substring(LEVEL.length); - if(siblingLevel.indexOf(HIDDEN)!=-1){ - siblingLevel = siblingLevel.substring(0,siblingLevel.length - HIDDEN.length-1); - } - siblingLevel=parseInt(siblingLevel); - while(sibling!=null && rowLevel<siblingLevel){ - if(isHidden){ - sibling.className += " "+ HIDDEN; - }else if(!isHidden && sibling.className.indexOf(HIDDEN)!=-1){ - var str = sibling.className; - sibling.className=str.substring(0, str.length - HIDDEN.length-1); - } - sibling = sibling.nextSibling; - siblingLevel = parseInt(sibling.className.substring(LEVEL.length)); - } -} - -function LOG(message) { - window.opener.LOG.warn(message); -} diff --git a/tests/FunctionalTests/selenium/core/scripts/find_matching_child.js b/tests/FunctionalTests/selenium/core/scripts/find_matching_child.js deleted file mode 100755 index 5b635a27..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/find_matching_child.js +++ /dev/null @@ -1,69 +0,0 @@ -/*
- * 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.
- *
- */
-
-Element.findMatchingChildren = function(element, selector) {
- var matches = $A([]);
-
- var childCount = element.childNodes.length;
- for (var i=0; i<childCount; i++) {
- var child = element.childNodes[i];
- if (selector(child)) {
- matches.push(child);
- } else {
- childMatches = Element.findMatchingChildren(child, selector);
- matches.push(childMatches);
- }
- }
-
- return matches.flatten();
-}
-
-ELEMENT_NODE_TYPE = 1;
-
-Element.findFirstMatchingChild = function(element, selector) {
-
- var childCount = element.childNodes.length;
- for (var i=0; i<childCount; i++) {
- var child = element.childNodes[i];
- if (child.nodeType == ELEMENT_NODE_TYPE) {
- if (selector(child)) {
- return child;
- }
- result = Element.findFirstMatchingChild(child, selector);
- if (result) {
- return result;
- }
- }
- }
- return null;
-}
-
-Element.findFirstMatchingParent = function(element, selector) {
- var current = element.parentNode;
- while (current != null) {
- if (selector(current)) {
- break;
- }
- current = current.parentNode;
- }
- return current;
-}
-
-Element.findMatchingChildById = function(element, id) {
- return Element.findFirstMatchingChild(element, function(element){return element.id==id} );
-}
-
diff --git a/tests/FunctionalTests/selenium/core/scripts/htmlutils.js b/tests/FunctionalTests/selenium/core/scripts/htmlutils.js deleted file mode 100755 index fcb1ee44..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/htmlutils.js +++ /dev/null @@ -1,463 +0,0 @@ -/* - * 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. - * - */ - -// This script contains some HTML utility functions that -// make it possible to handle elements in a way that is -// compatible with both IE-like and Mozilla-like browsers - -String.prototype.trim = function() { - var result = this.replace( /^\s+/g, "" );// strip leading - return result.replace( /\s+$/g, "" );// strip trailing -}; -String.prototype.lcfirst = function() { - return this.charAt(0).toLowerCase() + this.substr(1); -}; -String.prototype.ucfirst = function() { - return this.charAt(0).toUpperCase() + this.substr(1); -}; -String.prototype.startsWith = function(str) { - return this.indexOf(str) == 0; -}; - -// Returns the text in this element -function getText(element) { - var text = ""; - - if(browserVersion.isFirefox && browserVersion.firefoxVersion >= "1.5") - { - var dummyElement = element.cloneNode(true); - renderWhitespaceInTextContent(dummyElement); - text = dummyElement.textContent; - } else if (browserVersion.isOpera) { - var dummyElement = element.cloneNode(true); - renderWhitespaceInTextContent(dummyElement); - text = dummyElement.innerText; - text = xmlDecode(text); - } - else if(element.textContent) - { - text = element.textContent; - } - else if(element.innerText) - { - text = element.innerText; - } - - text = normalizeNewlines(text); - text = normalizeSpaces(text); - - return text.trim(); -} - -function renderWhitespaceInTextContent(element) { - // Remove non-visible newlines in text nodes - if (element.nodeType == Node.TEXT_NODE) - { - element.data = element.data.replace(/\n|\r|\t/g, " "); - return; - } - - if (element.nodeType == Node.COMMENT_NODE) - { - element.data = ""; - return; - } - - // Don't modify PRE elements - if (element.tagName == "PRE") - { - return; - } - - // Handle inline element that force newlines - if (tagIs(element, ["BR", "HR"])) - { - // Replace this element with a newline text element - element.parentNode.replaceChild(element.ownerDocument.createTextNode("\n"), element) - } - - for (var i = 0; i < element.childNodes.length; i++) - { - var child = element.childNodes.item(i) - renderWhitespaceInTextContent(child); - } - - // Handle block elements that introduce newlines -// -- From HTML spec: -//<!ENTITY % block -// "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT | -// BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS"> - if (tagIs(element, ["P", "DIV"])) - { - element.appendChild(element.ownerDocument.createTextNode("\n"), element) - } - -} - -function tagIs(element, tags) -{ - var tag = element.tagName; - for (var i = 0; i < tags.length; i++) - { - if (tags[i] == tag) - { - return true; - } - } - return false; -} - -/** - * Convert all newlines to \m - */ -function normalizeNewlines(text) -{ - return text.replace(/\r\n|\r/g, "\n"); -} - -/** - * Replace multiple sequential spaces with a single space, and then convert to space. - */ -function normalizeSpaces(text) -{ - // IE has already done this conversion, so doing it again will remove multiple nbsp - if (browserVersion.isIE) - { - return text; - } - - // Replace multiple spaces with a single space - // TODO - this shouldn't occur inside PRE elements - text = text.replace(/\ +/g, " "); - - // Replace with a space - var pat = String.fromCharCode(160); // Opera doesn't like /\240/g - var re = new RegExp(pat, "g"); - return text.replace(re, " "); -} - -function xmlDecode(text) { - text = text.replace(/"/g, '"'); - text = text.replace(/'/g, "'"); - text = text.replace(/</g, "<"); - text = text.replace(/>/g, ">"); - text = text.replace(/&/g, "&"); - return text; -} - -// Sets the text in this element -function setText(element, text) { - if(element.textContent) { - element.textContent = text; - } else if(element.innerText) { - element.innerText = text; - } -} - -// Get the value of an <input> element -function getInputValue(inputElement) { - if (inputElement.type.toUpperCase() == 'CHECKBOX' || - inputElement.type.toUpperCase() == 'RADIO') - { - return (inputElement.checked ? 'on' : 'off'); - } - return inputElement.value; -} - -/* Fire an event in a browser-compatible manner */ -function triggerEvent(element, eventType, canBubble) { - canBubble = (typeof(canBubble) == undefined) ? true : canBubble; - if (element.fireEvent) { - element.fireEvent('on' + eventType); - } - else { - var evt = document.createEvent('HTMLEvents'); - evt.initEvent(eventType, canBubble, true); - element.dispatchEvent(evt); - } -} - -function triggerKeyEvent(element, eventType, keycode, canBubble) { - canBubble = (typeof(canBubble) == undefined) ? true : canBubble; - if (element.fireEvent) { - keyEvent = parent.frames['myiframe'].document.createEventObject(); - keyEvent.keyCode=keycode; - element.fireEvent('on' + eventType, keyEvent); - } - else { - var evt; - if( window.KeyEvent ) { - evt = document.createEvent('KeyEvents'); - evt.initKeyEvent(eventType, true, true, window, false, false, false, false, keycode, keycode); - } else { - evt = document.createEvent('UIEvents'); - evt.initUIEvent( eventType, true, true, window, 1 ); - evt.keyCode = keycode; - } - - element.dispatchEvent(evt); - } -} - -/* Fire a mouse event in a browser-compatible manner */ -function triggerMouseEvent(element, eventType, canBubble) { - canBubble = (typeof(canBubble) == undefined) ? true : canBubble; - if (element.fireEvent) { - element.fireEvent('on' + eventType); - } - else { - var evt = document.createEvent('MouseEvents'); - if (evt.initMouseEvent) - { - evt.initMouseEvent(eventType, canBubble, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null) - } - else - { - // Safari - // TODO we should be initialising other mouse-event related attributes here - evt.initEvent(eventType, canBubble, true); - } - element.dispatchEvent(evt); - } -} - -function removeLoadListener(element, command) { - if (window.removeEventListener) - element.removeEventListener("load", command, true); - else if (window.detachEvent) - element.detachEvent("onload", command); -} - -function addLoadListener(element, command) { - if (window.addEventListener && !browserVersion.isOpera) - element.addEventListener("load",command, true); - else if (window.attachEvent) - element.attachEvent("onload",command); -} - -function addUnloadListener(element, command) { - if (window.addEventListener) - element.addEventListener("unload",command, true); - else if (window.attachEvent) - element.attachEvent("onunload",command); -} - -/** - * Override the broken getFunctionName() method from JsUnit - * This file must be loaded _after_ the jsunitCore.js - */ -function getFunctionName(aFunction) { - var regexpResult = aFunction.toString().match(/function (\w*)/); - if (regexpResult && regexpResult[1]) { - return regexpResult[1]; - } - return 'anonymous'; -} - -function getDocumentBase(doc) { - var bases = document.getElementsByTagName("base"); - if (bases && bases.length && bases[0].href) { - return bases[0].href; - } - return ""; -} - -function describe(object, delimiter) { - var props = new Array(); - for (var prop in object) { - props.push(prop + " -> " + object[prop]); - } - return props.join(delimiter || '\n'); -} - -var PatternMatcher = function(pattern) { - this.selectStrategy(pattern); -}; -PatternMatcher.prototype = { - - selectStrategy: function(pattern) { - this.pattern = pattern; - var strategyName = 'glob'; // by default - if (/^([a-z-]+):(.*)/.test(pattern)) { - strategyName = RegExp.$1; - pattern = RegExp.$2; - } - var matchStrategy = PatternMatcher.strategies[strategyName]; - if (!matchStrategy) { - throw new SeleniumError("cannot find PatternMatcher.strategies." + strategyName); - } - this.strategy = matchStrategy; - this.matcher = new matchStrategy(pattern); - }, - - matches: function(actual) { - return this.matcher.matches(actual + ''); - // Note: appending an empty string avoids a Konqueror bug - } - -}; - -/** - * A "static" convenience method for easy matching - */ -PatternMatcher.matches = function(pattern, actual) { - return new PatternMatcher(pattern).matches(actual); -}; - -PatternMatcher.strategies = { - - /** - * Exact matching, e.g. "exact:***" - */ - exact: function(expected) { - this.expected = expected; - this.matches = function(actual) { - return actual == this.expected; - }; - }, - - /** - * Match by regular expression, e.g. "regexp:^[0-9]+$" - */ - regexp: function(regexpString) { - this.regexp = new RegExp(regexpString); - this.matches = function(actual) { - return this.regexp.test(actual); - }; - }, - - /** - * "globContains" (aka "wildmat") patterns, e.g. "glob:one,two,*", - * but don't require a perfect match; instead succeed if actual - * contains something that matches globString. - * Making this distinction is motivated by a bug in IE6 which - * leads to the browser hanging if we implement *TextPresent tests - * by just matching against a regular expression beginning and - * ending with ".*". The globcontains strategy allows us to satisfy - * the functional needs of the *TextPresent ops more efficiently - * and so avoid running into this IE6 freeze. - */ - globContains: function(globString) { - this.regexp = new RegExp(PatternMatcher.regexpFromGlobContains(globString)); - this.matches = function(actual) { - return this.regexp.test(actual); - }; - }, - - - /** - * "glob" (aka "wildmat") patterns, e.g. "glob:one,two,*" - */ - glob: function(globString) { - this.regexp = new RegExp(PatternMatcher.regexpFromGlob(globString)); - this.matches = function(actual) { - return this.regexp.test(actual); - }; - } - -}; - -PatternMatcher.convertGlobMetaCharsToRegexpMetaChars = function(glob) { - var re = glob; - re = re.replace(/([.^$+(){}\[\]\\|])/g, "\\$1"); - re = re.replace(/\?/g, "(.|[\r\n])"); - re = re.replace(/\*/g, "(.|[\r\n])*"); - return re; -}; - -PatternMatcher.regexpFromGlobContains = function(globContains) { - return PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(globContains); -}; - -PatternMatcher.regexpFromGlob = function(glob) { - return "^" + PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(glob) + "$"; -}; - -var Assert = { - - fail: function(message) { - throw new AssertionFailedError(message); - }, - - /* - * Assert.equals(comment?, expected, actual) - */ - equals: function() { - var args = new AssertionArguments(arguments); - if (args.expected === args.actual) { - return; - } - Assert.fail(args.comment + - "Expected '" + args.expected + - "' but was '" + args.actual + "'"); - }, - - /* - * Assert.matches(comment?, pattern, actual) - */ - matches: function() { - var args = new AssertionArguments(arguments); - if (PatternMatcher.matches(args.expected, args.actual)) { - return; - } - Assert.fail(args.comment + - "Actual value '" + args.actual + - "' did not match '" + args.expected + "'"); - }, - - /* - * Assert.notMtches(comment?, pattern, actual) - */ - notMatches: function() { - var args = new AssertionArguments(arguments); - if (!PatternMatcher.matches(args.expected, args.actual)) { - return; - } - Assert.fail(args.comment + - "Actual value '" + args.actual + - "' did match '" + args.expected + "'"); - } - -}; - -// Preprocess the arguments to allow for an optional comment. -function AssertionArguments(args) { - if (args.length == 2) { - this.comment = ""; - this.expected = args[0]; - this.actual = args[1]; - } else { - this.comment = args[0] + "; "; - this.expected = args[1]; - this.actual = args[2]; - } -} - - - -function AssertionFailedError(message) { - this.isAssertionFailedError = true; - this.isSeleniumError = true; - this.message = message; - this.failureMessage = message; -} - -function SeleniumError(message) { - var error = new Error(message); - error.isSeleniumError = true; - return error; -}; diff --git a/tests/FunctionalTests/selenium/core/scripts/prototype-1.4.0.js b/tests/FunctionalTests/selenium/core/scripts/prototype-1.4.0.js deleted file mode 100755 index 0e85338b..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/prototype-1.4.0.js +++ /dev/null @@ -1,1781 +0,0 @@ -/* Prototype JavaScript framework, version 1.4.0 - * (c) 2005 Sam Stephenson <sam@conio.net> - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://prototype.conio.net/ - * -/*--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.4.0', - ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', - - emptyFunction: function() {}, - K: function(x) {return x} -} - -var Class = { - create: function() { - return function() { - this.initialize.apply(this, arguments); - } - } -} - -var Abstract = new Object(); - -Object.extend = function(destination, source) { - for (property in source) { - destination[property] = source[property]; - } - return destination; -} - -Object.inspect = function(object) { - try { - if (object == undefined) return 'undefined'; - if (object == null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } -} - -Function.prototype.bind = function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } -} - -Function.prototype.bindAsEventListener = function(object) { - var __method = this; - return function(event) { - return __method.call(object, event || window.event); - } -} - -Object.extend(Number.prototype, { - toColorPart: function() { - var digits = this.toString(16); - if (this < 16) return '0' + digits; - return digits; - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - } -}); - -var Try = { - these: function() { - var returnValue; - - for (var i = 0; i < arguments.length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) {} - } - - return returnValue; - } -} - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create(); -PeriodicalExecuter.prototype = { - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.callback(); - } finally { - this.currentlyExecuting = false; - } - } - } -} - -/*--------------------------------------------------------------------------*/ - -function $() { - var elements = new Array(); - - for (var i = 0; i < arguments.length; i++) { - var element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - - if (arguments.length == 1) - return element; - - elements.push(element); - } - - return elements; -} -Object.extend(String.prototype, { - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(eval); - }, - - escapeHTML: function() { - var div = document.createElement('div'); - var text = document.createTextNode(this); - div.appendChild(text); - return div.innerHTML; - }, - - unescapeHTML: function() { - var div = document.createElement('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; - }, - - toQueryParams: function() { - var pairs = this.match(/^\??(.*)$/)[1].split('&'); - return pairs.inject({}, function(params, pairString) { - var pair = pairString.split('='); - params[pair[0]] = pair[1]; - return params; - }); - }, - - toArray: function() { - return this.split(''); - }, - - camelize: function() { - var oStringList = this.split('-'); - if (oStringList.length == 1) return oStringList[0]; - - var camelizedString = this.indexOf('-') == 0 - ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) - : oStringList[0]; - - for (var i = 1, len = oStringList.length; i < len; i++) { - var s = oStringList[i]; - camelizedString += s.charAt(0).toUpperCase() + s.substring(1); - } - - return camelizedString; - }, - - inspect: function() { - return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; - } -}); - -String.prototype.parseQuery = String.prototype.toQueryParams; - -var $break = new Object(); -var $continue = new Object(); - -var Enumerable = { - each: function(iterator) { - var index = 0; - try { - this._each(function(value) { - try { - iterator(value, index++); - } catch (e) { - if (e != $continue) throw e; - } - }); - } catch (e) { - if (e != $break) throw e; - } - }, - - all: function(iterator) { - var result = true; - this.each(function(value, index) { - result = result && !!(iterator || Prototype.K)(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator) { - var result = true; - this.each(function(value, index) { - if (result = !!(iterator || Prototype.K)(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator) { - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function (iterator) { - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator) { - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(pattern, iterator) { - var results = []; - this.each(function(value, index) { - var stringValue = value.toString(); - if (stringValue.match(pattern)) - results.push((iterator || Prototype.K)(value, index)); - }) - return results; - }, - - include: function(object) { - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inject: function(memo, iterator) { - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.collect(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value >= (result || value)) - result = value; - }); - return result; - }, - - min: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value <= (result || value)) - result = value; - }); - return result; - }, - - partition: function(iterator) { - var trues = [], falses = []; - this.each(function(value, index) { - ((iterator || Prototype.K)(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value, index) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator) { - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator) { - return this.collect(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.collect(Prototype.K); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (typeof args.last() == 'function') - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - iterator(value = collections.pluck(index)); - return value; - }); - }, - - inspect: function() { - return '#<Enumerable:' + this.toArray().inspect() + '>'; - } -} - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray -}); -var $A = Array.from = function(iterable) { - if (!iterable) return []; - if (iterable.toArray) { - return iterable.toArray(); - } else { - var results = []; - for (var i = 0; i < iterable.length; i++) - results.push(iterable[i]); - return results; - } -} - -Object.extend(Array.prototype, Enumerable); - -Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0; i < this.length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != undefined || value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(value.constructor == Array ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - indexOf: function(object) { - for (var i = 0; i < this.length; i++) - if (this[i] == object) return i; - return -1; - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - shift: function() { - var result = this[0]; - for (var i = 0; i < this.length - 1; i++) - this[i] = this[i + 1]; - this.length--; - return result; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } -}); -var Hash = { - _each: function(iterator) { - for (key in this) { - var value = this[key]; - if (typeof value == 'function') continue; - - var pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - merge: function(hash) { - return $H(hash).inject($H(this), function(mergedHash, pair) { - mergedHash[pair.key] = pair.value; - return mergedHash; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - return pair.map(encodeURIComponent).join('='); - }).join('&'); - }, - - inspect: function() { - return '#<Hash:{' + this.map(function(pair) { - return pair.map(Object.inspect).join(': '); - }).join(', ') + '}>'; - } -} - -function $H(object) { - var hash = Object.extend({}, object || {}); - Object.extend(hash, Enumerable); - Object.extend(hash, Hash); - return hash; -} -ObjectRange = Class.create(); -Object.extend(ObjectRange.prototype, Enumerable); -Object.extend(ObjectRange.prototype, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - do { - iterator(value); - value = value.succ(); - } while (this.include(value)); - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')}, - function() {return new XMLHttpRequest()} - ) || false; - }, - - activeRequestCount: 0 -} - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responderToAdd) { - if (!this.include(responderToAdd)) - this.responders.push(responderToAdd); - }, - - unregister: function(responderToRemove) { - this.responders = this.responders.without(responderToRemove); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (responder[callback] && typeof responder[callback] == 'function') { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) {} - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { - Ajax.activeRequestCount++; - }, - - onComplete: function() { - Ajax.activeRequestCount--; - } -}); - -Ajax.Base = function() {}; -Ajax.Base.prototype = { - setOptions: function(options) { - this.options = { - method: 'post', - asynchronous: true, - parameters: '' - } - Object.extend(this.options, options || {}); - }, - - responseIsSuccess: function() { - return this.transport.status == undefined - || this.transport.status == 0 - || (this.transport.status >= 200 && this.transport.status < 300); - }, - - responseIsFailure: function() { - return !this.responseIsSuccess(); - } -} - -Ajax.Request = Class.create(); -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Request.prototype = Object.extend(new Ajax.Base(), { - initialize: function(url, options) { - this.transport = Ajax.getTransport(); - this.setOptions(options); - this.request(url); - }, - - request: function(url) { - var parameters = this.options.parameters || ''; - if (parameters.length > 0) parameters += '&_='; - - try { - this.url = url; - if (this.options.method == 'get' && parameters.length > 0) - this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; - - Ajax.Responders.dispatch('onCreate', this, this.transport); - - this.transport.open(this.options.method, this.url, - this.options.asynchronous); - - if (this.options.asynchronous) { - this.transport.onreadystatechange = this.onStateChange.bind(this); - setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); - } - - this.setRequestHeaders(); - - var body = this.options.postBody ? this.options.postBody : parameters; - this.transport.send(this.options.method == 'post' ? body : null); - - } catch (e) { - this.dispatchException(e); - } - }, - - setRequestHeaders: function() { - var requestHeaders = - ['X-Requested-With', 'XMLHttpRequest', - 'X-Prototype-Version', Prototype.Version]; - - if (this.options.method == 'post') { - requestHeaders.push('Content-type', - 'application/x-www-form-urlencoded'); - - /* Force "Connection: close" for Mozilla browsers to work around - * a bug where XMLHttpReqeuest sends an incorrect Content-length - * header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType) - requestHeaders.push('Connection', 'close'); - } - - if (this.options.requestHeaders) - requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); - - for (var i = 0; i < requestHeaders.length; i += 2) - this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState != 1) - this.respondToReadyState(this.transport.readyState); - }, - - header: function(name) { - try { - return this.transport.getResponseHeader(name); - } catch (e) {} - }, - - evalJSON: function() { - try { - return eval(this.header('X-JSON')); - } catch (e) {} - }, - - evalResponse: function() { - try { - return eval(this.transport.responseText); - } catch (e) { - this.dispatchException(e); - } - }, - - respondToReadyState: function(readyState) { - var event = Ajax.Request.Events[readyState]; - var transport = this.transport, json = this.evalJSON(); - - if (event == 'Complete') { - try { - (this.options['on' + this.transport.status] - || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(transport, json); - } catch (e) { - this.dispatchException(e); - } - - if ((this.header('Content-type') || '').match(/^text\/javascript/i)) - this.evalResponse(); - } - - try { - (this.options['on' + event] || Prototype.emptyFunction)(transport, json); - Ajax.Responders.dispatch('on' + event, this, transport, json); - } catch (e) { - this.dispatchException(e); - } - - /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ - if (event == 'Complete') - this.transport.onreadystatechange = Prototype.emptyFunction; - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Updater = Class.create(); - -Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { - initialize: function(container, url, options) { - this.containers = { - success: container.success ? $(container.success) : $(container), - failure: container.failure ? $(container.failure) : - (container.success ? null : $(container)) - } - - this.transport = Ajax.getTransport(); - this.setOptions(options); - - var onComplete = this.options.onComplete || Prototype.emptyFunction; - this.options.onComplete = (function(transport, object) { - this.updateContent(); - onComplete(transport, object); - }).bind(this); - - this.request(url); - }, - - updateContent: function() { - var receiver = this.responseIsSuccess() ? - this.containers.success : this.containers.failure; - var response = this.transport.responseText; - - if (!this.options.evalScripts) - response = response.stripScripts(); - - if (receiver) { - if (this.options.insertion) { - new this.options.insertion(receiver, response); - } else { - Element.update(receiver, response); - } - } - - if (this.responseIsSuccess()) { - if (this.onComplete) - setTimeout(this.onComplete.bind(this), 10); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(); -Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { - initialize: function(container, url, options) { - this.setOptions(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = {}; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(request) { - if (this.options.decay) { - this.decay = (request.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = request.responseText; - } - this.timer = setTimeout(this.onTimerEvent.bind(this), - this.decay * this.frequency * 1000); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -document.getElementsByClassName = function(className, parentElement) { - var children = ($(parentElement) || document.body).getElementsByTagName('*'); - return $A(children).inject([], function(elements, child) { - if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) - elements.push(child); - return elements; - }); -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Element) { - var Element = new Object(); -} - -Object.extend(Element, { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - Element[Element.visible(element) ? 'hide' : 'show'](element); - } - }, - - hide: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = 'none'; - } - }, - - show: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = ''; - } - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - }, - - update: function(element, html) { - $(element).innerHTML = html.stripScripts(); - setTimeout(function() {html.evalScripts()}, 10); - }, - - getHeight: function(element) { - element = $(element); - return element.offsetHeight; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).include(className); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).add(className); - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).remove(className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - for (var i = 0; i < element.childNodes.length; i++) { - var node = element.childNodes[i]; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - Element.remove(node); - } - }, - - empty: function(element) { - return $(element).innerHTML.match(/^\s*$/); - }, - - scrollTo: function(element) { - element = $(element); - var x = element.x ? element.x : element.offsetLeft, - y = element.y ? element.y : element.offsetTop; - window.scrollTo(x, y); - }, - - getStyle: function(element, style) { - element = $(element); - var value = element.style[style.camelize()]; - if (!value) { - if (document.defaultView && document.defaultView.getComputedStyle) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css.getPropertyValue(style) : null; - } else if (element.currentStyle) { - value = element.currentStyle[style.camelize()]; - } - } - - if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) - if (Element.getStyle(element, 'position') == 'static') value = 'auto'; - - return value == 'auto' ? null : value; - }, - - setStyle: function(element, style) { - element = $(element); - for (name in style) - element.style[name.camelize()] = style[name]; - }, - - getDimensions: function(element) { - element = $(element); - if (Element.getStyle(element, 'display') != 'none') - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = ''; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = 'none'; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return; - element._overflow = element.style.overflow; - if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') - element.style.overflow = 'hidden'; - }, - - undoClipping: function(element) { - element = $(element); - if (element._overflow) return; - element.style.overflow = element._overflow; - element._overflow = undefined; - } -}); - -var Toggle = new Object(); -Toggle.display = Element.toggle; - -/*--------------------------------------------------------------------------*/ - -Abstract.Insertion = function(adjacency) { - this.adjacency = adjacency; -} - -Abstract.Insertion.prototype = { - initialize: function(element, content) { - this.element = $(element); - this.content = content.stripScripts(); - - if (this.adjacency && this.element.insertAdjacentHTML) { - try { - this.element.insertAdjacentHTML(this.adjacency, this.content); - } catch (e) { - if (this.element.tagName.toLowerCase() == 'tbody') { - this.insertContent(this.contentFromAnonymousTable()); - } else { - throw e; - } - } - } else { - this.range = this.element.ownerDocument.createRange(); - if (this.initializeRange) this.initializeRange(); - this.insertContent([this.range.createContextualFragment(this.content)]); - } - - setTimeout(function() {content.evalScripts()}, 10); - }, - - contentFromAnonymousTable: function() { - var div = document.createElement('div'); - div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; - return $A(div.childNodes[0].childNodes[0].childNodes); - } -} - -var Insertion = new Object(); - -Insertion.Before = Class.create(); -Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { - initializeRange: function() { - this.range.setStartBefore(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, this.element); - }).bind(this)); - } -}); - -Insertion.Top = Class.create(); -Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(true); - }, - - insertContent: function(fragments) { - fragments.reverse(false).each((function(fragment) { - this.element.insertBefore(fragment, this.element.firstChild); - }).bind(this)); - } -}); - -Insertion.Bottom = Class.create(); -Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.appendChild(fragment); - }).bind(this)); - } -}); - -Insertion.After = Class.create(); -Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { - initializeRange: function() { - this.range.setStartAfter(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, - this.element.nextSibling); - }).bind(this)); - } -}); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set(this.toArray().concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set(this.select(function(className) { - return className != classNameToRemove; - }).join(' ')); - }, - - toString: function() { - return this.toArray().join(' '); - } -} - -Object.extend(Element.ClassNames.prototype, Enumerable); -var Field = { - clear: function() { - for (var i = 0; i < arguments.length; i++) - $(arguments[i]).value = ''; - }, - - focus: function(element) { - $(element).focus(); - }, - - present: function() { - for (var i = 0; i < arguments.length; i++) - if ($(arguments[i]).value == '') return false; - return true; - }, - - select: function(element) { - $(element).select(); - }, - - activate: function(element) { - element = $(element); - element.focus(); - if (element.select) - element.select(); - } -} - -/*--------------------------------------------------------------------------*/ - -var Form = { - serialize: function(form) { - var elements = Form.getElements($(form)); - var queryComponents = new Array(); - - for (var i = 0; i < elements.length; i++) { - var queryComponent = Form.Element.serialize(elements[i]); - if (queryComponent) - queryComponents.push(queryComponent); - } - - return queryComponents.join('&'); - }, - - getElements: function(form) { - form = $(form); - var elements = new Array(); - - for (tagName in Form.Element.Serializers) { - var tagElements = form.getElementsByTagName(tagName); - for (var j = 0; j < tagElements.length; j++) - elements.push(tagElements[j]); - } - return elements; - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) - return inputs; - - var matchingInputs = new Array(); - for (var i = 0; i < inputs.length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || - (name && input.name != name)) - continue; - matchingInputs.push(input); - } - - return matchingInputs; - }, - - disable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.blur(); - element.disabled = 'true'; - } - }, - - enable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.disabled = ''; - } - }, - - findFirstElement: function(form) { - return Form.getElements(form).find(function(element) { - return element.type != 'hidden' && !element.disabled && - ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - Field.activate(Form.findFirstElement(form)); - }, - - reset: function(form) { - $(form).reset(); - } -} - -Form.Element = { - serialize: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) { - var key = encodeURIComponent(parameter[0]); - if (key.length == 0) return; - - if (parameter[1].constructor != Array) - parameter[1] = [parameter[1]]; - - return parameter[1].map(function(value) { - return key + '=' + encodeURIComponent(value); - }).join('&'); - } - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) - return parameter[1]; - } -} - -Form.Element.Serializers = { - input: function(element) { - switch (element.type.toLowerCase()) { - case 'submit': - case 'hidden': - case 'password': - case 'text': - return Form.Element.Serializers.textarea(element); - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element); - } - return false; - }, - - inputSelector: function(element) { - if (element.checked) - return [element.name, element.value]; - }, - - textarea: function(element) { - return [element.name, element.value]; - }, - - select: function(element) { - return Form.Element.Serializers[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - }, - - selectOne: function(element) { - var value = '', opt, index = element.selectedIndex; - if (index >= 0) { - opt = element.options[index]; - value = opt.value; - if (!value && !('value' in opt)) - value = opt.text; - } - return [element.name, value]; - }, - - selectMany: function(element) { - var value = new Array(); - for (var i = 0; i < element.length; i++) { - var opt = element.options[i]; - if (opt.selected) { - var optValue = opt.value; - if (!optValue && !('value' in opt)) - optValue = opt.text; - value.push(optValue); - } - } - return [element.name, value]; - } -} - -/*--------------------------------------------------------------------------*/ - -var $F = Form.Element.getValue; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = function() {} -Abstract.TimedObserver.prototype = { - initialize: function(element, frequency, callback) { - this.frequency = frequency; - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - } -} - -Form.Element.Observer = Class.create(); -Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(); -Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = function() {} -Abstract.EventObserver.prototype = { - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - var elements = Form.getElements(this.element); - for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - case 'password': - case 'text': - case 'textarea': - case 'select-one': - case 'select-multiple': - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -} - -Form.Element.EventObserver = Class.create(); -Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(); -Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) { - var Event = new Object(); -} - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - - element: function(event) { - return event.target || event.srcElement; - }, - - isLeftClick: function(event) { - return (((event.which) && (event.which == 1)) || - ((event.button) && (event.button == 1))); - }, - - pointerX: function(event) { - return event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)); - }, - - pointerY: function(event) { - return event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)); - }, - - stop: function(event) { - if (event.preventDefault) { - event.preventDefault(); - event.stopPropagation(); - } else { - event.returnValue = false; - event.cancelBubble = true; - } - }, - - // find the first node with the given tagName, starting from the - // node the event was triggered on; traverses the DOM upwards - findElement: function(event, tagName) { - var element = Event.element(event); - while (element.parentNode && (!element.tagName || - (element.tagName.toUpperCase() != tagName.toUpperCase()))) - element = element.parentNode; - return element; - }, - - observers: false, - - _observeAndCache: function(element, name, observer, useCapture) { - if (!this.observers) this.observers = []; - if (element.addEventListener) { - this.observers.push([element, name, observer, useCapture]); - element.addEventListener(name, observer, useCapture); - } else if (element.attachEvent) { - this.observers.push([element, name, observer, useCapture]); - element.attachEvent('on' + name, observer); - } - }, - - unloadCache: function() { - if (!Event.observers) return; - for (var i = 0; i < Event.observers.length; i++) { - Event.stopObserving.apply(this, Event.observers[i]); - Event.observers[i][0] = null; - } - Event.observers = false; - }, - - observe: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) - name = 'keydown'; - - this._observeAndCache(element, name, observer, useCapture); - }, - - stopObserving: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.detachEvent)) - name = 'keydown'; - - if (element.removeEventListener) { - element.removeEventListener(name, observer, useCapture); - } else if (element.detachEvent) { - element.detachEvent('on' + name, observer); - } - } -}); - -/* prevent memory leaks in IE */ -Event.observe(window, 'unload', Event.unloadCache, false); -var Position = { - // set to true if needed, warning: firefox performance problems - // NOT neeeded for page scrolling, only if draggable contained in - // scrollable elements - includeScrollOffsets: false, - - // must be called before calling withinIncludingScrolloffset, every time the - // page is scrolled - prepare: function() { - this.deltaX = window.pageXOffset - || document.documentElement.scrollLeft - || document.body.scrollLeft - || 0; - this.deltaY = window.pageYOffset - || document.documentElement.scrollTop - || document.body.scrollTop - || 0; - }, - - realOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return [valueL, valueT]; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return [valueL, valueT]; - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; - } - } while (element); - return [valueL, valueT]; - }, - - offsetParent: function(element) { - if (element.offsetParent) return element.offsetParent; - if (element == document.body) return element; - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return element; - - return document.body; - }, - - // caches x/y coordinate pair to use with overlap - within: function(element, x, y) { - if (this.includeScrollOffsets) - return this.withinIncludingScrolloffsets(element, x, y); - this.xcomp = x; - this.ycomp = y; - this.offset = this.cumulativeOffset(element); - - return (y >= this.offset[1] && - y < this.offset[1] + element.offsetHeight && - x >= this.offset[0] && - x < this.offset[0] + element.offsetWidth); - }, - - withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = this.realOffset(element); - - this.xcomp = x + offsetcache[0] - this.deltaX; - this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = this.cumulativeOffset(element); - - return (this.ycomp >= this.offset[1] && - this.ycomp < this.offset[1] + element.offsetHeight && - this.xcomp >= this.offset[0] && - this.xcomp < this.offset[0] + element.offsetWidth); - }, - - // within must be called directly before - overlap: function(mode, element) { - if (!mode) return 0; - if (mode == 'vertical') - return ((this.offset[1] + element.offsetHeight) - this.ycomp) / - element.offsetHeight; - if (mode == 'horizontal') - return ((this.offset[0] + element.offsetWidth) - this.xcomp) / - element.offsetWidth; - }, - - clone: function(source, target) { - source = $(source); - target = $(target); - target.style.position = 'absolute'; - var offsets = this.cumulativeOffset(source); - target.style.top = offsets[1] + 'px'; - target.style.left = offsets[0] + 'px'; - target.style.width = source.offsetWidth + 'px'; - target.style.height = source.offsetHeight + 'px'; - }, - - page: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent==document.body) - if (Element.getStyle(element,'position')=='absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } while (element = element.parentNode); - - return [valueL, valueT]; - }, - - clone: function(source, target) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || {}) - - // find page position of source - source = $(source); - var p = Position.page(source); - - // find coordinate system to use - target = $(target); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(target,'position') == 'absolute') { - parent = Position.offsetParent(target); - delta = Position.page(parent); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if(options.setWidth) target.style.width = source.offsetWidth + 'px'; - if(options.setHeight) target.style.height = source.offsetHeight + 'px'; - }, - - absolutize: function(element) { - element = $(element); - if (element.style.position == 'absolute') return; - Position.prepare(); - - var offsets = Position.positionedOffset(element); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px';; - element.style.left = left + 'px';; - element.style.width = width + 'px';; - element.style.height = height + 'px';; - }, - - relativize: function(element) { - element = $(element); - if (element.style.position == 'relative') return; - Position.prepare(); - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - } -} - -// Safari returns margins on body which is incorrect if the child is absolutely -// positioned. For performance reasons, redefine Position.cumulativeOffset for -// KHTML/WebKit only. -if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - Position.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return [valueL, valueT]; - } -}
\ No newline at end of file diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-api.js b/tests/FunctionalTests/selenium/core/scripts/selenium-api.js deleted file mode 100755 index ad0509ee..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-api.js +++ /dev/null @@ -1,1402 +0,0 @@ -/* - * 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. - * - */ - -var storedVars = new Object(); - -function Selenium(browserbot) { - /** - * Defines an object that runs Selenium commands. - * - * <h3><a name="locators"></a>Element Locators</h3> - * <p> - * Element Locators tell Selenium which HTML element a command refers to. - * The format of a locator is:</p> - * <blockquote> - * <em>locatorType</em><strong>=</strong><em>argument</em> - * </blockquote> - * - * <p> - * We support the following strategies for locating elements: - * </p> - * <blockquote> - * <dl> - * <dt><strong>identifier</strong>=<em>id</em></dt> - * <dd>Select the element with the specified @id attribute. If no match is - * found, select the first element whose @name attribute is <em>id</em>. - * (This is normally the default; see below.)</dd> - * <dt><strong>id</strong>=<em>id</em></dt> - * <dd>Select the element with the specified @id attribute.</dd> - * - * <dt><strong>name</strong>=<em>name</em></dt> - * <dd>Select the first element with the specified @name attribute.</dd> - * <dd><ul class="first last simple"> - * <li>username</li> - * <li>name=username</li> - * </ul> - * </dd> - * <dd>The name may optionally be followed by one or more <em>element-filters</em>, separated from the name by whitespace. If the <em>filterType</em> is not specified, <strong>value</strong> is assumed.</dd> - * - * <dd><ul class="first last simple"> - * <li>name=flavour value=chocolate</li> - * </ul> - * </dd> - * <dt><strong>dom</strong>=<em>javascriptExpression</em></dt> - * - * <dd> - * - * <dd>Find an element using JavaScript traversal of the HTML Document Object - * Model. DOM locators <em>must</em> begin with "document.". - * <ul class="first last simple"> - * <li>dom=document.forms['myForm'].myDropdown</li> - * <li>dom=document.images[56]</li> - * </ul> - * </dd> - * - * </dd> - * - * <dt><strong>xpath</strong>=<em>xpathExpression</em></dt> - * <dd>Locate an element using an XPath expression. - * <ul class="first last simple"> - * <li>xpath=//img[@alt='The image alt text']</li> - * <li>xpath=//table[@id='table1']//tr[4]/td[2]</li> - * - * </ul> - * </dd> - * <dt><strong>link</strong>=<em>textPattern</em></dt> - * <dd>Select the link (anchor) element which contains text matching the - * specified <em>pattern</em>. - * <ul class="first last simple"> - * <li>link=The link text</li> - * </ul> - * - * </dd> - * </dl> - * </blockquote> - * <p> - * Without an explicit locator prefix, Selenium uses the following default - * strategies: - * </p> - * - * <ul class="simple"> - * <li><strong>dom</strong>, for locators starting with "document."</li> - * <li><strong>xpath</strong>, for locators starting with "//"</li> - * <li><strong>identifier</strong>, otherwise</li> - * </ul> - * - * <h3><a name="element-filters">Element Filters</a></h3> - * <blockquote> - * <p>Element filters can be used with a locator to refine a list of candidate elements. They are currently used only in the 'name' element-locator.</p> - * <p>Filters look much like locators, ie.</p> - * <blockquote> - * <em>filterType</em><strong>=</strong><em>argument</em></blockquote> - * - * <p>Supported element-filters are:</p> - * <p><strong>value=</strong><em>valuePattern</em></p> - * <blockquote> - * Matches elements based on their values. This is particularly useful for refining a list of similarly-named toggle-buttons.</blockquote> - * <p><strong>index=</strong><em>index</em></p> - * <blockquote> - * Selects a single element based on its position in the list (offset from zero).</blockquote> - * </blockquote> - * - * <h3><a name="patterns"></a>String-match Patterns</h3> - * - * <p> - * Various Pattern syntaxes are available for matching string values: - * </p> - * <blockquote> - * <dl> - * <dt><strong>glob:</strong><em>pattern</em></dt> - * <dd>Match a string against a "glob" (aka "wildmat") pattern. "Glob" is a - * kind of limited regular-expression syntax typically used in command-line - * shells. In a glob pattern, "*" represents any sequence of characters, and "?" - * represents any single character. Glob patterns match against the entire - * string.</dd> - * <dt><strong>regexp:</strong><em>regexp</em></dt> - * <dd>Match a string using a regular-expression. The full power of JavaScript - * regular-expressions is available.</dd> - * <dt><strong>exact:</strong><em>string</em></dt> - * - * <dd>Match a string exactly, verbatim, without any of that fancy wildcard - * stuff.</dd> - * </dl> - * </blockquote> - * <p> - * If no pattern prefix is specified, Selenium assumes that it's a "glob" - * pattern. - * </p> - */ - this.browserbot = browserbot; - this.optionLocatorFactory = new OptionLocatorFactory(); - this.page = function() { - return browserbot.getCurrentPage(); - }; -} - -Selenium.createForFrame = function(frame) { - return new Selenium(BrowserBot.createForFrame(frame)); -}; - -Selenium.prototype.reset = function() { - /** - * Clear out all stored variables and select the null (starting) window - */ - storedVars = new Object(); - this.browserbot.selectWindow("null"); -}; - -Selenium.prototype.doClick = function(locator) { - /** - * Clicks on a link, button, checkbox or radio button. If the click action - * causes a new page to load (like a link usually does), call - * waitForPageToLoad. - * - * @param locator an element locator - * - */ - var element = this.page().findElement(locator); - this.page().clickElement(element); -}; - -Selenium.prototype.doFireEvent = function(locator, eventName) { - /** - * Explicitly simulate an event, to trigger the corresponding "on<em>event</em>" - * handler. - * - * @param locator an <a href="#locators">element locator</a> - * @param eventName the event name, e.g. "focus" or "blur" - */ - var element = this.page().findElement(locator); - triggerEvent(element, eventName, false); -}; - -Selenium.prototype.doKeyPress = function(locator, keycode) { - /** - * Simulates a user pressing and releasing a key. - * - * @param locator an <a href="#locators">element locator</a> - * @param keycode the numeric keycode of the key to be pressed, normally the - * ASCII value of that key. - */ - var element = this.page().findElement(locator); - triggerKeyEvent(element, 'keypress', keycode, true); -}; - -Selenium.prototype.doKeyDown = function(locator, keycode) { - /** - * Simulates a user pressing a key (without releasing it yet). - * - * @param locator an <a href="#locators">element locator</a> - * @param keycode the numeric keycode of the key to be pressed, normally the - * ASCII value of that key. - */ - var element = this.page().findElement(locator); - triggerKeyEvent(element, 'keydown', keycode, true); -}; - -Selenium.prototype.doKeyUp = function(locator, keycode) { - /** - * Simulates a user releasing a key. - * - * @param locator an <a href="#locators">element locator</a> - * @param keycode the numeric keycode of the key to be released, normally the - * ASCII value of that key. - */ - var element = this.page().findElement(locator); - triggerKeyEvent(element, 'keyup', keycode, true); -}; - -Selenium.prototype.doMouseOver = function(locator) { - /** - * Simulates a user hovering a mouse over the specified element. - * - * @param locator an <a href="#locators">element locator</a> - */ - var element = this.page().findElement(locator); - triggerMouseEvent(element, 'mouseover', true); -}; - -Selenium.prototype.doMouseDown = function(locator) { - /** - * Simulates a user pressing the mouse button (without releasing it yet) on - * the specified element. - * - * @param locator an <a href="#locators">element locator</a> - */ - var element = this.page().findElement(locator); - triggerMouseEvent(element, 'mousedown', true); -}; - -Selenium.prototype.doType = function(locator, value) { - /** - * Sets the value of an input field, as though you typed it in. - * - * <p>Can also be used to set the value of combo boxes, check boxes, etc. In these cases, - * value should be the value of the option selected, not the visible text.</p> - * - * @param locator an <a href="#locators">element locator</a> - * @param value the value to type - */ - // TODO fail if it can't be typed into. - var element = this.page().findElement(locator); - this.page().replaceText(element, value); -}; - -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; -} - -Selenium.prototype.doCheck = function(locator) { - /** - * Check a toggle-button (checkbox/radio) - * - * @param locator an <a href="#locators">element locator</a> - */ - this.findToggleButton(locator).checked = true; -}; - -Selenium.prototype.doUncheck = function(locator) { - /** - * Uncheck a toggle-button (checkbox/radio) - * - * @param locator an <a href="#locators">element locator</a> - */ - this.findToggleButton(locator).checked = false; -}; - -Selenium.prototype.doSelect = function(selectLocator, optionLocator) { - /** - * Select an option from a drop-down using an option locator. - * - * <p> - * Option locators provide different ways of specifying options of an HTML - * Select element (e.g. for selecting a specific option, or for asserting - * that the selected option satisfies a specification). There are several - * forms of Select Option Locator. - * </p> - * <dl> - * <dt><strong>label</strong>=<em>labelPattern</em></dt> - * <dd>matches options based on their labels, i.e. the visible text. (This - * is the default.) - * <ul class="first last simple"> - * <li>label=regexp:^[Oo]ther</li> - * </ul> - * </dd> - * <dt><strong>value</strong>=<em>valuePattern</em></dt> - * <dd>matches options based on their values. - * <ul class="first last simple"> - * <li>value=other</li> - * </ul> - * - * - * </dd> - * <dt><strong>id</strong>=<em>id</em></dt> - * - * <dd>matches options based on their ids. - * <ul class="first last simple"> - * <li>id=option1</li> - * </ul> - * </dd> - * <dt><strong>index</strong>=<em>index</em></dt> - * <dd>matches an option based on its index (offset from zero). - * <ul class="first last simple"> - * - * <li>index=2</li> - * </ul> - * </dd> - * </dl> - * <p> - * If no option locator prefix is provided, the default behaviour is to match on <strong>label</strong>. - * </p> - * - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @param optionLocator an option locator (a label by default) - */ - var element = this.page().findElement(selectLocator); - 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); -}; - -Selenium.prototype.doAddSelection = function(locator, optionLocator) { - /** - * Add a selection to the set of selected options in a multi-select element using an option locator. - * - * @see #doSelect for details of option locators - * - * @param locator an <a href="#locators">element locator</a> identifying a multi-select box - * @param optionLocator an option locator (a label by default) - */ - 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().addSelection(element, option); -}; - -Selenium.prototype.doRemoveSelection = function(locator, optionLocator) { - /** - * Remove a selection from the set of selected options in a multi-select element using an option locator. - * - * @see #doSelect for details of option locators - * - * @param locator an <a href="#locators">element locator</a> identifying a multi-select box - * @param optionLocator an option locator (a label by default) - */ - - 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().removeSelection(element, option); -}; - -Selenium.prototype.doSubmit = function(formLocator) { - /** - * Submit the specified form. This is particularly useful for forms without - * submit buttons, e.g. single-input "Search" forms. - * - * @param formLocator an <a href="#locators">element locator</a> for the form you want to submit - */ - var form = this.page().findElement(formLocator); - var actuallySubmit = true; - if (form.onsubmit) { - // apply this to the correct window so alerts are properly handled, even in IE HTA mode - actuallySubmit = form.onsubmit.apply(this.browserbot.getContentWindow()); - } - if (actuallySubmit) { - form.submit(); - } - -}; - -Selenium.prototype.doOpen = function(url) { - /** - * Opens an URL in the test frame. This accepts both relative and absolute - * URLs. - * - * The "open" command waits for the page to load before proceeding, - * ie. the "AndWait" suffix is implicit. - * - * <em>Note</em>: The URL must be on the same domain as the runner HTML - * due to security restrictions in the browser (Same Origin Policy). If you - * need to open an URL on another domain, use the Selenium Server to start a - * new browser session on that domain. - * - * @param url the URL to open; may be relative or absolute - */ - this.browserbot.openLocation(url); - return SELENIUM_PROCESS_WAIT; -}; - -Selenium.prototype.doSelectWindow = function(windowID) { - /** - * Selects a popup window; once a popup window has been selected, all - * commands go to that window. To select the main window again, use "null" - * as the target. - * - * @param windowID the JavaScript window ID of the window to select - */ - this.browserbot.selectWindow(windowID); -}; - -Selenium.prototype.doWaitForPopUp = function(windowID, timeout) { - /** - * Waits for a popup window to appear and load up. - * - * @param windowID the JavaScript window ID of the window that will appear - * @param timeout a timeout in milliseconds, after which the action will return with an error - */ - if (isNaN(timeout)) { - throw new SeleniumError("Timeout is not a number: " + timeout); - } - - testLoop.waitForCondition = function () { - var targetWindow = selenium.browserbot.getTargetWindow(windowID); - if (!targetWindow) return false; - if (!targetWindow.location) return false; - if ("about:blank" == targetWindow.location) return false; - if (!targetWindow.document) return false; - if (!targetWindow.document.readyState) return true; - if ('complete' != targetWindow.document.readyState) return false; - return true; - }; - - testLoop.waitForConditionStart = new Date().getTime(); - testLoop.waitForConditionTimeout = timeout; - -} - -Selenium.prototype.doWaitForPopUp.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.doChooseCancelOnNextConfirmation = function() { - /** - * By default, Selenium's overridden window.confirm() function will - * return true, as if the user had manually clicked OK. After running - * this command, the next call to confirm() will return false, as if - * the user had clicked Cancel. - * - */ - this.browserbot.cancelNextConfirmation(); -}; - - -Selenium.prototype.doAnswerOnNextPrompt = function(answer) { - /** - * Instructs Selenium to return the specified answer string in response to - * the next JavaScript prompt [window.prompt()]. - * - * - * @param answer the answer to give in response to the prompt pop-up - */ - this.browserbot.setNextPromptResult(answer); -}; - -Selenium.prototype.doGoBack = function() { - /** - * Simulates the user clicking the "back" button on their browser. - * - */ - this.page().goBack(); -}; - -Selenium.prototype.doRefresh = function() { - /** - * Simulates the user clicking the "Refresh" button on their browser. - * - */ - this.page().refresh(); -}; - -Selenium.prototype.doClose = function() { - /** - * Simulates the user clicking the "close" button in the titlebar of a popup - * window or tab. - */ - this.page().close(); -}; - -Selenium.prototype.isAlertPresent = function() { - /** - * Has an alert occurred? - * - * <p> - * This function never throws an exception - * </p> - * @return boolean true if there is an alert - */ - return this.browserbot.hasAlerts(); -}; -Selenium.prototype.isPromptPresent = function() { - /** - * Has a prompt occurred? - * - * <p> - * This function never throws an exception - * </p> - * @return boolean true if there is a pending prompt - */ - return this.browserbot.hasPrompts(); -}; -Selenium.prototype.isConfirmationPresent = function() { - /** - * Has confirm() been called? - * - * <p> - * This function never throws an exception - * </p> - * @return boolean true if there is a pending confirmation - */ - return this.browserbot.hasConfirmations(); -}; -Selenium.prototype.getAlert = function() { - /** - * Retrieves the message of a JavaScript alert generated during the previous action, or fail if there were no alerts. - * - * <p>Getting an alert has the same effect as manually clicking OK. If an - * alert is generated but you do not get/verify it, the next Selenium action - * will fail.</p> - * - * <p>NOTE: under Selenium, JavaScript alerts will NOT pop up a visible alert - * dialog.</p> - * - * <p>NOTE: Selenium does NOT support JavaScript alerts that are generated in a - * page's onload() event handler. In this case a visible dialog WILL be - * generated and Selenium will hang until someone manually clicks OK.</p> - * @return string The message of the most recent JavaScript alert - */ - if (!this.browserbot.hasAlerts()) { - Assert.fail("There were no alerts"); - } - return this.browserbot.getNextAlert(); -}; -Selenium.prototype.getAlert.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.getConfirmation = function() { - /** - * Retrieves the message of a JavaScript confirmation dialog generated during - * the previous action. - * - * <p> - * By default, the confirm function will return true, having the same effect - * as manually clicking OK. This can be changed by prior execution of the - * chooseCancelOnNextConfirmation command. If an confirmation is generated - * but you do not get/verify it, the next Selenium action will fail. - * </p> - * - * <p> - * NOTE: under Selenium, JavaScript confirmations will NOT pop up a visible - * dialog. - * </p> - * - * <p> - * NOTE: Selenium does NOT support JavaScript confirmations that are - * generated in a page's onload() event handler. In this case a visible - * dialog WILL be generated and Selenium will hang until you manually click - * OK. - * </p> - * - * @return string the message of the most recent JavaScript confirmation dialog - */ - if (!this.browserbot.hasConfirmations()) { - Assert.fail("There were no confirmations"); - } - return this.browserbot.getNextConfirmation(); -}; -Selenium.prototype.getConfirmation.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.getPrompt = function() { - /** - * Retrieves the message of a JavaScript question prompt dialog generated during - * the previous action. - * - * <p>Successful handling of the prompt requires prior execution of the - * answerOnNextPrompt command. If a prompt is generated but you - * do not get/verify it, the next Selenium action will fail.</p> - * - * <p>NOTE: under Selenium, JavaScript prompts will NOT pop up a visible - * dialog.</p> - * - * <p>NOTE: Selenium does NOT support JavaScript prompts that are generated in a - * page's onload() event handler. In this case a visible dialog WILL be - * generated and Selenium will hang until someone manually clicks OK.</p> - * @return string the message of the most recent JavaScript question prompt - */ - if (! this.browserbot.hasPrompts()) { - Assert.fail("There were no prompts"); - } - return this.browserbot.getNextPrompt(); -}; - -Selenium.prototype.getLocation = function() { - /** Gets the absolute URL of the current page. - * - * @return string the absolute URL of the current page - */ - return this.page().location; -}; - -Selenium.prototype.getTitle = function() { - /** Gets the title of the current page. - * - * @return string the title of the current page - */ - return this.page().title(); -}; - - -Selenium.prototype.getBodyText = function() { - /** - * Gets the entire text of the page. - * @return string the entire text of the page - */ - return this.page().bodyText(); -}; - - -Selenium.prototype.getValue = function(locator) { - /** - * Gets the (whitespace-trimmed) value of an input field (or anything else with a value parameter). - * For checkbox/radio elements, the value will be "on" or "off" depending on - * whether the element is checked or not. - * - * @param locator an <a href="#locators">element locator</a> - * @return string the element value, or "on/off" for checkbox/radio elements - */ - var element = this.page().findElement(locator) - return getInputValue(element).trim(); -} - -Selenium.prototype.getText = function(locator) { - /** - * Gets the text of an element. This works for any element that contains - * text. This command uses either the textContent (Mozilla-like browsers) or - * the innerText (IE-like browsers) of the element, which is the rendered - * text shown to the user. - * - * @param locator an <a href="#locators">element locator</a> - * @return string the text of the element - */ - var element = this.page().findElement(locator); - return getText(element).trim(); -}; - -Selenium.prototype.getEval = function(script) { - /** Gets the result of evaluating the specified JavaScript snippet. The snippet may - * have multiple lines, but only the result of the last line will be returned. - * - * <p>Note that, by default, the snippet will run in the context of the "selenium" - * object itself, so <code>this</code> will refer to the Selenium object, and <code>window</code> will - * refer to the top-level runner test window, not the window of your application.</p> - * - * <p>If you need a reference to the window of your application, you can refer - * to <code>this.browserbot.getCurrentWindow()</code> and if you need to use - * a locator to refer to a single element in your application page, you can - * use <code>this.page().findElement("foo")</code> where "foo" is your locator.</p> - * - * @param script the JavaScript snippet to run - * @return string the results of evaluating the snippet - */ - try { - var result = eval(script); - // Selenium RC doesn't allow returning null - if (null == result) return "null"; - return result; - } catch (e) { - throw new SeleniumError("Threw an exception: " + e.message); - } -}; - -Selenium.prototype.isChecked = function(locator) { - /** - * Gets whether a toggle-button (checkbox/radio) is checked. Fails if the specified element doesn't exist or isn't a toggle-button. - * @param locator an <a href="#locators">element locator</a> pointing to a checkbox or radio button - * @return string either "true" or "false" depending on whether the checkbox is checked - */ - var element = this.page().findElement(locator); - if (element.checked == null) { - throw new SeleniumError("Element " + locator + " is not a toggle-button."); - } - return element.checked; -}; - -Selenium.prototype.getTable = function(tableCellAddress) { - /** - * Gets the text from a cell of a table. The cellAddress syntax - * tableLocator.row.column, where row and column start at 0. - * - * @param tableCellAddress a cell address, e.g. "foo.1.4" - * @return string the text from the specified cell - */ - // This regular expression matches "tableName.row.column" - // For example, "mytable.3.4" - pattern = /(.*)\.(\d+)\.(\d+)/; - - if(!pattern.test(tableCellAddress)) { - throw new SeleniumError("Invalid target format. Correct format is tableName.rowNum.columnNum"); - } - - pieces = tableCellAddress.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(); - } - return null; -}; - -Selenium.prototype.assertSelected = function(selectLocator, optionLocator) { - /** - * Verifies that the selected option of a drop-down satisfies the optionSpecifier. - * - * <p>See the select command for more information about option locators.</p> - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @param optionLocator an option locator, typically just an option label (e.g. "John Smith") - */ - var element = this.page().findElement(selectLocator); - var locator = this.optionLocatorFactory.fromLocatorString(optionLocator); - if (element.selectedIndex == -1) - { - Assert.fail("No option selected"); - } - locator.assertSelected(element); -}; - -Selenium.prototype.getSelectedLabels = function(selectLocator) { - /** Gets all option labels (visible text) for selected options in the specified select or multi-select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all selected option labels in the specified select drop-down - */ - return this.findSelectedOptionProperties(selectLocator, "text").join(","); -} - -Selenium.prototype.getSelectedLabel = function(selectLocator) { - /** Gets option label (visible text) for selected option in the specified select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string the selected option label in the specified select drop-down - */ - return this.findSelectedOptionProperty(selectLocator, "text"); -} - -Selenium.prototype.getSelectedValues = function(selectLocator) { - /** Gets all option values (value attributes) for selected options in the specified select or multi-select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all selected option values in the specified select drop-down - */ - return this.findSelectedOptionProperties(selectLocator, "value").join(","); -} - -Selenium.prototype.getSelectedValue = function(selectLocator) { - /** Gets option value (value attribute) for selected option in the specified select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string the selected option value in the specified select drop-down - */ - return this.findSelectedOptionProperty(selectLocator, "value"); -} - -Selenium.prototype.getSelectedIndexes = function(selectLocator) { - /** Gets all option indexes (option number, starting at 0) for selected options in the specified select or multi-select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all selected option indexes in the specified select drop-down - */ - return this.findSelectedOptionProperties(selectLocator, "index").join(","); -} - -Selenium.prototype.getSelectedIndex = function(selectLocator) { - /** Gets option index (option number, starting at 0) for selected option in the specified select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string the selected option index in the specified select drop-down - */ - return this.findSelectedOptionProperty(selectLocator, "index"); -} - -Selenium.prototype.getSelectedIds = function(selectLocator) { - /** Gets all option element IDs for selected options in the specified select or multi-select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all selected option IDs in the specified select drop-down - */ - return this.findSelectedOptionProperties(selectLocator, "id").join(","); -} - -Selenium.prototype.getSelectedId = function(selectLocator) { - /** Gets option element ID for selected option in the specified select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string the selected option ID in the specified select drop-down - */ - return this.findSelectedOptionProperty(selectLocator, "id"); -} - -Selenium.prototype.isSomethingSelected = function(selectLocator) { - /** Determines whether some option in a drop-down menu is selected. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return boolean true if some option has been selected, false otherwise - */ - var element = this.page().findElement(selectLocator); - if (!("options" in element)) { - throw new SeleniumError("Specified element is not a Select (has no options)"); - } - - var selectedOptions = []; - - for (var i = 0; i < element.options.length; i++) { - if (element.options[i].selected) - { - return true; - } - } - return false; -} - -Selenium.prototype.findSelectedOptionProperties = function(locator, property) { - var element = this.page().findElement(locator); - if (!("options" in element)) { - throw new SeleniumError("Specified element is not a Select (has no options)"); - } - - var selectedOptions = []; - - for (var i = 0; i < element.options.length; i++) { - if (element.options[i].selected) - { - var propVal = element.options[i][property]; - if (propVal.replace) { - propVal.replace(/,/g, "\\,"); - } - selectedOptions.push(propVal); - } - } - if (selectedOptions.length == 0) Assert.fail("No option selected"); - return selectedOptions; -} - -Selenium.prototype.findSelectedOptionProperty = function(locator, property) { - var selectedOptions = this.findSelectedOptionProperties(locator, property); - if (selectedOptions.length > 1) { - Assert.fail("More than one selected option!"); - } - return selectedOptions[0]; -} - -Selenium.prototype.getSelectOptions = function(selectLocator) { - /** Gets all option labels in the specified select drop-down. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all option labels in the specified select drop-down - */ - var element = this.page().findElement(selectLocator); - - var selectOptions = []; - - for (var i = 0; i < element.options.length; i++) { - var option = element.options[i].text.replace(/,/g, "\\,"); - selectOptions.push(option); - } - - return selectOptions.join(","); -}; - - -Selenium.prototype.getAttribute = function(attributeLocator) { - /** - * Gets the value of an element attribute. - * @param attributeLocator an element locator followed by an @ sign and then the name of the attribute, e.g. "foo@bar" - * @return string the value of the specified attribute - */ - var result = this.page().findAttribute(attributeLocator); - if (result == null) { - throw new SeleniumError("Could not find element attribute: " + attributeLocator); - } - return result; -}; - -Selenium.prototype.isTextPresent = function(pattern) { - /** - * Verifies that the specified text pattern appears somewhere on the rendered page shown to the user. - * @param pattern a <a href="#patterns">pattern</a> to match with the text of the page - * @return boolean true if the pattern matches the text, false otherwise - */ - var allText = this.page().bodyText(); - - if(allText == "") { - Assert.fail("Page text not found"); - } else { - var patternMatcher = new PatternMatcher(pattern); - if (patternMatcher.strategy == PatternMatcher.strategies.glob) { - patternMatcher.matcher = new PatternMatcher.strategies.globContains(pattern); - } - return patternMatcher.matches(allText); - } -}; - -Selenium.prototype.isElementPresent = function(locator) { - /** - * Verifies that the specified element is somewhere on the page. - * @param locator an <a href="#locators">element locator</a> - * @return boolean true if the element is present, false otherwise - */ - try { - this.page().findElement(locator); - } catch (e) { - return false; - } - return true; -}; - -Selenium.prototype.isVisible = function(locator) { - /** - * Determines if the specified element is visible. An - * element can be rendered invisible by setting the CSS "visibility" - * property to "hidden", or the "display" property to "none", either for the - * element itself or one if its ancestors. This method will fail if - * the element is not present. - * - * @param locator an <a href="#locators">element locator</a> - * @return boolean true if the specified element is visible, false otherwise - */ - var element; - element = this.page().findElement(locator); - - if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - var visibility = element.style["visibility"]; - else - var visibility = this.findEffectiveStyleProperty(element, "visibility"); - - var _isDisplayed = this._isDisplayed(element); - return (visibility != "hidden" && _isDisplayed); -}; - -Selenium.prototype.findEffectiveStyleProperty = function(element, property) { - var effectiveStyle = this.findEffectiveStyle(element); - var propertyValue = effectiveStyle[property]; - if (propertyValue == 'inherit' && element.parentNode.style) { - return this.findEffectiveStyleProperty(element.parentNode, property); - } - return propertyValue; -}; - -Selenium.prototype._isDisplayed = function(element) { - if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - var display = element.style["display"]; - else - var display = this.findEffectiveStyleProperty(element, "display"); - if (display == "none") return false; - if (element.parentNode.style) { - return this._isDisplayed(element.parentNode); - } - return true; -}; - -Selenium.prototype.findEffectiveStyle = 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"); -}; - -Selenium.prototype.isEditable = function(locator) { - /** - * Determines whether the specified input element is editable, ie hasn't been disabled. - * This method will fail if the specified element isn't an input element. - * - * @param locator an <a href="#locators">element locator</a> - * @return boolean true if the input element is editable, false otherwise - */ - var element = this.page().findElement(locator); - if (element.value == undefined) { - Assert.fail("Element " + locator + " is not an input."); - } - return !element.disabled; -}; - -Selenium.prototype.getAllButtons = function() { - /** Returns the IDs of all buttons on the page. - * - * <p>If a given button has no ID, it will appear as "" in this array.</p> - * - * @return string[] the IDs of all buttons on the page - */ - return this.page().getAllButtons(); -}; - -Selenium.prototype.getAllLinks = function() { - /** Returns the IDs of all links on the page. - * - * <p>If a given link has no ID, it will appear as "" in this array.</p> - * - * @return string[] the IDs of all links on the page - */ - return this.page().getAllLinks(); -}; - -Selenium.prototype.getAllFields = function() { - /** Returns the IDs of all input fields on the page. - * - * <p>If a given field has no ID, it will appear as "" in this array.</p> - * - * @return string[] the IDs of all field on the page - */ - return this.page().getAllFields(); -}; - -Selenium.prototype.getHtmlSource = function() { - /** Returns the entire HTML source between the opening and - * closing "html" tags. - * - * @return string the entire HTML source - */ - return this.page().currentDocument.getElementsByTagName("html")[0].innerHTML; -}; - -Selenium.prototype.doSetCursorPosition = function(locator, position) { - /** - * Moves the text cursor to the specified position in the given input element or textarea. - * This method will fail if the specified element isn't an input element or textarea. - * - * @param locator an <a href="#locators">element locator</a> pointing to an input element or textarea - * @param position the numerical position of the cursor in the field; position should be 0 to move the position to the beginning of the field. You can also set the cursor to -1 to move it to the end of the field. - */ - var element = this.page().findElement(locator); - if (element.value == undefined) { - Assert.fail("Element " + locator + " is not an input."); - } - if (position == -1) { - position = element.value.length; - } - - if( element.setSelectionRange && !browserVersion.isOpera) { - element.focus(); - element.setSelectionRange(/*start*/position,/*end*/position); - } - else if( element.createTextRange ) { - triggerEvent(element, 'focus', false); - var range = element.createTextRange(); - range.collapse(true); - range.moveEnd('character',position); - range.moveStart('character',position); - range.select(); - } -} - -Selenium.prototype.getCursorPosition = function(locator) { - /** - * Retrieves the text cursor position in the given input element or textarea; beware, this may not work perfectly on all browsers. - * - * <p>Specifically, if the cursor/selection has been cleared by JavaScript, this command will tend to - * return the position of the last location of the cursor, even though the cursor is now gone from the page. This is filed as <a href="http://jira.openqa.org/browse/SEL-243">SEL-243</a>.</p> - * This method will fail if the specified element isn't an input element or textarea, or there is no cursor in the element. - * - * @param locator an <a href="#locators">element locator</a> pointing to an input element or textarea - * @return number the numerical position of the cursor in the field - */ - var element = this.page().findElement(locator); - var doc = this.page().currentDocument; - var win = this.browserbot.getCurrentWindow(); - if( doc.selection && !browserVersion.isOpera){ - - var selectRange = doc.selection.createRange().duplicate(); - var elementRange = element.createTextRange(); - selectRange.move("character",0); - elementRange.move("character",0); - var inRange1 = selectRange.inRange(elementRange); - var inRange2 = elementRange.inRange(selectRange); - try { - elementRange.setEndPoint("EndToEnd", selectRange); - } catch (e) { - Assert.fail("There is no cursor on this page!"); - } - var answer = String(elementRange.text).replace(/\r/g,"").length; - return answer; - } else { - if (typeof(element.selectionStart) != undefined) { - if (win.getSelection && typeof(win.getSelection().rangeCount) != undefined && win.getSelection().rangeCount == 0) { - Assert.fail("There is no cursor on this page!"); - } - return element.selectionStart; - } - } - throw new Error("Couldn't detect cursor position on this browser!"); -} - - -Selenium.prototype.doSetContext = function(context, logLevelThreshold) { - /** - * Writes a message to the status bar and adds a note to the browser-side - * log. - * - * <p>If logLevelThreshold is specified, set the threshold for logging - * to that level (debug, info, warn, error).</p> - * - * <p>(Note that the browser-side logs will <i>not</i> be sent back to the - * server, and are invisible to the Client Driver.)</p> - * - * @param context - * the message to be sent to the browser - * @param logLevelThreshold one of "debug", "info", "warn", "error", sets the threshold for browser-side logging - */ - if (logLevelThreshold==null || logLevelThreshold=="") { - return this.page().setContext(context); - } - return this.page().setContext(context, logLevelThreshold); -}; - -Selenium.prototype.getExpression = function(expression) { - /** - * Returns the specified expression. - * - * <p>This is useful because of JavaScript preprocessing. - * It is used to generate commands like assertExpression and storeExpression.</p> - * - * @param expression the value to return - * @return string the value passed in - */ - return expression; -} - -Selenium.prototype.doWaitForCondition = function(script, timeout) { - /** - * Runs the specified JavaScript snippet repeatedly until it evaluates to "true". - * The snippet may have multiple lines, but only the result of the last line - * will be considered. - * - * <p>Note that, by default, the snippet will be run in the runner's test window, not in the window - * of your application. To get the window of your application, you can use - * the JavaScript snippet <code>selenium.browserbot.getCurrentWindow()</code>, and then - * run your JavaScript in there</p> - * @param script the JavaScript snippet to run - * @param timeout a timeout in milliseconds, after which this command will return with an error - */ - if (isNaN(timeout)) { - throw new SeleniumError("Timeout is not a number: " + timeout); - } - - testLoop.waitForCondition = function () { - return eval(script); - }; - - testLoop.waitForConditionStart = new Date().getTime(); - testLoop.waitForConditionTimeout = timeout; -}; - -Selenium.prototype.doWaitForCondition.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.doSetTimeout = function(timeout) { - /** - * Specifies the amount of time that Selenium will wait for actions to complete. - * - * <p>Actions that require waiting include "open" and the "waitFor*" actions.</p> - * The default timeout is 30 seconds. - * @param timeout a timeout in milliseconds, after which the action will return with an error - */ - testLoop.waitForConditionTimeout = timeout; -} - -Selenium.prototype.doWaitForPageToLoad = function(timeout) { - /** - * Waits for a new page to load. - * - * <p>You can use this command instead of the "AndWait" suffixes, "clickAndWait", "selectAndWait", "typeAndWait" etc. - * (which are only available in the JS API).</p> - * - * <p>Selenium constantly keeps track of new pages loading, and sets a "newPageLoaded" - * flag when it first notices a page load. Running any other Selenium command after - * turns the flag to false. Hence, if you want to wait for a page to load, you must - * wait immediately after a Selenium command that caused a page-load.</p> - * @param timeout a timeout in milliseconds, after which this command will return with an error - */ - this.doWaitForCondition("selenium.browserbot.isNewPageLoaded()", timeout); -}; - -Selenium.prototype.doWaitForPageToLoad.dontCheckAlertsAndConfirms = true; - -/** - * 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\{((.|\r?\n)+)\}$/); - 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) - }; -}; - - diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-browserbot.js b/tests/FunctionalTests/selenium/core/scripts/selenium-browserbot.js deleted file mode 100755 index 8df46865..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-browserbot.js +++ /dev/null @@ -1,1114 +0,0 @@ -/* -* 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. -* -*/ - -/* -* This script provides the Javascript API to drive the test application contained within -* a Browser Window. -* TODO: -* Add support for more events (keyboard and mouse) -* Allow to switch "user-entry" mode from mouse-based to keyboard-based, firing different -* events in different modes. -*/ - -// The window to which the commands will be sent. For example, to click on a -// popup window, first select that window, and then do a normal click command. - -var BrowserBot = function(frame) { - this.frame = frame; - this.currentPage = null; - this.currentWindowName = null; - - this.modalDialogTest = null; - this.recordedAlerts = new Array(); - this.recordedConfirmations = new Array(); - this.recordedPrompts = new Array(); - this.openedWindows = {}; - this.nextConfirmResult = true; - this.nextPromptResult = ''; - this.newPageLoaded = false; - this.pageLoadError = null; - - var self = this; - this.recordPageLoad = function() { - LOG.debug("Page load detected"); - try { - LOG.debug("Page load location=" + self.getCurrentWindow().location); - } catch (e) { - self.pageLoadError = e; - return; - } - self.currentPage = null; - self.newPageLoaded = true; - }; - - this.isNewPageLoaded = function() { - if (this.pageLoadError) throw this.pageLoadError; - return self.newPageLoaded; - }; -}; - -BrowserBot.createForFrame = function(frame) { - var browserbot; - LOG.debug("browserName: " + browserVersion.name); - LOG.debug("userAgent: " + navigator.userAgent); - if (browserVersion.isIE) { - browserbot = new IEBrowserBot(frame); - } - else if (browserVersion.isKonqueror) { - browserbot = new KonquerorBrowserBot(frame); - } - else if (browserVersion.isSafari) { - browserbot = new SafariBrowserBot(frame); - } - else { - LOG.info("Using MozillaBrowserBot") - // Use mozilla by default - browserbot = new MozillaBrowserBot(frame); - } - - // Modify the test IFrame so that page loads are detected. - addLoadListener(browserbot.getFrame(), browserbot.recordPageLoad); - return browserbot; -}; - -BrowserBot.prototype.doModalDialogTest = function(test) { - this.modalDialogTest = test; -}; - -BrowserBot.prototype.cancelNextConfirmation = function() { - this.nextConfirmResult = false; -}; - -BrowserBot.prototype.setNextPromptResult = function(result) { - this.nextPromptResult = result; -}; - -BrowserBot.prototype.hasAlerts = function() { - return (this.recordedAlerts.length > 0) ; -}; - -BrowserBot.prototype.getNextAlert = function() { - return this.recordedAlerts.shift(); -}; - -BrowserBot.prototype.hasConfirmations = function() { - return (this.recordedConfirmations.length > 0) ; -}; - -BrowserBot.prototype.getNextConfirmation = function() { - return this.recordedConfirmations.shift(); -}; - -BrowserBot.prototype.hasPrompts = function() { - return (this.recordedPrompts.length > 0) ; -}; - -BrowserBot.prototype.getNextPrompt = function() { - return this.recordedPrompts.shift(); -}; - -BrowserBot.prototype.getFrame = function() { - return this.frame; -}; - -BrowserBot.prototype.selectWindow = function(target) { - // we've moved to a new page - clear the current one - this.currentPage = null; - this.currentWindowName = null; - if (target && target != "null") { - // If window exists - if (this.getTargetWindow(target)) { - this.currentWindowName = target; - } - } -}; - -BrowserBot.prototype.openLocation = function(target) { - // We're moving to a new page - clear the current one - this.currentPage = null; - this.newPageLoaded = false; - - this.setOpenLocation(target); -}; - -BrowserBot.prototype.setIFrameLocation = function(iframe, location) { - iframe.src = location; -}; - -BrowserBot.prototype.setOpenLocation = function(location) { - this.getCurrentWindow().location.href = location; -}; - -BrowserBot.prototype.getCurrentPage = function() { - if (this.currentPage == null) { - var testWindow = this.getCurrentWindow(); - this.modifyWindowToRecordPopUpDialogs(testWindow, this); - this.modifySeparateTestWindowToDetectPageLoads(testWindow); - this.currentPage = PageBot.createForWindow(testWindow); - this.newPageLoaded = false; - } - - return this.currentPage; -}; - -BrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { - windowToModify.alert = function(alert) { - browserBot.recordedAlerts.push(alert); - }; - - windowToModify.confirm = function(message) { - browserBot.recordedConfirmations.push(message); - var result = browserBot.nextConfirmResult; - browserBot.nextConfirmResult = true; - return result; - }; - - windowToModify.prompt = function(message) { - browserBot.recordedPrompts.push(message); - var result = !browserBot.nextConfirmResult ? null : browserBot.nextPromptResult; - browserBot.nextConfirmResult = true; - browserBot.nextPromptResult = ''; - return result; - }; - - // Keep a reference to all popup windows by name - // note that in IE the "windowName" argument must be a valid javascript identifier, it seems. - var originalOpen = windowToModify.open; - windowToModify.open = function(url, windowName, windowFeatures, replaceFlag) { - var openedWindow = originalOpen(url, windowName, windowFeatures, replaceFlag); - selenium.browserbot.openedWindows[windowName] = openedWindow; - return openedWindow; - }; -}; - -/** - * The main IFrame has a single, long-lived onload handler that clears - * Browserbot.currentPage and sets the "newPageLoaded" flag. For separate - * windows, we need to attach a handler each time. This uses the - * "callOnWindowPageTransition" mechanism, which is implemented differently - * for different browsers. - */ -BrowserBot.prototype.modifySeparateTestWindowToDetectPageLoads = function(windowToModify) { - if (this.currentWindowName != null) { - this.callOnWindowPageTransition(this.recordPageLoad, windowToModify); - } -}; - -/** - * Call the supplied function when a the current page unloads and a new one loads. - * This is done by polling continuously until the document changes and is fully loaded. - */ -BrowserBot.prototype.callOnWindowPageTransition = function(loadFunction, windowObject) { - // Since the unload event doesn't fire in Safari 1.3, we start polling immediately - if (windowObject && !windowObject.closed) { - LOG.debug("Starting pollForLoad: " + windowObject.document.location); - this.pollingForLoad = true; - this.pollForLoad(loadFunction, windowObject, windowObject.location, windowObject.location.href); - } -}; - -/** - * Set up a polling timer that will keep checking the readyState of the document until it's complete. - * Since we might call this before the original page is unloaded, we first check to see that the current location - * or href is different from the original one. - */ -BrowserBot.prototype.pollForLoad = function(loadFunction, windowObject, originalLocation, originalHref) { - var windowClosed = true; - try { - windowClosed = windowObject.closed; - } catch (e) { - LOG.debug("exception detecting closed window (I guess it must be closed)"); - LOG.exception(e); - // swallow exceptions which may occur in HTA mode when the window is closed - } - if (null == windowClosed) windowClosed = true; - if (windowClosed) { - this.pollingForLoad = false; - return; - } - - LOG.debug("pollForLoad original: " + originalHref); - try { - - var currentLocation = windowObject.location; - var currentHref = currentLocation.href - - var sameLoc = (originalLocation === currentLocation); - var sameHref = (originalHref === currentHref); - var rs = windowObject.document.readyState; - - if (rs == null) rs = 'complete'; - - if (!(sameLoc && sameHref) && rs == 'complete') { - LOG.debug("pollForLoad complete: " + rs + " (" + currentHref + ")"); - loadFunction(); - this.pollingForLoad = false; - return; - } - var self = this; - LOG.debug("pollForLoad continue: " + currentHref); - window.setTimeout(function() {self.pollForLoad(loadFunction, windowObject, originalLocation, originalHref);}, 500); - } catch (e) { - LOG.error("Exception during pollForLoad; this should get noticed soon!"); - LOG.exception(e); - this.pageLoadError = e; - } -}; - - -BrowserBot.prototype.getContentWindow = function() { - return this.getFrame().contentWindow || frames[this.getFrame().id]; -}; - -BrowserBot.prototype.getTargetWindow = function(windowName) { - LOG.debug("getTargetWindow(" + windowName + ")"); - // First look in the map of opened windows - var targetWindow = this.openedWindows[windowName]; - if (!targetWindow) { - var evalString = "this.getContentWindow().window." + windowName; - targetWindow = eval(evalString); - } - if (!targetWindow) { - throw new SeleniumError("Window does not exist"); - } - return targetWindow; -}; - -BrowserBot.prototype.getCurrentWindow = function() { - var testWindow = this.getContentWindow().window; - if (this.currentWindowName != null) { - testWindow = this.getTargetWindow(this.currentWindowName); - } - return testWindow; -}; - -function MozillaBrowserBot(frame) { - BrowserBot.call(this, frame); -} -MozillaBrowserBot.prototype = new BrowserBot; - -function KonquerorBrowserBot(frame) { - BrowserBot.call(this, frame); -} -KonquerorBrowserBot.prototype = new BrowserBot; - -KonquerorBrowserBot.prototype.setIFrameLocation = function(iframe, location) { - // Window doesn't fire onload event when setting src to the current value, - // so we set it to blank first. - iframe.src = "about:blank"; - iframe.src = location; -}; - -KonquerorBrowserBot.prototype.setOpenLocation = function(location) { - // Window doesn't fire onload event when setting src to the current value, - // so we set it to blank first. - this.getCurrentWindow().location.href = "about:blank"; - this.getCurrentWindow().location.href = location; -}; - -function SafariBrowserBot(frame) { - BrowserBot.call(this, frame); -} -SafariBrowserBot.prototype = new BrowserBot; - -SafariBrowserBot.prototype.setIFrameLocation = KonquerorBrowserBot.prototype.setIFrameLocation; - -function IEBrowserBot(frame) { - BrowserBot.call(this, frame); -} -IEBrowserBot.prototype = new BrowserBot; - -IEBrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { - BrowserBot.prototype.modifyWindowToRecordPopUpDialogs(windowToModify, browserBot); - - // we will call the previous version of this method from within our own interception - oldShowModalDialog = windowToModify.showModalDialog; - - windowToModify.showModalDialog = function(url, args, features) { - // Get relative directory to where TestRunner.html lives - // A risky assumption is that the user's TestRunner is named TestRunner.html - var doc_location = document.location.toString(); - var end_of_base_ref = doc_location.indexOf('TestRunner.html'); - var base_ref = doc_location.substring(0, end_of_base_ref); - - var fullURL = base_ref + "TestRunner.html?singletest=" + escape(browserBot.modalDialogTest) + "&autoURL=" + escape(url) + "&runInterval=" + runInterval; - browserBot.modalDialogTest = null; - - var returnValue = oldShowModalDialog(fullURL, args, features); - return returnValue; - }; -}; - -SafariBrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { - BrowserBot.prototype.modifyWindowToRecordPopUpDialogs(windowToModify, browserBot); - - var originalOpen = windowToModify.open; - /* - * Safari seems to be broken, so that when we manually trigger the onclick method - * of a button/href, any window.open calls aren't resolved relative to the app location. - * So here we replace the open() method with one that does resolve the url correctly. - */ - windowToModify.open = function(url, windowName, windowFeatures, replaceFlag) { - - if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("/")) { - return originalOpen(url, windowName, windowFeatures, replaceFlag); - } - - // Reduce the current path to the directory - var currentPath = windowToModify.location.pathname || "/"; - currentPath = currentPath.replace(/\/[^\/]*$/, "/"); - - // Remove any leading "./" from the new url. - url = url.replace(/^\.\//, ""); - - newUrl = currentPath + url; - - return originalOpen(newUrl, windowName, windowFeatures, replaceFlag); - }; -}; - -var PageBot = function(pageWindow) { - if (pageWindow) { - this.currentWindow = pageWindow; - this.currentDocument = pageWindow.document; - this.location = pageWindow.location; - this.title = function() {return this.currentDocument.title;}; - } - - // Register all locateElementBy* functions - // TODO - don't do this in the constructor - only needed once ever - this.locationStrategies = {}; - for (var functionName in this) { - var result = /^locateElementBy([A-Z].+)$/.exec(functionName); - if (result != null) { - var locatorFunction = this[functionName]; - if (typeof(locatorFunction) != 'function') { - continue; - } - // Use a specified prefix in preference to one generated from - // the function name - var locatorPrefix = locatorFunction.prefix || result[1].toLowerCase(); - this.locationStrategies[locatorPrefix] = locatorFunction; - } - } - - /** - * Find a locator based on a prefix. - */ - this.findElementBy = function(locatorType, locator, inDocument) { - var locatorFunction = this.locationStrategies[locatorType]; - if (! locatorFunction) { - throw new SeleniumError("Unrecognised locator type: '" + locatorType + "'"); - } - return locatorFunction.call(this, locator, inDocument); - }; - - /** - * The implicit locator, that is used when no prefix is supplied. - */ - this.locationStrategies['implicit'] = function(locator, inDocument) { - if (locator.startsWith('//')) { - return this.locateElementByXPath(locator, inDocument); - } - if (locator.startsWith('document.')) { - return this.locateElementByDomTraversal(locator, inDocument); - } - return this.locateElementByIdentifier(locator, inDocument); - }; - -}; - -PageBot.createForWindow = function(windowObject) { - if (browserVersion.isIE) { - return new IEPageBot(windowObject); - } - else if (browserVersion.isKonqueror) { - return new KonquerorPageBot(windowObject); - } - else if (browserVersion.isSafari) { - return new SafariPageBot(windowObject); - } - else if (browserVersion.isOpera) { - return new OperaPageBot(windowObject); - } - else { - LOG.info("Using MozillaPageBot") - // Use mozilla by default - return new MozillaPageBot(windowObject); - } -}; - -var MozillaPageBot = function(pageWindow) { - PageBot.call(this, pageWindow); -}; -MozillaPageBot.prototype = new PageBot(); - -var KonquerorPageBot = function(pageWindow) { - PageBot.call(this, pageWindow); -}; -KonquerorPageBot.prototype = new PageBot(); - -var SafariPageBot = function(pageWindow) { - PageBot.call(this, pageWindow); -}; -SafariPageBot.prototype = new PageBot(); - -var IEPageBot = function(pageWindow) { - PageBot.call(this, pageWindow); -}; -IEPageBot.prototype = new PageBot(); - -OperaPageBot = function(pageWindow) { - PageBot.call(this, pageWindow); -}; -OperaPageBot.prototype = new PageBot(); - -/* -* Finds an element on the current page, using various lookup protocols -*/ -PageBot.prototype.findElement = function(locator) { - var locatorType = 'implicit'; - var locatorString = locator; - - // If there is a locator prefix, use the specified strategy - var result = locator.match(/^([A-Za-z]+)=(.+)/); - if (result) { - locatorType = result[1].toLowerCase(); - locatorString = result[2]; - } - - var element = this.findElementBy(locatorType, locatorString, this.currentDocument); - if (element != null) { - return element; - } - for (var i = 0; i < this.currentWindow.frames.length; i++) { - element = this.findElementBy(locatorType, locatorString, this.currentWindow.frames[i].document); - if (element != null) { - return element; - } - } - - // Element was not found by any locator function. - throw new SeleniumError("Element " + locator + " not found"); -}; - -/** - * In non-IE browsers, getElementById() does not search by name. Instead, we - * we search separately by id and name. - */ -PageBot.prototype.locateElementByIdentifier = function(identifier, inDocument) { - return PageBot.prototype.locateElementById(identifier, inDocument) - || PageBot.prototype.locateElementByName(identifier, inDocument) - || null; -}; - -/** - * In IE, getElementById() also searches by name - this is an optimisation for IE. - */ -IEPageBot.prototype.locateElementByIdentifer = function(identifier, inDocument) { - return inDocument.getElementById(identifier); -}; - -/** - * Find the element with id - can't rely on getElementById, coz it returns by name as well in IE.. - */ -PageBot.prototype.locateElementById = function(identifier, inDocument) { - var element = inDocument.getElementById(identifier); - if (element && element.id === identifier) { - return element; - } - else { - return null; - } -}; - -/** - * Find an element by name, refined by (optional) element-filter - * expressions. - */ -PageBot.prototype.locateElementByName = function(locator, document) { - var elements = document.getElementsByTagName("*"); - - var filters = locator.split(' '); - filters[0] = 'name=' + filters[0]; - - while (filters.length) { - var filter = filters.shift(); - elements = this.selectElements(filter, elements, 'value'); - } - - if (elements.length > 0) { - return elements[0]; - } - return null; -}; - -/** -* Finds an element using by evaluating the "document.*" string against the -* current document object. Dom expressions must begin with "document." -*/ -PageBot.prototype.locateElementByDomTraversal = function(domTraversal, inDocument) { - if (domTraversal.indexOf("document.") != 0) { - return null; - } - - // Trim the leading 'document' - domTraversal = domTraversal.substr(9); - var locatorScript = "inDocument." + domTraversal; - var element = eval(locatorScript); - - if (!element) { - return null; - } - - return element; -}; -PageBot.prototype.locateElementByDomTraversal.prefix = "dom"; - -/** -* Finds an element identified by the xpath expression. Expressions _must_ -* begin with "//". -*/ -PageBot.prototype.locateElementByXPath = function(xpath, inDocument) { - - // Trim any trailing "/": not valid xpath, and remains from attribute - // locator. - if (xpath.charAt(xpath.length - 1) == '/') { - xpath = xpath.slice(0, -1); - } - - // Handle //tag - var match = xpath.match(/^\/\/(\w+|\*)$/); - if (match) { - var elements = inDocument.getElementsByTagName(match[1].toUpperCase()); - if (elements == null) return null; - return elements[0]; - } - - // Handle //tag[@attr='value'] - var match = xpath.match(/^\/\/(\w+|\*)\[@(\w+)=('([^\']+)'|"([^\"]+)")\]$/); - if (match) { - return this.findElementByTagNameAndAttributeValue( - inDocument, - match[1].toUpperCase(), - match[2].toLowerCase(), - match[3].slice(1, -1) - ); - } - - // Handle //tag[text()='value'] - var match = xpath.match(/^\/\/(\w+|\*)\[text\(\)=('([^\']+)'|"([^\"]+)")\]$/); - if (match) { - return this.findElementByTagNameAndText( - inDocument, - match[1].toUpperCase(), - match[2].slice(1, -1) - ); - } - - return this.findElementUsingFullXPath(xpath, inDocument); -}; - -PageBot.prototype.findElementByTagNameAndAttributeValue = function( - inDocument, tagName, attributeName, attributeValue -) { - if (browserVersion.isIE && attributeName == "class") { - attributeName = "className"; - } - var elements = inDocument.getElementsByTagName(tagName); - for (var i = 0; i < elements.length; i++) { - var elementAttr = elements[i].getAttribute(attributeName); - if (elementAttr == attributeValue) { - return elements[i]; - } - } - return null; -}; - -PageBot.prototype.findElementByTagNameAndText = function( - inDocument, tagName, text -) { - var elements = inDocument.getElementsByTagName(tagName); - for (var i = 0; i < elements.length; i++) { - if (getText(elements[i]) == text) { - return elements[i]; - } - } - return null; -}; - -PageBot.prototype.findElementUsingFullXPath = function(xpath, inDocument) { - // Use document.evaluate() if it's available - if (inDocument.evaluate) { - return inDocument.evaluate(xpath, inDocument, null, 0, null).iterateNext(); - } - - // If not, fall back to slower JavaScript implementation - var context = new ExprContext(inDocument); - var xpathObj = xpathParse(xpath); - var xpathResult = xpathObj.evaluate(context); - if (xpathResult && xpathResult.value) { - return xpathResult.value[0]; - } - return null; -}; - -/** -* Finds a link element with text matching the expression supplied. Expressions must -* begin with "link:". -*/ -PageBot.prototype.locateElementByLinkText = function(linkText, inDocument) { - var links = inDocument.getElementsByTagName('a'); - for (var i = 0; i < links.length; i++) { - var element = links[i]; - if (PatternMatcher.matches(linkText, getText(element))) { - return element; - } - } - return null; -}; -PageBot.prototype.locateElementByLinkText.prefix = "link"; - -/** -* Returns an attribute based on an attribute locator. This is made up of an element locator -* suffixed with @attribute-name. -*/ -PageBot.prototype.findAttribute = function(locator) { - // Split into locator + attributeName - var attributePos = locator.lastIndexOf("@"); - var elementLocator = locator.slice(0, attributePos); - var attributeName = locator.slice(attributePos + 1); - - // Find the element. - var element = this.findElement(elementLocator); - - // Handle missing "class" attribute in IE. - if (browserVersion.isIE && attributeName == "class") { - attributeName = "className"; - } - - // Get the attribute value. - var attributeValue = element.getAttribute(attributeName); - - return attributeValue ? attributeValue.toString() : null; -}; - -/* -* Select the specified option and trigger the relevant events of the element. -*/ -PageBot.prototype.selectOption = function(element, optionToSelect) { - triggerEvent(element, 'focus', false); - var changed = false; - for (var i = 0; i < element.options.length; i++) { - var option = element.options[i]; - if (option.selected && option != optionToSelect) { - option.selected = false; - changed = true; - } - else if (!option.selected && option == optionToSelect) { - option.selected = true; - changed = true; - } - } - - if (changed) { - triggerEvent(element, 'change', true); - } - triggerEvent(element, 'blur', false); -}; - -/* -* Select the specified option and trigger the relevant events of the element. -*/ -PageBot.prototype.addSelection = function(element, option) { - this.checkMultiselect(element); - triggerEvent(element, 'focus', false); - if (!option.selected) { - option.selected = true; - triggerEvent(element, 'change', true); - } - triggerEvent(element, 'blur', false); -}; - -/* -* Select the specified option and trigger the relevant events of the element. -*/ -PageBot.prototype.removeSelection = function(element, option) { - this.checkMultiselect(element); - triggerEvent(element, 'focus', false); - if (option.selected) { - option.selected = false; - triggerEvent(element, 'change', true); - } - triggerEvent(element, 'blur', false); -}; - -PageBot.prototype.checkMultiselect = function(element) { - if (!element.multiple) - { - throw new SeleniumError("Not a multi-select"); - } - -}; - -PageBot.prototype.replaceText = function(element, stringValue) { - triggerEvent(element, 'focus', false); - triggerEvent(element, 'select', true); - element.value=stringValue; - if (!browserVersion.isChrome) { - // In chrome URL, The change event is already fired by setting the value. - triggerEvent(element, 'change', true); - } - triggerEvent(element, 'blur', false); -}; - -MozillaPageBot.prototype.clickElement = function(element) { - - triggerEvent(element, 'focus', false); - - // Add an event listener that detects if the default action has been prevented. - // (This is caused by a javascript onclick handler returning false) - var preventDefault = false; - - element.addEventListener("click", function(evt) {preventDefault = evt.getPreventDefault();}, false); - - // Trigger the click event. - triggerMouseEvent(element, 'click', true); - - // Perform the link action if preventDefault was set. - // In chrome URL, the link action is already executed by triggerMouseEvent. - if (!browserVersion.isChrome && !preventDefault) { - // Try the element itself, as well as it's parent - this handles clicking images inside links. - if (element.href) { - this.currentWindow.location.href = element.href; - } - else if (element.parentNode && element.parentNode.href) { - this.currentWindow.location.href = element.parentNode.href; - } - } - - if (this.windowClosed()) { - return; - } - - triggerEvent(element, 'blur', false); -}; - -OperaPageBot.prototype.clickElement = function(element) { - - triggerEvent(element, 'focus', false); - - // Trigger the click event. - triggerMouseEvent(element, 'click', true); - - if (isDefined(element.checked)) { - // In Opera, clicking won't check/uncheck - if (element.type == "checkbox") { - element.checked = !element.checked; - } else { - element.checked = true; - } - } - - if (this.windowClosed()) { - return; - } - - triggerEvent(element, 'blur', false); -}; - - -KonquerorPageBot.prototype.clickElement = function(element) { - - triggerEvent(element, 'focus', false); - - if (element.click) { - element.click(); - } - else { - triggerMouseEvent(element, 'click', true); - } - - if (this.windowClosed()) { - return; - } - - triggerEvent(element, 'blur', false); -}; - -SafariPageBot.prototype.clickElement = function(element) { - - triggerEvent(element, 'focus', false); - - var wasChecked = element.checked; - - // For form element it is simple. - if (element.click) { - element.click(); - } - // For links and other elements, event emulation is required. - else { - triggerMouseEvent(element, 'click', true); - - // Unfortunately, triggering the event doesn't seem to activate onclick handlers. - // We currently call onclick for the link, but I'm guessing that the onclick for containing - // elements is not being called. - var success = true; - if (element.onclick) { - var evt = document.createEvent('HTMLEvents'); - evt.initEvent('click', true, true); - var onclickResult = element.onclick(evt); - if (onclickResult === false) { - success = false; - } - } - - if (success) { - // Try the element itself, as well as it's parent - this handles clicking images inside links. - if (element.href) { - this.currentWindow.location.href = element.href; - } - else if (element.parentNode.href) { - this.currentWindow.location.href = element.parentNode.href; - } else { - // This is true for buttons outside of forms, and maybe others. - LOG.warn("Ignoring 'click' call for button outside form, or link without href." - + "Using buttons without an enclosing form can cause wierd problems with URL resolution in Safari." ); - // I implemented special handling for window.open, but unfortunately this behaviour is also displayed - // when we have a button without an enclosing form that sets document.location in the onclick handler. - // The solution is to always use an enclosing form for a button. - } - } - } - - if (this.windowClosed()) { - return; - } - - triggerEvent(element, 'blur', false); -}; - -IEPageBot.prototype.clickElement = function(element) { - - triggerEvent(element, 'focus', false); - - var wasChecked = element.checked; - - // Set a flag that records if the page will unload - this isn't always accurate, because - // <a href="javascript:alert('foo'):"> triggers the onbeforeunload event, even thought the page won't unload - var pageUnloading = false; - var pageUnloadDetector = function() {pageUnloading = true;}; - this.currentWindow.attachEvent("onbeforeunload", pageUnloadDetector); - - element.click(); - - // If the page is going to unload - still attempt to fire any subsequent events. - // However, we can't guarantee that the page won't unload half way through, so we need to handle exceptions. - try { - this.currentWindow.detachEvent("onbeforeunload", pageUnloadDetector); - - if (this.windowClosed()) { - return; - } - - // Onchange event is not triggered automatically in IE. - if (isDefined(element.checked) && wasChecked != element.checked) { - triggerEvent(element, 'change', true); - } - - triggerEvent(element, 'blur', false); - } - catch (e) { - // If the page is unloading, we may get a "Permission denied" or "Unspecified error". - // Just ignore it, because the document may have unloaded. - if (pageUnloading) { - LOG.warn("Caught exception when firing events on unloading page: " + e.message); - return; - } - throw e; - } -}; - -PageBot.prototype.windowClosed = function(element) { - return this.currentWindow.closed; -}; - -PageBot.prototype.bodyText = function() { - return getText(this.currentDocument.body); -}; - -PageBot.prototype.getAllButtons = function() { - var elements = this.currentDocument.getElementsByTagName('input'); - var result = ''; - - for (var i = 0; i < elements.length; i++) { - if (elements[i].type == 'button' || elements[i].type == 'submit' || elements[i].type == 'reset') { - result += elements[i].id; - - result += ','; - } - } - - return result; -}; - - -PageBot.prototype.getAllFields = function() { - var elements = this.currentDocument.getElementsByTagName('input'); - var result = ''; - - for (var i = 0; i < elements.length; i++) { - if (elements[i].type == 'text') { - result += elements[i].id; - - result += ','; - } - } - - return result; -}; - -PageBot.prototype.getAllLinks = function() { - var elements = this.currentDocument.getElementsByTagName('a'); - var result = ''; - - for (var i = 0; i < elements.length; i++) { - result += elements[i].id; - - result += ','; - } - - return result; -}; - -PageBot.prototype.setContext = function(strContext, logLevel) { - //set the current test title - document.getElementById("context").innerHTML=strContext; - if (logLevel!=null) { - LOG.setLogLevelThreshold(logLevel); - } -}; - -function isDefined(value) { - return typeof(value) != undefined; -} - -PageBot.prototype.goBack = function() { - this.currentWindow.history.back(); - if (browserVersion.isOpera && !selenium.browserbot.pollingForLoad) { - // DGF On Opera, goBack doesn't re-trigger a load event, so we have to poll for it - selenium.browserbot.callOnWindowPageTransition(selenium.browserbot.recordPageLoad, this.currentWindow); - } -}; - -PageBot.prototype.goForward = function() { - this.currentWindow.history.forward(); -}; - -PageBot.prototype.close = function() { - if (browserVersion.isChrome) { - this.currentWindow.close(); - } else { - this.currentWindow.eval("window.close();"); - } -}; - -PageBot.prototype.refresh = function() { - this.currentWindow.location.reload(true); -}; - -/** - * Refine a list of elements using a filter. - */ -PageBot.prototype.selectElementsBy = function(filterType, filter, elements) { - var filterFunction = PageBot.filterFunctions[filterType]; - if (! filterFunction) { - throw new SeleniumError("Unrecognised element-filter type: '" + filterType + "'"); - } - - return filterFunction(filter, elements); -}; - -PageBot.filterFunctions = {}; - -PageBot.filterFunctions.name = function(name, elements) { - var selectedElements = []; - for (var i = 0; i < elements.length; i++) { - if (elements[i].name === name) { - selectedElements.push(elements[i]); - } - } - return selectedElements; -}; - -PageBot.filterFunctions.value = function(value, elements) { - var selectedElements = []; - for (var i = 0; i < elements.length; i++) { - if (elements[i].value === value) { - selectedElements.push(elements[i]); - } - } - return selectedElements; -}; - -PageBot.filterFunctions.index = function(index, elements) { - index = Number(index); - if (isNaN(index) || index < 0) { - throw new SeleniumError("Illegal Index: " + index); - } - if (elements.length <= index) { - throw new SeleniumError("Index out of range: " + index); - } - return [elements[index]]; -}; - -PageBot.prototype.selectElements = function(filterExpr, elements, defaultFilterType) { - - var filterType = (defaultFilterType || 'value'); - - // If there is a filter prefix, use the specified strategy - var result = filterExpr.match(/^([A-Za-z]+)=(.+)/); - if (result) { - filterType = result[1].toLowerCase(); - filterExpr = result[2]; - } - - return this.selectElementsBy(filterType, filterExpr, elements); -}; - -/** - * Find an element by class - */ -PageBot.prototype.locateElementByClass = function(locator, document) { - return Element.findFirstMatchingChild(document, - function(element) { - return element.className == locator - } - ); -} - -/** - * Find an element by alt - */ -PageBot.prototype.locateElementByAlt = function(locator, document) { - return Element.findFirstMatchingChild(document, - function(element) { - return element.alt == locator - } - ); -} - diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-browserdetect.js b/tests/FunctionalTests/selenium/core/scripts/selenium-browserdetect.js deleted file mode 100755 index 137a1518..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-browserdetect.js +++ /dev/null @@ -1,115 +0,0 @@ -/* -* 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. -* -*/ - -// Although it's generally better web development practice not to use browser-detection -// (feature detection is better), the subtle browser differences that Selenium has to -// work around seem to make it necessary. Maybe as we learn more about what we need, -// we can do this in a more "feature-centric" rather than "browser-centric" way. - -BrowserVersion = function() { - this.name = navigator.appName; - - if (window.opera != null) - { - this.browser = BrowserVersion.OPERA; - this.isOpera = true; - return; - } - - var self = this; - - var checkChrome = function() { - var loc = window.document.location.href; - try { - loc = window.top.document.location.href; - } catch (e) { - // can't see the top (that means we might be chrome, but it's impossible to be sure) - self.isChromeDetectable = "no, top location couldn't be read in this window"; - } - - if (/^chrome:\/\//.test(loc)) { - self.isChrome = true; - } else { - self.isChrome = false; - } - } - - if (this.name == "Microsoft Internet Explorer") - { - this.browser = BrowserVersion.IE; - this.isIE = true; - if (window.top.SeleniumHTARunner && window.top.document.location.pathname.match(/.hta$/i)) { - this.isHTA = true; - } - if ("0" == navigator.appMinorVersion) { - this.preSV1 = true; - } - return; - } - - if (navigator.userAgent.indexOf('Safari') != -1) - { - this.browser = BrowserVersion.SAFARI; - this.isSafari = true; - this.khtml = true; - return; - } - - if (navigator.userAgent.indexOf('Konqueror') != -1) - { - this.browser = BrowserVersion.KONQUEROR; - this.isKonqueror = true; - this.khtml = true; - return; - } - - if (navigator.userAgent.indexOf('Firefox') != -1) - { - this.browser = BrowserVersion.FIREFOX; - this.isFirefox = true; - this.isGecko = true; - var result = /.*Firefox\/([\d\.]+).*/.exec(navigator.userAgent); - if (result) - { - this.firefoxVersion = result[1]; - } - checkChrome(); - return; - } - - if (navigator.userAgent.indexOf('Gecko') != -1) - { - this.browser = BrowserVersion.MOZILLA; - this.isMozilla = true; - this.isGecko = true; - checkChrome(); - return; - } - - this.browser = BrowserVersion.UNKNOWN; -} - -BrowserVersion.OPERA = "Opera"; -BrowserVersion.IE = "IE"; -BrowserVersion.KONQUEROR = "Konqueror"; -BrowserVersion.SAFARI = "Safari"; -BrowserVersion.FIREFOX = "Firefox"; -BrowserVersion.MOZILLA = "Mozilla"; -BrowserVersion.UNKNOWN = "Unknown"; - -browserVersion = new BrowserVersion(); - diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-commandhandlers.js b/tests/FunctionalTests/selenium/core/scripts/selenium-commandhandlers.js deleted file mode 100755 index ee01ea76..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-commandhandlers.js +++ /dev/null @@ -1,371 +0,0 @@ -/* -* 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, dontCheckAlertsAndConfirms) { - var handler = new ActionHandler(action, wait, dontCheckAlertsAndConfirms); - 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.getCommandHandler = function(name) { - return this.actions[name] || this.accessors[name] || this.asserts[name] || null; - }; - - this.registerAll = function(commandObject) { - registerAllAccessors(commandObject); - registerAllActions(commandObject); - registerAllAsserts(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, action.dontCheckAlertsAndConfirms); - - // Register actionName + "AndWait" with the wait flag; - var waitActionName = actionName + "AndWait"; - self.registerAction(waitActionName, action, true, action.dontCheckAlertsAndConfirms); - } - } - }; - - - 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 getBlah(target), - // return a "predicate" equivalient to isBlah(target, value) that - // is true when the value returned by the accessor matches the specified value. - this.createPredicateFromSingleArgAccessor = function(accessor) { - return function(target, value) { - var accessorResult = accessor.call(this, target); - if (PatternMatcher.matches(value, accessorResult)) { - return new PredicateResult(true, "Actual value '" + accessorResult + "' did match '" + value + "'"); - } else { - return new PredicateResult(false, "Actual value '" + accessorResult + "' did not match '" + value + "'"); - } - }; - }; - - // Given a (no-arg) accessor function getBlah(), - // return a "predicate" equivalient to isBlah(value) that - // is true when the value returned by the accessor matches the specified value. - this.createPredicateFromNoArgAccessor = function(accessor) { - return function(value) { - var accessorResult = accessor.call(this); - if (PatternMatcher.matches(value, accessorResult)) { - return new PredicateResult(true, "Actual value '" + accessorResult + "' did match '" + value + "'"); - } else { - return new PredicateResult(false, "Actual value '" + accessorResult + "' did not match '" + value + "'"); - } - }; - }; - - // Given a boolean accessor function isBlah(), - // return a "predicate" equivalient to isBlah() that - // returns an appropriate PredicateResult value. - this.createPredicateFromBooleanAccessor = function(accessor) { - return function() { - var accessorResult; - if (arguments.length > 2) throw new SeleniumError("Too many arguments! " + arguments.length); - if (arguments.length == 2) { - accessorResult = accessor.call(this, arguments[0], arguments[1]); - } else if (arguments.length == 1) { - accessorResult = accessor.call(this, arguments[0]); - } else { - accessorResult = accessor.call(this); - } - if (accessorResult) { - return new PredicateResult(true, "true"); - } else { - return new PredicateResult(false, "false"); - } - }; - }; - - // Given an accessor fuction getBlah([target]) (target is optional) - // return a predicate equivalent to isBlah([target,] value) that - // is true when the value returned by the accessor matches the specified value. - this.createPredicateFromAccessor = function(accessor) { - if (accessor.length == 0) { - return self.createPredicateFromNoArgAccessor(accessor); - } - return self.createPredicateFromSingleArgAccessor(accessor); - }; - - // Given a predicate, return the negation of that predicate. - // Leaves the message unchanged. - // Used to create assertNot, verifyNot, and waitForNot commands. - this.invertPredicate = function(predicate) { - return function(target, value) { - var result = predicate.call(this, target, value); - result.isTrue = ! result.isTrue; - return result; - }; - }; - - // Convert an isBlahBlah(target, value) function into an assertBlahBlah(target, value) function. - this.createAssertionFromPredicate = function(predicate) { - return function(target, value) { - var result = predicate.call(this, target, value); - if (!result.isTrue) { - Assert.fail(result.message); - } - }; - }; - - // Register an assertion, a verification, a negative assertion, - // and a negative verification based on the specified accessor. - this.registerAssertionsBasedOnAccessor = function(accessor, baseName, predicate) { - if (predicate==null) { - predicate = self.createPredicateFromAccessor(accessor); - } - var assertion = self.createAssertionFromPredicate(predicate); - // Register an assert with the "assert" prefix, and halt on failure. - self.registerAssert("assert" + baseName, assertion, true); - // Register a verify with the "verify" prefix, and do not halt on failure. - self.registerAssert("verify" + baseName, assertion, false); - - var invertedPredicate = self.invertPredicate(predicate); - var negativeAssertion = self.createAssertionFromPredicate(invertedPredicate); - - var result = /^(.*)Present$/.exec(baseName); - if (result==null) { - // Register an assertNot with the "assertNot" prefix, and halt on failure. - self.registerAssert("assertNot"+baseName, negativeAssertion, true); - // Register a verifyNot with the "verifyNot" prefix, and do not halt on failure. - self.registerAssert("verifyNot"+baseName, negativeAssertion, false); - } - else { - var invertedBaseName = result[1] + "NotPresent"; - - // Register an assertNot ending w/ "NotPresent", and halt on failure. - self.registerAssert("assert"+invertedBaseName, negativeAssertion, true); - // Register an assertNot ending w/ "NotPresent", and do not halt on failure. - self.registerAssert("verify"+invertedBaseName, negativeAssertion, false); - } - }; - - - // Convert an isBlahBlah(target, value) function into a waitForBlahBlah(target, value) function. - this.createWaitForActionFromPredicate = function(predicate) { - var action = function(target, value) { - var seleniumApi = this; - testLoop.waitForCondition = function () { - try { - return predicate.call(seleniumApi, target, value).isTrue; - } catch (e) { - // Treat exceptions as meaning the condition is not yet met. - // Useful, for example, for waitForValue when the element has - // not even been created yet. - // TODO: possibly should rethrow some types of exception. - return false; - } - }; - }; - return action; - }; - - // Register a waitForBlahBlah and waitForNotBlahBlah based on the specified accessor. - this.registerWaitForCommandsBasedOnAccessor = function(accessor, baseName, predicate) { - if (predicate==null) { - predicate = self.createPredicateFromAccessor(accessor); - } - var waitForAction = self.createWaitForActionFromPredicate(predicate); - self.registerAction("waitFor"+baseName, waitForAction, false, true); - var invertedPredicate = self.invertPredicate(predicate); - var waitForNotAction = self.createWaitForActionFromPredicate(invertedPredicate); - self.registerAction("waitForNot"+baseName, waitForNotAction, false, true); - } - - // Register a storeBlahBlah based on the specified accessor. - this.registerStoreCommandBasedOnAccessor = function(accessor, baseName) { - var action; - if (accessor.length == 1) { - action = function(target, varName) { - storedVars[varName] = accessor.call(this, target); - }; - } else { - action = function(varName) { - storedVars[varName] = accessor.call(this); - }; - } - self.registerAction("store"+baseName, action, false, accessor.dontCheckAlertsAndConfirms); - }; - - // Methods of the form getFoo(target) result in commands: - // getFoo, assertFoo, verifyFoo, assertNotFoo, verifyNotFoo - // storeFoo, waitForFoo, and waitForNotFoo. - 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); - self.registerStoreCommandBasedOnAccessor(accessor, baseName); - self.registerWaitForCommandsBasedOnAccessor(accessor, baseName); - } - var match = /^is([A-Z].+)$/.exec(functionName); - if (match != null) { - var accessor = commandObject[functionName]; - var baseName = match[1]; - var predicate = self.createPredicateFromBooleanAccessor(accessor); - self.registerAccessor(functionName, accessor); - self.registerAssertionsBasedOnAccessor(accessor, baseName, predicate); - self.registerStoreCommandBasedOnAccessor(accessor, baseName); - self.registerWaitForCommandsBasedOnAccessor(accessor, baseName, predicate); - } - } - }; - - -} - -function PredicateResult(isTrue, message) { - this.isTrue = isTrue; - this.message = message; -} - -// NOTE: The CommandHandler is effectively an abstract base for -// various handlers including ActionHandler, AccessorHandler and AssertHandler. -// Subclasses need to implement an execute(seleniumApi, command) function, -// where seleniumApi is the Selenium object, and command a SeleniumCommand object. -function CommandHandler(type, haltOnFailure, executor) { - this.type = type; - this.haltOnFailure = haltOnFailure; - this.executor = executor; -} - -// An ActionHandler is a command handler that executes the sepcified action, -// possibly checking for alerts and confirmations (if checkAlerts is set), and -// possibly waiting for a page load if wait is set. -function ActionHandler(action, wait, dontCheckAlerts) { - CommandHandler.call(this, "action", true, action); - if (wait) { - this.wait = true; - } - // note that dontCheckAlerts could be undefined!!! - this.checkAlerts = (dontCheckAlerts) ? false : true; -} -ActionHandler.prototype = new CommandHandler; -ActionHandler.prototype.execute = function(seleniumApi, command) { - if (this.checkAlerts && (null==/(Alert|Confirmation)(Not)?Present/.exec(command.command))) { - this.checkForAlerts(seleniumApi); - } - 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); -}; -ActionHandler.prototype.checkForAlerts = function(seleniumApi) { - if ( seleniumApi.browserbot.hasAlerts() ) { - throw new SeleniumError("There was an unexpected Alert! [" + seleniumApi.browserbot.getNextAlert() + "]"); - } - if ( seleniumApi.browserbot.hasConfirmations() ) { - throw new SeleniumError("There was an unexpected Confirmation! [" + seleniumApi.browserbot.getNextConfirmation() + "]"); - } -}; - -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; -}; - -/** - * Handler for assertions and verifications. - */ -function AssertHandler(assertion, haltOnFailure) { - CommandHandler.call(this, "assert", haltOnFailure || false, assertion); -} -AssertHandler.prototype = new CommandHandler; -AssertHandler.prototype.execute = function(seleniumApi, command) { - var result = new CommandResult(); - try { - this.executor.call(seleniumApi, command.target, command.value); - 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 SeleniumError(e.failureMessage); - throw error; - } - result.failed = true; - result.failureMessage = e.failureMessage; - } - return result; -}; - - -function CommandResult(processState) { - this.processState = processState; - this.result = null; -} - -function SeleniumCommand(command, target, value) { - this.command = command; - this.target = target; - this.value = value; -} diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js b/tests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js deleted file mode 100755 index 14c1a07a..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-executionloop.js +++ /dev/null @@ -1,266 +0,0 @@ -/* -* 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; - } -}; - diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-logging.js b/tests/FunctionalTests/selenium/core/scripts/selenium-logging.js deleted file mode 100755 index b0fc67e4..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-logging.js +++ /dev/null @@ -1,112 +0,0 @@ -/* -* 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. -*/ - -var Logger = function() { - this.logWindow = null; -} -Logger.prototype = { - - setLogLevelThreshold: function(logLevel) { - this.pendingLogLevelThreshold = logLevel; - this.show(); - // - // The following message does not show up in the log -- _unless_ I step along w/ the debugger - // down to the append call. I believe this is because the new log window has not yet loaded, - // and therefore the log msg is discarded; but if I step through the debugger, this changes - // the scheduling so as to load that window and make it ready. - // this.info("Log level programmatically set to " + logLevel + " (presumably by driven-mode test code)"); - }, - - getLogWindow: function() { - if (this.logWindow && this.logWindow.closed) { - this.logWindow = null; - } - if (this.logWindow && this.pendingLogLevelThreshold && this.logWindow.setThresholdLevel) { - this.logWindow.setThresholdLevel(this.pendingLogLevelThreshold); - - // can't just directly log because that action would loop back to this code infinitely - this.pendingInfoMessage = "Log level programmatically set to " + this.pendingLogLevelThreshold + " (presumably by driven-mode test code)"; - - this.pendingLogLevelThreshold = null; // let's only go this way one time - } - - return this.logWindow; - }, - - openLogWindow: function() { - this.logWindow = window.open( - getDocumentBase(document) + "SeleniumLog.html", "SeleniumLog", - "width=600,height=250,bottom=0,right=0,status,scrollbars,resizable" - ); - return this.logWindow; - }, - - show: function() { - if (! this.getLogWindow()) { - this.openLogWindow(); - } - }, - - log: function(message, className) { - var logWindow = this.getLogWindow(); - if (logWindow) { - if (logWindow.append) { - if (this.pendingInfoMessage) { - logWindow.append("info: " + this.pendingInfoMessage, "info"); - this.pendingInfoMessage = null; - } - logWindow.append(className + ": " + message, className); - } - } - }, - - close: function(message) { - if (this.logWindow != null) { - try { - this.logWindow.close(); - } catch (e) { - // swallow exception - // the window is probably closed if we get an exception here - } - this.logWindow = null; - } - }, - - debug: function(message) { - this.log(message, "debug"); - }, - - info: function(message) { - this.log(message, "info"); - }, - - warn: function(message) { - this.log(message, "warn"); - }, - - error: function(message) { - this.log(message, "error"); - }, - - exception: function(exception) { - var msg = "Unexpected Exception: " + describe(exception, ', '); - this.error(msg); - } - -}; - -var LOG = new Logger(); - diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-seleneserunner.js b/tests/FunctionalTests/selenium/core/scripts/selenium-seleneserunner.js deleted file mode 100755 index 041b3bf9..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-seleneserunner.js +++ /dev/null @@ -1,300 +0,0 @@ -/* -* Copyright 2005 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"; -errorColor = "#ffffff"; -workingColor = "#DEE7EC"; -doneColor = "#FFFFCC"; - -slowMode = false; - -var cmd1 = document.createElement("div"); -var cmd2 = document.createElement("div"); -var cmd3 = document.createElement("div"); -var cmd4 = document.createElement("div"); - -var postResult = "START"; - -queryString = null; - -function runTest() { - var testAppFrame = document.getElementById('myiframe'); - selenium = Selenium.createForFrame(testAppFrame); - - commandFactory = new CommandHandlerFactory(); - commandFactory.registerAll(selenium); - - testLoop = new TestLoop(commandFactory); - - testLoop.nextCommand = nextCommand; - testLoop.commandStarted = commandStarted; - testLoop.commandComplete = commandComplete; - testLoop.commandError = commandError; - testLoop.requiresCallBack = true; - testLoop.testComplete = function() { - window.status = "Selenium Tests Complete, for this Test" - // Continue checking for new results - testLoop.continueTest(); - postResult = "START"; - }; - - document.getElementById("commandList").appendChild(cmd4); - document.getElementById("commandList").appendChild(cmd3); - document.getElementById("commandList").appendChild(cmd2); - document.getElementById("commandList").appendChild(cmd1); - - var doContinue = getQueryVariable("continue"); - if (doContinue != null) postResult = "OK"; - - testLoop.start(); -} - -function getQueryString() { - if (queryString != null) return queryString; - if (browserVersion.isHTA) { - var args = extractArgs(); - if (args.length < 2) return null; - queryString = args[1]; - return queryString; - } else { - return location.search.substr(1); - } -} - -function extractArgs() { - var str = SeleniumHTARunner.commandLine; - if (str == null || str == "") return new Array(); - var matches = str.match(/(?:"([^"]+)"|(?!"([^"]+)")(\S+))/g); - // We either want non quote stuff ([^"]+) surrounded by quotes - // or we want to look-ahead, see that the next character isn't - // a quoted argument, and then grab all the non-space stuff - // this will return for the line: "foo" bar - // the results "\"foo\"" and "bar" - - // So, let's unquote the quoted arguments: - var args = new Array; - for (var i = 0; i < matches.length; i++) { - args[i] = matches[i]; - args[i] = args[i].replace(/^"(.*)"$/, "$1"); - } - return args; -} - -function getQueryVariable(variable) { - var query = getQueryString(); - if (query == null) return null; - var vars = query.split("&"); - for (var i=0;i<vars.length;i++) { - var pair = vars[i].split("="); - if (pair[0] == variable) { - return pair[1]; - } - } -} - -function buildBaseUrl() { - var baseUrl = getQueryVariable("baseUrl"); - if (baseUrl != null) return baseUrl; - var lastSlash = window.location.href.lastIndexOf('/'); - baseUrl = window.location.href.substring(0, lastSlash+1); - return baseUrl; -} - -function buildDriverParams() { - var params = ""; - - var host = getQueryVariable("driverhost"); - var port = getQueryVariable("driverport"); - if (host != undefined && port != undefined) { - params = params + "&driverhost=" + host + "&driverport=" + port; - } - - var sessionId = getQueryVariable("sessionId"); - if (sessionId != undefined) { - params = params + "&sessionId=" + sessionId; - } - - return params; -} - -function preventBrowserCaching() { - var t = (new Date()).getTime(); - return "&counterToMakeURsUniqueAndSoStopPageCachingInTheBrowser=" + t; -} - -function nextCommand() { - xmlHttp = XmlHttp.create(); - try { - - var url = buildBaseUrl(); - if (postResult == "START") { - url = url + "driver/?seleniumStart=true" + buildDriverParams() + preventBrowserCaching(); - } else { - url = url + "driver/?" + buildDriverParams() + preventBrowserCaching(); - } - LOG.debug("XMLHTTPRequesting " + url); - xmlHttp.open("POST", url, true); - xmlHttp.onreadystatechange=handleHttpResponse; - xmlHttp.send(postResult); - } catch(e) { - var s = 'xmlHttp returned:\n' - for (key in e) { - s += "\t" + key + " -> " + e[key] + "\n" - } - LOG.error(s); - return null; - } - return null; -} - - function handleHttpResponse() { - if (xmlHttp.readyState == 4) { - if (xmlHttp.status == 200) { - var command = extractCommand(xmlHttp); - testLoop.currentCommand = command; - testLoop.beginNextTest(); - } else { - var s = 'xmlHttp returned: ' + xmlHttp.status + ": " + xmlHttp.statusText; - LOG.error(s); - testLoop.currentCommand = null; - setTimeout("testLoop.beginNextTest();", 2000); - } - - } - } - - -function extractCommand(xmlHttp) { - if (slowMode) { - delay(2000); - } - - var command; - try { - command = xmlHttp.responseText; - } catch (e) { - alert('could not get responseText: ' + e.message); - } - if (command.substr(0,'|testComplete'.length)=='|testComplete') { - return null; - } - - return createCommandFromRequest(command); -} - -function commandStarted(command) { - commandNode = document.createElement("div"); - innerHTML = command.command + '('; - if (command.target != null && command.target != "") { - innerHTML += command.target; - if (command.value != null && command.value != "") { - innerHTML += ', ' + command.value; - } - } - innerHTML += ")"; - commandNode.innerHTML = innerHTML; - commandNode.style.backgroundColor = workingColor; - document.getElementById("commandList").removeChild(cmd1); - document.getElementById("commandList").removeChild(cmd2); - document.getElementById("commandList").removeChild(cmd3); - document.getElementById("commandList").removeChild(cmd4); - cmd4 = cmd3; - cmd3 = cmd2; - cmd2 = cmd1; - cmd1 = commandNode; - document.getElementById("commandList").appendChild(cmd4); - document.getElementById("commandList").appendChild(cmd3); - document.getElementById("commandList").appendChild(cmd2); - document.getElementById("commandList").appendChild(cmd1); -} - -function commandComplete(result) { - if (result.failed) { - if (postResult == "CONTINUATION") { - testLoop.aborted = true; - } - postResult = result.failureMessage; - commandNode.title = result.failureMessage; - commandNode.style.backgroundColor = failColor; - } else if (result.passed) { - postResult = "OK"; - commandNode.style.backgroundColor = passColor; - } else { - if (result.result == null) { - postResult = "OK"; - } else { - postResult = "OK," + result.result; - } - commandNode.style.backgroundColor = doneColor; - } -} - -function commandError(message) { - postResult = "ERROR: " + message; - commandNode.style.backgroundColor = errorColor; - commandNode.title = message; -} - -function slowClicked() { - slowMode = !slowMode; -} - -function delay(millis) { - startMillis = new Date(); - while (true) { - milli = new Date(); - if (milli-startMillis > millis) { - break; - } - } -} - -function getIframeDocument(iframe) { - if (iframe.contentDocument) { - return iframe.contentDocument; - } - else { - return iframe.contentWindow.document; - } -} - -// Parses a URI query string into a SeleniumCommand object -function createCommandFromRequest(commandRequest) { - //decodeURIComponent doesn't strip plus signs - var processed = commandRequest.replace(/\+/g, "%20"); - // strip trailing spaces - var processed = processed.replace(/\s+$/, ""); - var vars = processed.split("&"); - var cmdArgs = new Object(); - for (var i=0;i<vars.length;i++) { - var pair = vars[i].split("="); - cmdArgs[pair[0]] = pair[1]; - } - var cmd = cmdArgs['cmd']; - var arg1 = cmdArgs['1']; - if (null == arg1) arg1 = ""; - arg1 = decodeURIComponent(arg1); - var arg2 = cmdArgs['2']; - if (null == arg2) arg2 = ""; - arg2 = decodeURIComponent(arg2); - if (cmd == null) { - throw new Error("Bad command request: " + commandRequest); - } - return new SeleniumCommand(cmd, arg1, arg2); -} - diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-testrunner.js b/tests/FunctionalTests/selenium/core/scripts/selenium-testrunner.js deleted file mode 100755 index 1ced0a11..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-testrunner.js +++ /dev/null @@ -1,748 +0,0 @@ -/* -* 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. -* -*/ - -// The current row in the list of tests (test suite) -currentRowInSuite = 0; - -// An object representing the current test -currentTest = null; - -// 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; - -// Colors used to provide feedback -passColor = "#ccffcc"; -doneColor = "#eeffee"; -failColor = "#ffcccc"; -workingColor = "#ffffcc"; - -// 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; - -queryString = null; - -function setRunInterval() { - // Get the value of the checked runMode option. - // There should be a way of getting the value of the "group", but I don't know how. - var runModeOptions = document.forms['controlPanel'].runMode; - for (var i = 0; i < runModeOptions.length; i++) { - if (runModeOptions[i].checked) { - runInterval = runModeOptions[i].value; - break; - } - } -} - -function continueCurrentTest() { - document.getElementById('continueTest').disabled = true; - testLoop.resume(); -} - -function getApplicationFrame() { - return document.getElementById('myiframe'); -} - -function getSuiteFrame() { - return document.getElementById('testSuiteFrame'); -} - -function getTestFrame(){ - return document.getElementById('testFrame'); -} - -function loadAndRunIfAuto() { - loadSuiteFrame(); -} - -function start() { - queryString = null; - setRunInterval(); - loadSuiteFrame(); -} - -function loadSuiteFrame() { - var testAppFrame = document.getElementById('myiframe'); - selenium = Selenium.createForFrame(testAppFrame); - registerCommandHandlers(); - - //set the runInterval if there is a queryParameter for it - var tempRunInterval = getQueryParameter("runInterval"); - if (tempRunInterval) { - runInterval = tempRunInterval; - } - - document.getElementById("modeRun").onclick = setRunInterval; - document.getElementById('modeWalk').onclick = setRunInterval; - document.getElementById('modeStep').onclick = setRunInterval; - document.getElementById('continueTest').onclick = continueCurrentTest; - - var testSuiteName = getQueryParameter("test"); - - if (testSuiteName) { - addLoadListener(getSuiteFrame(), onloadTestSuite); - getSuiteFrame().src = testSuiteName; - } else { - onloadTestSuite(); - } -} - -function startSingleTest() { - removeLoadListener(getApplicationFrame(), startSingleTest); - var singleTestName = getQueryParameter("singletest"); - addLoadListener(getTestFrame(), startTest); - getTestFrame().src = singleTestName; -} - -function getIframeDocument(iframe) -{ - if (iframe.contentDocument) { - return iframe.contentDocument; - } - else { - return iframe.contentWindow.document; - } -} - -function onloadTestSuite() { - removeLoadListener(getSuiteFrame(), onloadTestSuite); - - // Add an onclick function to each link in all suite tables - var allTables = getIframeDocument(getSuiteFrame()).getElementsByTagName("table"); - for (var tableNum = 0; tableNum < allTables.length; tableNum++) - { - var skippedTable = allTables[tableNum]; - for(rowNum = 1;rowNum < skippedTable.rows.length; rowNum++) { - addOnclick(skippedTable, rowNum); - } - } - - suiteTable = getIframeDocument(getSuiteFrame()).getElementsByTagName("table")[0]; - if (suiteTable!=null) { - - if (isAutomatedRun()) { - startTestSuite(); - } else if (getQueryParameter("autoURL")) { - - addLoadListener(getApplicationFrame(), startSingleTest); - - getApplicationFrame().src = getQueryParameter("autoURL"); - - } else { - testLink = suiteTable.rows[currentRowInSuite+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 (the event source is not consistently reported by browsers) - row = srcObj.parentNode.parentNode.rowIndex || srcObj.parentNode.parentNode.parentNode.rowIndex; - - // If the row has a stored results table, use that - if(suiteTable.rows[row].cells[1]) { - var bodyElement = getIframeDocument(getTestFrame()).body; - - // Create a div element to hold the results table. - var tableNode = getIframeDocument(getTestFrame()).createElement("div"); - var resultsCell = suiteTable.rows[row].cells[1]; - tableNode.innerHTML = resultsCell.innerHTML; - - // Append this text node, and remove all the preceding nodes. - bodyElement.appendChild(tableNode); - while (bodyElement.firstChild != bodyElement.lastChild) { - bodyElement.removeChild(bodyElement.firstChild); - } - } - // Otherwise, just open up the fresh page. - else { - getTestFrame().src = suiteTable.rows[row].cells[0].getElementsByTagName("a")[0].href; - } - - return false; - }; -} - -function isQueryParameterTrue(name) { - parameterValue = getQueryParameter(name); - return (parameterValue != null && parameterValue.toLowerCase() == "true"); -} - -function getQueryString() { - if (queryString != null) return queryString; - if (browserVersion.isHTA) { - var args = extractArgs(); - if (args.length < 2) return null; - queryString = args[1]; - return queryString; - } else { - return location.search.substr(1); - } -} - -function extractArgs() { - var str = SeleniumHTARunner.commandLine; - if (str == null || str == "") return new Array(); - var matches = str.match(/(?:"([^"]+)"|(?!"([^"]+)")(\S+))/g); - // We either want non quote stuff ([^"]+) surrounded by quotes - // or we want to look-ahead, see that the next character isn't - // a quoted argument, and then grab all the non-space stuff - // this will return for the line: "foo" bar - // the results "\"foo\"" and "bar" - - // So, let's unquote the quoted arguments: - var args = new Array; - for (var i = 0; i < matches.length; i++) { - args[i] = matches[i]; - args[i] = args[i].replace(/^"(.*)"$/, "$1"); - } - return args; -} - -function getQueryParameter(searchKey) { - var str = getQueryString(); - if (str == null) return null; - var clauses = str.split('&'); - for (var i = 0; i < clauses.length; i++) { - var keyValuePair = clauses[i].split('=',2); - var key = unescape(keyValuePair[0]); - if (key == searchKey) { - return unescape(keyValuePair[1]); - } - } - return null; -} - -function isNewWindow() { - return isQueryParameterTrue("newWindow"); -} - -function isAutomatedRun() { - return isQueryParameterTrue("auto"); -} - -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); - - // Scroll to the top of the test frame - if (getTestFrame().contentWindow) { - getTestFrame().contentWindow.scrollTo(0,0); - } - else { - frames['testFrame'].scrollTo(0,0); - } - - currentTest = new HtmlTest(getIframeDocument(getTestFrame())); - - testFailed = false; - storedVars = new Object(); - - testLoop = initialiseTestLoop(); - testLoop.start(); -} - -function HtmlTest(testDocument) { - this.init(testDocument); -} - -HtmlTest.prototype = { - - init: function(testDocument) { - this.document = testDocument; - this.document.bgColor = ""; - this.currentRow = null; - this.commandRows = new Array(); - this.headerRow = null; - var tables = this.document.getElementsByTagName("table"); - for (var i = 0; i < tables.length; i++) { - var candidateRows = tables[i].rows; - for (var j = 0; j < candidateRows.length; j++) { - if (!this.headerRow) { - this.headerRow = candidateRows[j]; - } - if (candidateRows[j].cells.length >= 3) { - this.addCommandRow(candidateRows[j]); - } - } - } - }, - - addCommandRow: function(row) { - if (row.cells[2] && row.cells[2].originalHTML) { - row.cells[2].innerHTML = row.cells[2].originalHTML; - } - row.bgColor = ""; - this.commandRows.push(row); - }, - - nextCommand: function() { - if (this.commandRows.length > 0) { - this.currentRow = this.commandRows.shift(); - } else { - this.currentRow = null; - } - return this.currentRow; - } - -}; - -function startTestSuite() { - resetMetrics(); - currentRowInSuite = 0; - runAllTests = true; - suiteFailed = false; - - runNextTest(); -} - -function runNextTest() { - if (!runAllTests) - return; - - suiteTable = getIframeDocument(getSuiteFrame()).getElementsByTagName("table")[0]; - - // Do not change the row color of the first row - if (currentRowInSuite > 0) { - // Provide test-status feedback - if (testFailed) { - setCellColor(suiteTable.rows, currentRowInSuite, 0, failColor); - } else { - setCellColor(suiteTable.rows, currentRowInSuite, 0, passColor); - } - - // Set the results from the previous test run - setResultsData(suiteTable, currentRowInSuite); - } - - currentRowInSuite++; - - // If we are done with all of the tests, set the title bar as pass or fail - if (currentRowInSuite >= 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, currentRowInSuite, 0, workingColor); - - testLink = suiteTable.rows[currentRowInSuite].cells[0].getElementsByTagName("a")[0]; - testLink.focus(); - - var testFrame = getTestFrame(); - addLoadListener(testFrame, startTest); - - selenium.browserbot.setIFrameLocation(testFrame, 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 - var resultTable = getIframeDocument(getTestFrame()).body.innerHTML; - if (!resultTable) return; - - var tableNode = suiteTable.ownerDocument.createElement("div"); - tableNode.innerHTML = resultTable; - - var new_column = suiteTable.ownerDocument.createElement("td"); - new_column.appendChild(tableNode); - - // Set the column to be invisible - new_column.style.display = "none"; - - // Add the invisible column - suiteTable.rows[row].appendChild(new_column); -} - -// Post the results to a servlet, CGI-script, etc. The URL of the -// results-handler defaults to "/postResults", but an alternative location -// can be specified by providing a "resultsUrl" query parameter. -// -// Parameters passed to the results-handler 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"); - document.body.appendChild(form); - - form.id = "resultsForm"; - form.method="post"; - form.target="myiframe"; - - var resultsUrl = getQueryParameter("resultsUrl"); - if (!resultsUrl) { - resultsUrl = "./postResults"; - } - - var actionAndParameters = resultsUrl.split('?',2); - form.action = actionAndParameters[0]; - var resultsUrlQueryString = actionAndParameters[1]; - - form.createHiddenField = function(name, value) { - input = document.createElement("input"); - input.type = "hidden"; - input.name = name; - input.value = value; - this.appendChild(input); - }; - - if (resultsUrlQueryString) { - var clauses = resultsUrlQueryString.split('&'); - for (var i = 0; i < clauses.length; i++) { - var keyValuePair = clauses[i].split('=',2); - var key = unescape(keyValuePair[0]); - var value = unescape(keyValuePair[1]); - form.createHiddenField(key, value); - } - } - - form.createHiddenField("selenium.version", Selenium.version); - form.createHiddenField("selenium.revision", Selenium.revision); - - form.createHiddenField("result", suiteFailed == true ? "failed" : "passed"); - - form.createHiddenField("totalTime", Math.floor((currentTime - startTime) / 1000)); - form.createHiddenField("numTestPasses", numTestPasses); - form.createHiddenField("numTestFailures", numTestFailures); - form.createHiddenField("numCommandPasses", numCommandPasses); - form.createHiddenField("numCommandFailures", numCommandFailures); - form.createHiddenField("numCommandErrors", numCommandErrors); - - // 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) { - var resultCell = suiteTable.rows[rowNum].cells[1]; - form.createHiddenField("testTable." + rowNum, resultCell.innerHTML); - // remove the resultCell, so it's not included in the suite HTML - resultCell.parentNode.removeChild(resultCell); - } - } - - form.createHiddenField("numTestTotal", rowNum); - - // Add HTML for the suite itself - form.createHiddenField("suite", suiteTable.parentNode.innerHTML); - - if (isQueryParameterTrue("save")) { - saveToFile(resultsUrl, form); - } else { - form.submit(); - } - document.body.removeChild(form); - if (isQueryParameterTrue("close")) { - window.top.close(); - } -} - -function saveToFile(fileName, form) { - // This only works when run as an IE HTA - var inputs = new Object(); - for (var i = 0; i < form.elements.length; i++) { - inputs[form.elements[i].name] = form.elements[i].value; - } - var objFSO = new ActiveXObject("Scripting.FileSystemObject") - var scriptFile = objFSO.CreateTextFile(fileName); - scriptFile.WriteLine("<html><body>\n<h1>Test suite results </h1>" + - "\n\n<table>\n<tr>\n<td>result:</td>\n<td>" + inputs["result"] + "</td>\n" + - "</tr>\n<tr>\n<td>totalTime:</td>\n<td>" + inputs["totalTime"] + "</td>\n</tr>\n" + - "<tr>\n<td>numTestPasses:</td>\n<td>" + inputs["numTestPasses"] + "</td>\n</tr>\n" + - "<tr>\n<td>numTestFailures:</td>\n<td>" + inputs["numTestFailures"] + "</td>\n</tr>\n" + - "<tr>\n<td>numCommandPasses:</td>\n<td>" + inputs["numCommandPasses"] + "</td>\n</tr>\n" + - "<tr>\n<td>numCommandFailures:</td>\n<td>" + inputs["numCommandFailures"] + "</td>\n</tr>\n" + - "<tr>\n<td>numCommandErrors:</td>\n<td>" + inputs["numCommandErrors"] + "</td>\n</tr>\n" + - "<tr>\n<td>" + inputs["suite"] + "</td>\n<td> </td>\n</tr>"); - var testNum = inputs["numTestTotal"]; - for (var rowNum = 1; rowNum < testNum; rowNum++) { - scriptFile.WriteLine("<tr>\n<td>" + inputs["testTable." + rowNum] + "</td>\n<td> </td>\n</tr>"); - } - scriptFile.WriteLine("</table></body></html>"); - scriptFile.Close(); -} - -function printMetrics() { - setText(document.getElementById("commandPasses"), numCommandPasses); - setText(document.getElementById("commandFailures"), numCommandFailures); - setText(document.getElementById("commandErrors"), numCommandErrors); - setText(document.getElementById("testRuns"), numTestPasses + numTestFailures); - 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; -} - -/* - * 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); - -} - -function initialiseTestLoop() { - testLoop = new TestLoop(commandFactory); - - testLoop.getCommandInterval = function() { return runInterval; }; - testLoop.nextCommand = nextCommand; - testLoop.commandStarted = commandStarted; - testLoop.commandComplete = commandComplete; - testLoop.commandError = commandError; - testLoop.testComplete = testComplete; - testLoop.pause = function() { - document.getElementById('continueTest').disabled = false; - }; - return testLoop; -} - -function nextCommand() { - var row = currentTest.nextCommand(); - if (row == null) { - return null; - } - row.cells[2].originalHTML = row.cells[2].innerHTML; - return new SeleniumCommand(getText(row.cells[0]), - getText(row.cells[1]), - getText(row.cells[2])); -} - -function removeNbsp(value) { - return value.replace(/\240/g, ""); -} - -function scrollIntoView(element) { - if (element.scrollIntoView) { - element.scrollIntoView(false); - return; - } - // TODO: work out how to scroll browsers that don't support - // scrollIntoView (like Konqueror) -} - -function commandStarted() { - currentTest.currentRow.bgColor = workingColor; - scrollIntoView(currentTest.currentRow.cells[0]); - printMetrics(); -} - -function commandComplete(result) { - if (result.failed) { - numCommandFailures += 1; - recordFailure(result.failureMessage); - } else if (result.passed) { - numCommandPasses += 1; - currentTest.currentRow.bgColor = passColor; - } else { - currentTest.currentRow.bgColor = doneColor; - } -} - -function commandError(errorMessage) { - numCommandErrors += 1; - recordFailure(errorMessage); -} - -function recordFailure(errorMsg) { - LOG.warn("recordFailure: " + errorMsg); - // Set cell background to red - currentTest.currentRow.bgColor = failColor; - - // Set error message - currentTest.currentRow.cells[2].innerHTML = errorMsg; - currentTest.currentRow.title = errorMsg; - testFailed = true; - suiteFailed = true; -} - -function testComplete() { - var resultColor = passColor; - if (testFailed) { - resultColor = failColor; - numTestFailures += 1; - } else { - numTestPasses += 1; - } - - if (currentTest.headerRow) { - currentTest.headerRow.bgColor = resultColor; - } - - printMetrics(); - - window.setTimeout("runNextTest()", 1); -} - -Selenium.prototype.doPause = function(waitTime) { - testLoop.pauseInterval = waitTime; -}; - -Selenium.prototype.doPause.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.doBreak = function() { - document.getElementById('modeStep').checked = true; - runInterval = -1; -}; - -/* - * 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); -}; - -/* - * 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; -}; - -Selenium.prototype.doEcho = function(msg) { - currentTest.currentRow.cells[2].innerHTML = msg; -} diff --git a/tests/FunctionalTests/selenium/core/scripts/selenium-version.js b/tests/FunctionalTests/selenium/core/scripts/selenium-version.js deleted file mode 100755 index 1fee837b..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/selenium-version.js +++ /dev/null @@ -1,5 +0,0 @@ -Selenium.version = "@VERSION@"; -Selenium.revision = "@REVISION@"; - -window.top.document.title += " v" + Selenium.version + " [" + Selenium.revision + "]"; - diff --git a/tests/FunctionalTests/selenium/core/scripts/user-extensions.js.sample b/tests/FunctionalTests/selenium/core/scripts/user-extensions.js.sample deleted file mode 100755 index 0f0ca840..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/user-extensions.js.sample +++ /dev/null @@ -1,75 +0,0 @@ -/* - * By default, Selenium looks for a file called "user-extensions.js", and loads and javascript - * code found in that file. This file is a sample of what that file could look like. - * - * user-extensions.js provides a convenient location for adding extensions to Selenium, like - * new actions, checks and locator-strategies. - * By default, this file does not exist. Users can create this file and place their extension code - * in this common location, removing the need to modify the Selenium sources, and hopefully assisting - * with the upgrade process. - * - * You can find contributed extensions at http://wiki.openqa.org/display/SEL/Contributed%20User-Extensions - */ - -// The following examples try to give an indication of how Selenium can be extended with javascript. - -// All do* methods on the Selenium prototype are added as actions. -// Eg add a typeRepeated action to Selenium, which types the text twice into a text box. -// The typeTwiceAndWait command will be available automatically -Selenium.prototype.doTypeRepeated = function(locator, text) { - // All locator-strategies are automatically handled by "findElement" - var element = this.page().findElement(locator); - - // Create the text to type - var valueToType = text + text; - - // Replace the element text with the new text - this.page().replaceText(element, valueToType); -}; - -// All assert* methods on the Selenium prototype are added as checks. -// Eg add a assertValueRepeated check, that makes sure that the element value -// consists of the supplied text repeated. -// The verify version will be available automatically. -Selenium.prototype.assertValueRepeated = function(locator, text) { - // All locator-strategies are automatically handled by "findElement" - var element = this.page().findElement(locator); - - // Create the text to verify - var expectedValue = text + text; - - // Get the actual element value - var actualValue = element.value; - - // Make sure the actual value matches the expected - Assert.matches(expectedValue, actualValue); -}; - -// All get* methods on the Selenium prototype result in -// store, assert, assertNot, verify, verifyNot, waitFor, and waitForNot commands. -// E.g. add a getTextLength method that returns the length of the text -// of a specified element. -// Will result in support for storeTextLength, assertTextLength, etc. -Selenium.prototype.getTextLength = function(locator) { - return this.getText(locator).length; -}; - -// All locateElementBy* methods are added as locator-strategies. -// Eg add a "valuerepeated=" locator, that finds the first element with the supplied value, repeated. -// The "inDocument" is a the document you are searching. -PageBot.prototype.locateElementByValueRepeated = function(text, inDocument) { - // Create the text to search for - var expectedValue = text + text; - - // Loop through all elements, looking for ones that have a value === our expected value - var allElements = inDocument.getElementsByTagName("*"); - for (var i = 0; i < allElements.length; i++) { - var testElement = allElements[i]; - if (testElement.value && testElement.value === expectedValue) { - return testElement; - } - } - return null; -}; - - diff --git a/tests/FunctionalTests/selenium/core/scripts/xmlextras.js b/tests/FunctionalTests/selenium/core/scripts/xmlextras.js deleted file mode 100755 index 267aa058..00000000 --- a/tests/FunctionalTests/selenium/core/scripts/xmlextras.js +++ /dev/null @@ -1,153 +0,0 @@ -// This is a third party JavaScript library from -// http://webfx.eae.net/dhtml/xmlextras/xmlextras.html -// i.e. This has not been written by ThoughtWorks. - -//<script> -////////////////// -// Helper Stuff // -////////////////// - -// used to find the Automation server name -function getDomDocumentPrefix() { - if (getDomDocumentPrefix.prefix) - return getDomDocumentPrefix.prefix; - - var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; - var o; - for (var i = 0; i < prefixes.length; i++) { - try { - // try to create the objects - o = new ActiveXObject(prefixes[i] + ".DomDocument"); - return getDomDocumentPrefix.prefix = prefixes[i]; - } - catch (ex) {}; - } - - throw new Error("Could not find an installed XML parser"); -} - -function getXmlHttpPrefix() { - if (getXmlHttpPrefix.prefix) - return getXmlHttpPrefix.prefix; - - var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; - var o; - for (var i = 0; i < prefixes.length; i++) { - try { - // try to create the objects - o = new ActiveXObject(prefixes[i] + ".XmlHttp"); - return getXmlHttpPrefix.prefix = prefixes[i]; - } - catch (ex) {}; - } - - throw new Error("Could not find an installed XML parser"); -} - -////////////////////////// -// Start the Real stuff // -////////////////////////// - - -// XmlHttp factory -function XmlHttp() {} - -XmlHttp.create = function () { - try { - if (window.XMLHttpRequest) { - var req = new XMLHttpRequest(); - - // some versions of Moz do not support the readyState property - // and the onreadystate event so we patch it! - if (req.readyState == null) { - req.readyState = 1; - req.addEventListener("load", function () { - req.readyState = 4; - if (typeof req.onreadystatechange == "function") - req.onreadystatechange(); - }, false); - } - - return req; - } - if (window.ActiveXObject) { - return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp"); - } - } - catch (ex) {} - // fell through - throw new Error("Your browser does not support XmlHttp objects"); -}; - -// XmlDocument factory -function XmlDocument() {} - -XmlDocument.create = function () { - try { - // DOM2 - if (document.implementation && document.implementation.createDocument) { - var doc = document.implementation.createDocument("", "", null); - - // some versions of Moz do not support the readyState property - // and the onreadystate event so we patch it! - if (doc.readyState == null) { - doc.readyState = 1; - doc.addEventListener("load", function () { - doc.readyState = 4; - if (typeof doc.onreadystatechange == "function") - doc.onreadystatechange(); - }, false); - } - - return doc; - } - if (window.ActiveXObject) - return new ActiveXObject(getDomDocumentPrefix() + ".DomDocument"); - } - catch (ex) {} - throw new Error("Your browser does not support XmlDocument objects"); -}; - -// Create the loadXML method and xml getter for Mozilla -if (window.DOMParser && - window.XMLSerializer && - window.Node && Node.prototype && Node.prototype.__defineGetter__) { - - // XMLDocument did not extend the Document interface in some versions - // of Mozilla. Extend both! - //XMLDocument.prototype.loadXML = - Document.prototype.loadXML = function (s) { - - // parse the string to a new doc - var doc2 = (new DOMParser()).parseFromString(s, "text/xml"); - - // remove all initial children - while (this.hasChildNodes()) - this.removeChild(this.lastChild); - - // insert and import nodes - for (var i = 0; i < doc2.childNodes.length; i++) { - this.appendChild(this.importNode(doc2.childNodes[i], true)); - } - }; - - - /* - * xml getter - * - * This serializes the DOM tree to an XML String - * - * Usage: var sXml = oNode.xml - * - */ - // XMLDocument did not extend the Document interface in some versions - // of Mozilla. Extend both! - /* - XMLDocument.prototype.__defineGetter__("xml", function () { - return (new XMLSerializer()).serializeToString(this); - }); - */ - Document.prototype.__defineGetter__("xml", function () { - return (new XMLSerializer()).serializeToString(this); - }); -}
\ No newline at end of file diff --git a/tests/FunctionalTests/selenium/core/selenium-logo.png b/tests/FunctionalTests/selenium/core/selenium-logo.png Binary files differdeleted file mode 100755 index 1de09290..00000000 --- a/tests/FunctionalTests/selenium/core/selenium-logo.png +++ /dev/null diff --git a/tests/FunctionalTests/selenium/core/selenium.css b/tests/FunctionalTests/selenium/core/selenium.css deleted file mode 100755 index 6e9f3f30..00000000 --- a/tests/FunctionalTests/selenium/core/selenium.css +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2005 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. - */ - -/*---( Layout )---*/ - -body { - margin: 0; - padding: 0; - overflow: auto; -} - -td { - position: static; -} - -tr { - vertical-align: top; -} - -.layout { - width: 100%; - height: 100%; - border-collapse: collapse; -} - -.layout td { - margin: 0; - padding: 0; - border: 0; -} - -iframe { - width: 100%; - height: 100%; - border: 0; - background: white; - overflow: auto; -} - -/*---( Style )---*/ - -body, html { - font-family: Verdana, Arial, sans-serif; -} - -.selenium th, .selenium td { - border: 1px solid #999; -} - -.header { - background: #ccc; - padding: 0; - font-size: 90%; -} - -#controlPanel { - padding: 0.5ex; - background: #eee; - overflow: auto; - font-size: 75%; - text-align: center; -} - -#controlPanel fieldset { - margin: 0.3ex; - padding: 0.3ex; -} - -#controlPanel fieldset legend { - color: black; -} - -#controlPanel button { - margin: 0.5ex; -} - -#controlPanel table { - font-size: 100%; -} - -#controlPanel th, #controlPanel td { - border: 0; -} - -h1 { - margin: 0.2ex; - font-size: 130%; - font-weight: bold; -} - -h2 { - margin: 0.2ex; - font-size: 80%; - font-weight: normal; -} - -.selenium a { - color: black; - text-decoration: none; -} - -.selenium a:hover { - text-decoration: underline; -} - -button, label { - cursor: pointer; -} - -#stats { - margin: 0.5em auto 0.5em auto; -} - -#stats th, #stats td { - text-align: left; - padding-left: 2px; -} - -#stats th { - text-decoration: underline; -} - -#stats td.count { - font-weight: bold; - text-align: right; -} - -#testRuns { - color: green; -} - -#testFailures { - color: red; -} - -#commandPasses { - color: green; -} - -#commandFailures { - color: red; -} - -#commandErrors { - color: #f90; -} - -.splash { - border: 1px solid black; - padding: 20px; - background: #ccc; -} - -/*---( Logging Console )---*/ - -#logging-console { - background: #fff; - font-size: 75%; -} - -#logging-console #banner { - display: block; - width: 100%; - position: fixed; - top: 0; - background: #ddd; - border-bottom: 1px solid #666; -} - -#logging-console #logLevelChooser { - float: right; - margin: 3px; -} - -#logging-console ul { - list-style-type: none; - margin: 0px; - margin-top: 3em; - padding-left: 5px; -} - -#logging-console li { - margin: 2px; - border-top: 1px solid #ccc; -} - -#logging-console li.error { - font-weight: bold; - color: red; -} - -#logging-console li.warn { - color: red; -} - -#logging-console li.debug { - color: green; -} diff --git a/tests/FunctionalTests/selenium/core/xpath/dom.js b/tests/FunctionalTests/selenium/core/xpath/dom.js deleted file mode 100755 index 5e49748c..00000000 --- a/tests/FunctionalTests/selenium/core/xpath/dom.js +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright 2005 Google Inc.
-// All Rights Reserved
-//
-// An XML parse and a minimal DOM implementation that just supportes
-// the subset of the W3C DOM that is used in the XSLT implementation.
-//
-// References:
-//
-// [DOM] W3C DOM Level 3 Core Specification
-// <http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/>.
-//
-//
-// Author: Steffen Meschkat <mesch@google.com>
-
-// NOTE: The split() method in IE omits empty result strings. This is
-// utterly annoying. So we don't use it here.
-
-// Resolve entities in XML text fragments. According to the DOM
-// specification, the DOM is supposed to resolve entity references at
-// the API level. I.e. no entity references are passed through the
-// API. See "Entities and the DOM core", p.12, DOM 2 Core
-// Spec. However, different browsers actually pass very different
-// values at the API.
-//
-function xmlResolveEntities(s) {
-
- var parts = stringSplit(s, '&');
-
- var ret = parts[0];
- for (var i = 1; i < parts.length; ++i) {
- var rp = stringSplit(parts[i], ';');
- if (rp.length == 1) {
- // no entity reference: just a & but no ;
- ret += parts[i];
- continue;
- }
-
- var ch;
- switch (rp[0]) {
- case 'lt':
- ch = '<';
- break;
- case 'gt':
- ch = '>';
- break;
- case 'amp':
- ch = '&';
- break;
- case 'quot':
- ch = '"';
- break;
- case 'apos':
- ch = '\'';
- break;
- case 'nbsp':
- ch = String.fromCharCode(160);
- break;
- default:
- // Cool trick: let the DOM do the entity decoding. We assign
- // the entity text through non-W3C DOM properties and read it
- // through the W3C DOM. W3C DOM access is specified to resolve
- // entities.
- var span = window.document.createElement('span');
- span.innerHTML = '&' + rp[0] + '; ';
- ch = span.childNodes[0].nodeValue.charAt(0);
- }
- ret += ch + rp[1];
- }
-
- return ret;
-}
-
-
-// Parses the given XML string with our custom, JavaScript XML parser. Written
-// by Steffen Meschkat (mesch@google.com).
-function xmlParse(xml) {
- Timer.start('xmlparse');
- var regex_empty = /\/$/;
-
- // See also <http://www.w3.org/TR/REC-xml/#sec-common-syn> for
- // allowed chars in a tag and attribute name. TODO(mesch): the
- // following is still not completely correct.
-
- var regex_tagname = /^([\w:-]*)/;
- var regex_attribute = /([\w:-]+)\s?=\s?('([^\']*)'|"([^\"]*)")/g;
-
- var xmldoc = new XDocument();
- var root = xmldoc;
-
- // For the record: in Safari, we would create native DOM nodes, but
- // in Opera that is not possible, because the DOM only allows HTML
- // element nodes to be created, so we have to do our own DOM nodes.
-
- // xmldoc = document.implementation.createDocument('','',null);
- // root = xmldoc; // .createDocumentFragment();
- // NOTE(mesch): using the DocumentFragment instead of the Document
- // crashes my Safari 1.2.4 (v125.12).
- var stack = [];
-
- var parent = root;
- stack.push(parent);
-
- var x = stringSplit(xml, '<');
- for (var i = 1; i < x.length; ++i) {
- var xx = stringSplit(x[i], '>');
- var tag = xx[0];
- var text = xmlResolveEntities(xx[1] || '');
-
- if (tag.charAt(0) == '/') {
- stack.pop();
- parent = stack[stack.length-1];
-
- } else if (tag.charAt(0) == '?') {
- // Ignore XML declaration and processing instructions
- } else if (tag.charAt(0) == '!') {
- // Ignore notation and comments
- } else {
- var empty = tag.match(regex_empty);
- var tagname = regex_tagname.exec(tag)[1];
- var node = xmldoc.createElement(tagname);
-
- var att;
- while (att = regex_attribute.exec(tag)) {
- var val = xmlResolveEntities(att[3] || att[4] || '');
- node.setAttribute(att[1], val);
- }
-
- if (empty) {
- parent.appendChild(node);
- } else {
- parent.appendChild(node);
- parent = node;
- stack.push(node);
- }
- }
-
- if (text && parent != root) {
- parent.appendChild(xmldoc.createTextNode(text));
- }
- }
-
- Timer.end('xmlparse');
- return root;
-}
-
-
-// Our W3C DOM Node implementation. Note we call it XNode because we
-// can't define the identifier Node. We do this mostly for Opera,
-// where we can't reuse the HTML DOM for parsing our own XML, and for
-// Safari, where it is too expensive to have the template processor
-// operate on native DOM nodes.
-function XNode(type, name, value, owner) {
- this.attributes = [];
- this.childNodes = [];
-
- XNode.init.call(this, type, name, value, owner);
-}
-
-// Don't call as method, use apply() or call().
-XNode.init = function(type, name, value, owner) {
- this.nodeType = type - 0;
- this.nodeName = '' + name;
- this.nodeValue = '' + value;
- this.ownerDocument = owner;
-
- this.firstChild = null;
- this.lastChild = null;
- this.nextSibling = null;
- this.previousSibling = null;
- this.parentNode = null;
-}
-
-XNode.unused_ = [];
-
-XNode.recycle = function(node) {
- if (!node) {
- return;
- }
-
- if (node.constructor == XDocument) {
- XNode.recycle(node.documentElement);
- return;
- }
-
- if (node.constructor != this) {
- return;
- }
-
- XNode.unused_.push(node);
- for (var a = 0; a < node.attributes.length; ++a) {
- XNode.recycle(node.attributes[a]);
- }
- for (var c = 0; c < node.childNodes.length; ++c) {
- XNode.recycle(node.childNodes[c]);
- }
- node.attributes.length = 0;
- node.childNodes.length = 0;
- XNode.init.call(node, 0, '', '', null);
-}
-
-XNode.create = function(type, name, value, owner) {
- if (XNode.unused_.length > 0) {
- var node = XNode.unused_.pop();
- XNode.init.call(node, type, name, value, owner);
- return node;
- } else {
- return new XNode(type, name, value, owner);
- }
-}
-
-XNode.prototype.appendChild = function(node) {
- // firstChild
- if (this.childNodes.length == 0) {
- this.firstChild = node;
- }
-
- // previousSibling
- node.previousSibling = this.lastChild;
-
- // nextSibling
- node.nextSibling = null;
- if (this.lastChild) {
- this.lastChild.nextSibling = node;
- }
-
- // parentNode
- node.parentNode = this;
-
- // lastChild
- this.lastChild = node;
-
- // childNodes
- this.childNodes.push(node);
-}
-
-
-XNode.prototype.replaceChild = function(newNode, oldNode) {
- if (oldNode == newNode) {
- return;
- }
-
- for (var i = 0; i < this.childNodes.length; ++i) {
- if (this.childNodes[i] == oldNode) {
- this.childNodes[i] = newNode;
-
- var p = oldNode.parentNode;
- oldNode.parentNode = null;
- newNode.parentNode = p;
-
- p = oldNode.previousSibling;
- oldNode.previousSibling = null;
- newNode.previousSibling = p;
- if (newNode.previousSibling) {
- newNode.previousSibling.nextSibling = newNode;
- }
-
- p = oldNode.nextSibling;
- oldNode.nextSibling = null;
- newNode.nextSibling = p;
- if (newNode.nextSibling) {
- newNode.nextSibling.previousSibling = newNode;
- }
-
- if (this.firstChild == oldNode) {
- this.firstChild = newNode;
- }
-
- if (this.lastChild == oldNode) {
- this.lastChild = newNode;
- }
-
- break;
- }
- }
-}
-
-XNode.prototype.insertBefore = function(newNode, oldNode) {
- if (oldNode == newNode) {
- return;
- }
-
- if (oldNode.parentNode != this) {
- return;
- }
-
- if (newNode.parentNode) {
- newNode.parentNode.removeChild(newNode);
- }
-
- var newChildren = [];
- for (var i = 0; i < this.childNodes.length; ++i) {
- var c = this.childNodes[i];
- if (c == oldNode) {
- newChildren.push(newNode);
-
- newNode.parentNode = this;
-
- newNode.previousSibling = oldNode.previousSibling;
- oldNode.previousSibling = newNode;
- if (newNode.previousSibling) {
- newNode.previousSibling.nextSibling = newNode;
- }
-
- newNode.nextSibling = oldNode;
-
- if (this.firstChild == oldNode) {
- this.firstChild = newNode;
- }
- }
- newChildren.push(c);
- }
- this.childNodes = newChildren;
-}
-
-XNode.prototype.removeChild = function(node) {
- var newChildren = [];
- for (var i = 0; i < this.childNodes.length; ++i) {
- var c = this.childNodes[i];
- if (c != node) {
- newChildren.push(c);
- } else {
- if (c.previousSibling) {
- c.previousSibling.nextSibling = c.nextSibling;
- }
- if (c.nextSibling) {
- c.nextSibling.previousSibling = c.previousSibling;
- }
- if (this.firstChild == c) {
- this.firstChild = c.nextSibling;
- }
- if (this.lastChild == c) {
- this.lastChild = c.previousSibling;
- }
- }
- }
- this.childNodes = newChildren;
-}
-
-
-XNode.prototype.hasAttributes = function() {
- return this.attributes.length > 0;
-}
-
-
-XNode.prototype.setAttribute = function(name, value) {
- for (var i = 0; i < this.attributes.length; ++i) {
- if (this.attributes[i].nodeName == name) {
- this.attributes[i].nodeValue = '' + value;
- return;
- }
- }
- this.attributes.push(new XNode(DOM_ATTRIBUTE_NODE, name, value));
-}
-
-
-XNode.prototype.getAttribute = function(name) {
- for (var i = 0; i < this.attributes.length; ++i) {
- if (this.attributes[i].nodeName == name) {
- return this.attributes[i].nodeValue;
- }
- }
- return null;
-}
-
-XNode.prototype.removeAttribute = function(name) {
- var a = [];
- for (var i = 0; i < this.attributes.length; ++i) {
- if (this.attributes[i].nodeName != name) {
- a.push(this.attributes[i]);
- }
- }
- this.attributes = a;
-}
-
-
-function XDocument() {
- XNode.call(this, DOM_DOCUMENT_NODE, '#document', null, this);
- this.documentElement = null;
-}
-
-XDocument.prototype = new XNode(DOM_DOCUMENT_NODE, '#document');
-
-XDocument.prototype.clear = function() {
- XNode.recycle(this.documentElement);
- this.documentElement = null;
-}
-
-XDocument.prototype.appendChild = function(node) {
- XNode.prototype.appendChild.call(this, node);
- this.documentElement = this.childNodes[0];
-}
-
-XDocument.prototype.createElement = function(name) {
- return XNode.create(DOM_ELEMENT_NODE, name, null, this);
-}
-
-XDocument.prototype.createDocumentFragment = function() {
- return XNode.create(DOM_DOCUMENT_FRAGMENT_NODE, '#document-fragment',
- null, this);
-}
-
-XDocument.prototype.createTextNode = function(value) {
- return XNode.create(DOM_TEXT_NODE, '#text', value, this);
-}
-
-XDocument.prototype.createAttribute = function(name) {
- return XNode.create(DOM_ATTRIBUTE_NODE, name, null, this);
-}
-
-XDocument.prototype.createComment = function(data) {
- return XNode.create(DOM_COMMENT_NODE, '#comment', data, this);
-}
-
-XNode.prototype.getElementsByTagName = function(name, list) {
- if (!list) {
- list = [];
- }
-
- if (this.nodeName == name) {
- list.push(this);
- }
-
- for (var i = 0; i < this.childNodes.length; ++i) {
- this.childNodes[i].getElementsByTagName(name, list);
- }
-
- return list;
-}
diff --git a/tests/FunctionalTests/selenium/core/xpath/misc.js b/tests/FunctionalTests/selenium/core/xpath/misc.js deleted file mode 100755 index 9017542e..00000000 --- a/tests/FunctionalTests/selenium/core/xpath/misc.js +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2005 Google Inc.
-// All Rights Reserved
-//
-// Miscellania that support the ajaxslt implementation.
-//
-// Author: Steffen Meschkat <mesch@google.com>
-//
-
-function el(i) {
- return document.getElementById(i);
-}
-
-function px(x) {
- return x + 'px';
-}
-
-// Split a string s at all occurrences of character c. This is like
-// the split() method of the string object, but IE omits empty
-// strings, which violates the invariant (s.split(x).join(x) == s).
-function stringSplit(s, c) {
- var a = s.indexOf(c);
- if (a == -1) {
- return [ s ];
- }
-
- var parts = [];
- parts.push(s.substr(0,a));
- while (a != -1) {
- var a1 = s.indexOf(c, a + 1);
- if (a1 != -1) {
- parts.push(s.substr(a + 1, a1 - a - 1));
- } else {
- parts.push(s.substr(a + 1));
- }
- a = a1;
- }
-
- return parts;
-}
-
-// Returns the text value if a node; for nodes without children this
-// is the nodeValue, for nodes with children this is the concatenation
-// of the value of all children.
-function xmlValue(node) {
- if (!node) {
- return '';
- }
-
- var ret = '';
- if (node.nodeType == DOM_TEXT_NODE ||
- node.nodeType == DOM_CDATA_SECTION_NODE ||
- node.nodeType == DOM_ATTRIBUTE_NODE) {
- ret += node.nodeValue;
-
- } else if (node.nodeType == DOM_ELEMENT_NODE ||
- node.nodeType == DOM_DOCUMENT_NODE ||
- node.nodeType == DOM_DOCUMENT_FRAGMENT_NODE) {
- for (var i = 0; i < node.childNodes.length; ++i) {
- ret += arguments.callee(node.childNodes[i]);
- }
- }
- return ret;
-}
-
-// Returns the representation of a node as XML text.
-function xmlText(node) {
- var ret = '';
- if (node.nodeType == DOM_TEXT_NODE) {
- ret += xmlEscapeText(node.nodeValue);
-
- } else if (node.nodeType == DOM_ELEMENT_NODE) {
- ret += '<' + node.nodeName;
- for (var i = 0; i < node.attributes.length; ++i) {
- var a = node.attributes[i];
- if (a && a.nodeName && a.nodeValue) {
- ret += ' ' + a.nodeName;
- ret += '="' + xmlEscapeAttr(a.nodeValue) + '"';
- }
- }
-
- if (node.childNodes.length == 0) {
- ret += '/>';
-
- } else {
- ret += '>';
- for (var i = 0; i < node.childNodes.length; ++i) {
- ret += arguments.callee(node.childNodes[i]);
- }
- ret += '</' + node.nodeName + '>';
- }
-
- } else if (node.nodeType == DOM_DOCUMENT_NODE ||
- node.nodeType == DOM_DOCUMENT_FRAGMENT_NODE) {
- for (var i = 0; i < node.childNodes.length; ++i) {
- ret += arguments.callee(node.childNodes[i]);
- }
- }
-
- return ret;
-}
-
-// Applies the given function to each element of the array.
-function mapExec(array, func) {
- for (var i = 0; i < array.length; ++i) {
- func(array[i]);
- }
-}
-
-// Returns an array that contains the return value of the given
-// function applied to every element of the input array.
-function mapExpr(array, func) {
- var ret = [];
- for (var i = 0; i < array.length; ++i) {
- ret.push(func(array[i]));
- }
- return ret;
-};
-
-// Reverses the given array in place.
-function reverseInplace(array) {
- for (var i = 0; i < array.length / 2; ++i) {
- var h = array[i];
- var ii = array.length - i - 1;
- array[i] = array[ii];
- array[ii] = h;
- }
-}
-
-// Shallow-copies an array.
-function copyArray(dst, src) {
- for (var i = 0; i < src.length; ++i) {
- dst.push(src[i]);
- }
-}
-
-function assert(b) {
- if (!b) {
- throw 'assertion failed';
- }
-}
-
-// Based on
-// <http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247>
-var DOM_ELEMENT_NODE = 1;
-var DOM_ATTRIBUTE_NODE = 2;
-var DOM_TEXT_NODE = 3;
-var DOM_CDATA_SECTION_NODE = 4;
-var DOM_ENTITY_REFERENCE_NODE = 5;
-var DOM_ENTITY_NODE = 6;
-var DOM_PROCESSING_INSTRUCTION_NODE = 7;
-var DOM_COMMENT_NODE = 8;
-var DOM_DOCUMENT_NODE = 9;
-var DOM_DOCUMENT_TYPE_NODE = 10;
-var DOM_DOCUMENT_FRAGMENT_NODE = 11;
-var DOM_NOTATION_NODE = 12;
-
-
-var xpathdebug = false; // trace xpath parsing
-var xsltdebug = false; // trace xslt processing
-
-
-// Escape XML special markup chracters: tag delimiter < > and entity
-// reference start delimiter &. The escaped string can be used in XML
-// text portions (i.e. between tags).
-function xmlEscapeText(s) {
- return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
-}
-
-// Escape XML special markup characters: tag delimiter < > entity
-// reference start delimiter & and quotes ". The escaped string can be
-// used in double quoted XML attribute value portions (i.e. in
-// attributes within start tags).
-function xmlEscapeAttr(s) {
- return xmlEscapeText(s).replace(/\"/g, '"');
-}
-
-// Escape markup in XML text, but don't touch entity references. The
-// escaped string can be used as XML text (i.e. between tags).
-function xmlEscapeTags(s) {
- return s.replace(/</g, '<').replace(/>/g, '>');
-}
-
-// An implementation of the debug log.
-
-var logging__ = false;
-
-function Log() {};
-
-Log.lines = [];
-
-Log.write = function(s) {
- if (logging__) {
- this.lines.push(xmlEscapeText(s));
- this.show();
- }
-};
-
-// Writes the given XML with every tag on a new line.
-Log.writeXML = function(xml) {
- if (logging__) {
- var s0 = xml.replace(/</g, '\n<');
- var s1 = xmlEscapeText(s0);
- var s2 = s1.replace(/\s*\n(\s|\n)*/g, '<br/>');
- this.lines.push(s2);
- this.show();
- }
-}
-
-// Writes without any escaping
-Log.writeRaw = function(s) {
- if (logging__) {
- this.lines.push(s);
- this.show();
- }
-}
-
-Log.clear = function() {
- if (logging__) {
- var l = this.div();
- l.innerHTML = '';
- this.lines = [];
- }
-}
-
-Log.show = function() {
- var l = this.div();
- l.innerHTML += this.lines.join('<br/>') + '<br/>';
- this.lines = [];
- l.scrollTop = l.scrollHeight;
-}
-
-Log.div = function() {
- var l = document.getElementById('log');
- if (!l) {
- l = document.createElement('div');
- l.id = 'log';
- l.style.position = 'absolute';
- l.style.right = '5px';
- l.style.top = '5px';
- l.style.width = '250px';
- l.style.height = '150px';
- l.style.overflow = 'auto';
- l.style.backgroundColor = '#f0f0f0';
- l.style.border = '1px solid gray';
- l.style.fontSize = '10px';
- l.style.padding = '5px';
- document.body.appendChild(l);
- }
- return l;
-}
-
-
-function Timer() {}
-Timer.start = function() {}
-Timer.end = function() {}
diff --git a/tests/FunctionalTests/selenium/core/xpath/xpath.js b/tests/FunctionalTests/selenium/core/xpath/xpath.js deleted file mode 100755 index ce784585..00000000 --- a/tests/FunctionalTests/selenium/core/xpath/xpath.js +++ /dev/null @@ -1,2182 +0,0 @@ -// Copyright 2005 Google Inc.
-// All Rights Reserved
-//
-// An XPath parser and evaluator written in JavaScript. The
-// implementation is complete except for functions handling
-// namespaces.
-//
-// Reference: [XPATH] XPath Specification
-// <http://www.w3.org/TR/1999/REC-xpath-19991116>.
-//
-//
-// The API of the parser has several parts:
-//
-// 1. The parser function xpathParse() that takes a string and returns
-// an expession object.
-//
-// 2. The expression object that has an evaluate() method to evaluate the
-// XPath expression it represents. (It is actually a hierarchy of
-// objects that resembles the parse tree, but an application will call
-// evaluate() only on the top node of this hierarchy.)
-//
-// 3. The context object that is passed as an argument to the evaluate()
-// method, which represents the DOM context in which the expression is
-// evaluated.
-//
-// 4. The value object that is returned from evaluate() and represents
-// values of the different types that are defined by XPath (number,
-// string, boolean, and node-set), and allows to convert between them.
-//
-// These parts are near the top of the file, the functions and data
-// that are used internally follow after them.
-//
-//
-// TODO(mesch): add jsdoc comments. Use more coherent naming.
-//
-//
-// Author: Steffen Meschkat <mesch@google.com>
-
-
-// The entry point for the parser.
-//
-// @param expr a string that contains an XPath expression.
-// @return an expression object that can be evaluated with an
-// expression context.
-
-function xpathParse(expr) {
- if (xpathdebug) {
- Log.write('XPath parse ' + expr);
- }
- xpathParseInit();
-
- var cached = xpathCacheLookup(expr);
- if (cached) {
- if (xpathdebug) {
- Log.write(' ... cached');
- }
- return cached;
- }
-
- // Optimize for a few common cases: simple attribute node tests
- // (@id), simple element node tests (page), variable references
- // ($address), numbers (4), multi-step path expressions where each
- // step is a plain element node test
- // (page/overlay/locations/location).
-
- if (expr.match(/^(\$|@)?\w+$/i)) {
- var ret = makeSimpleExpr(expr);
- xpathParseCache[expr] = ret;
- if (xpathdebug) {
- Log.write(' ... simple');
- }
- return ret;
- }
-
- if (expr.match(/^\w+(\/\w+)*$/i)) {
- var ret = makeSimpleExpr2(expr);
- xpathParseCache[expr] = ret;
- if (xpathdebug) {
- Log.write(' ... simple 2');
- }
- return ret;
- }
-
- var cachekey = expr; // expr is modified during parse
- if (xpathdebug) {
- Timer.start('XPath parse', cachekey);
- }
-
- var stack = [];
- var ahead = null;
- var previous = null;
- var done = false;
-
- var parse_count = 0;
- var lexer_count = 0;
- var reduce_count = 0;
-
- while (!done) {
- parse_count++;
- expr = expr.replace(/^\s*/, '');
- previous = ahead;
- ahead = null;
-
- var rule = null;
- var match = '';
- for (var i = 0; i < xpathTokenRules.length; ++i) {
- var result = xpathTokenRules[i].re.exec(expr);
- lexer_count++;
- if (result && result.length > 0 && result[0].length > match.length) {
- rule = xpathTokenRules[i];
- match = result[0];
- break;
- }
- }
-
- // Special case: allow operator keywords to be element and
- // variable names.
-
- // NOTE(mesch): The parser resolves conflicts by looking ahead,
- // and this is the only case where we look back to
- // disambiguate. So this is indeed something different, and
- // looking back is usually done in the lexer (via states in the
- // general case, called "start conditions" in flex(1)). Also,the
- // conflict resolution in the parser is not as robust as it could
- // be, so I'd like to keep as much off the parser as possible (all
- // these precedence values should be computed from the grammar
- // rules and possibly associativity declarations, as in bison(1),
- // and not explicitly set.
-
- if (rule &&
- (rule == TOK_DIV ||
- rule == TOK_MOD ||
- rule == TOK_AND ||
- rule == TOK_OR) &&
- (!previous ||
- previous.tag == TOK_AT ||
- previous.tag == TOK_DSLASH ||
- previous.tag == TOK_SLASH ||
- previous.tag == TOK_AXIS ||
- previous.tag == TOK_DOLLAR)) {
- rule = TOK_QNAME;
- }
-
- if (rule) {
- expr = expr.substr(match.length);
- if (xpathdebug) {
- Log.write('token: ' + match + ' -- ' + rule.label);
- }
- ahead = {
- tag: rule,
- match: match,
- prec: rule.prec ? rule.prec : 0, // || 0 is removed by the compiler
- expr: makeTokenExpr(match)
- };
-
- } else {
- if (xpathdebug) {
- Log.write('DONE');
- }
- done = true;
- }
-
- while (xpathReduce(stack, ahead)) {
- reduce_count++;
- if (xpathdebug) {
- Log.write('stack: ' + stackToString(stack));
- }
- }
- }
-
- if (xpathdebug) {
- Log.write(stackToString(stack));
- }
-
- if (stack.length != 1) {
- throw 'XPath parse error ' + cachekey + ':\n' + stackToString(stack);
- }
-
- var result = stack[0].expr;
- xpathParseCache[cachekey] = result;
-
- if (xpathdebug) {
- Timer.end('XPath parse', cachekey);
- }
-
- if (xpathdebug) {
- Log.write('XPath parse: ' + parse_count + ' / ' +
- lexer_count + ' / ' + reduce_count);
- }
-
- return result;
-}
-
-var xpathParseCache = {};
-
-function xpathCacheLookup(expr) {
- return xpathParseCache[expr];
-}
-
-function xpathReduce(stack, ahead) {
- var cand = null;
-
- if (stack.length > 0) {
- var top = stack[stack.length-1];
- var ruleset = xpathRules[top.tag.key];
-
- if (ruleset) {
- for (var i = 0; i < ruleset.length; ++i) {
- var rule = ruleset[i];
- var match = xpathMatchStack(stack, rule[1]);
- if (match.length) {
- cand = {
- tag: rule[0],
- rule: rule,
- match: match
- };
- cand.prec = xpathGrammarPrecedence(cand);
- break;
- }
- }
- }
- }
-
- var ret;
- if (cand && (!ahead || cand.prec > ahead.prec ||
- (ahead.tag.left && cand.prec >= ahead.prec))) {
- for (var i = 0; i < cand.match.matchlength; ++i) {
- stack.pop();
- }
-
- if (xpathdebug) {
- Log.write('reduce ' + cand.tag.label + ' ' + cand.prec +
- ' ahead ' + (ahead ? ahead.tag.label + ' ' + ahead.prec +
- (ahead.tag.left ? ' left' : '')
- : ' none '));
- }
-
- var matchexpr = mapExpr(cand.match, function(m) { return m.expr; });
- cand.expr = cand.rule[3].apply(null, matchexpr);
-
- stack.push(cand);
- ret = true;
-
- } else {
- if (ahead) {
- if (xpathdebug) {
- Log.write('shift ' + ahead.tag.label + ' ' + ahead.prec +
- (ahead.tag.left ? ' left' : '') +
- ' over ' + (cand ? cand.tag.label + ' ' +
- cand.prec : ' none'));
- }
- stack.push(ahead);
- }
- ret = false;
- }
- return ret;
-}
-
-function xpathMatchStack(stack, pattern) {
-
- // NOTE(mesch): The stack matches for variable cardinality are
- // greedy but don't do backtracking. This would be an issue only
- // with rules of the form A* A, i.e. with an element with variable
- // cardinality followed by the same element. Since that doesn't
- // occur in the grammar at hand, all matches on the stack are
- // unambiguous.
-
- var S = stack.length;
- var P = pattern.length;
- var p, s;
- var match = [];
- match.matchlength = 0;
- var ds = 0;
- for (p = P - 1, s = S - 1; p >= 0 && s >= 0; --p, s -= ds) {
- ds = 0;
- var qmatch = [];
- if (pattern[p] == Q_MM) {
- p -= 1;
- match.push(qmatch);
- while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
- qmatch.push(stack[s - ds]);
- ds += 1;
- match.matchlength += 1;
- }
-
- } else if (pattern[p] == Q_01) {
- p -= 1;
- match.push(qmatch);
- while (s - ds >= 0 && ds < 2 && stack[s - ds].tag == pattern[p]) {
- qmatch.push(stack[s - ds]);
- ds += 1;
- match.matchlength += 1;
- }
-
- } else if (pattern[p] == Q_1M) {
- p -= 1;
- match.push(qmatch);
- if (stack[s].tag == pattern[p]) {
- while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
- qmatch.push(stack[s - ds]);
- ds += 1;
- match.matchlength += 1;
- }
- } else {
- return [];
- }
-
- } else if (stack[s].tag == pattern[p]) {
- match.push(stack[s]);
- ds += 1;
- match.matchlength += 1;
-
- } else {
- return [];
- }
-
- reverseInplace(qmatch);
- qmatch.expr = mapExpr(qmatch, function(m) { return m.expr; });
- }
-
- reverseInplace(match);
-
- if (p == -1) {
- return match;
-
- } else {
- return [];
- }
-}
-
-function xpathTokenPrecedence(tag) {
- return tag.prec || 2;
-}
-
-function xpathGrammarPrecedence(frame) {
- var ret = 0;
-
- if (frame.rule) { /* normal reduce */
- if (frame.rule.length >= 3 && frame.rule[2] >= 0) {
- ret = frame.rule[2];
-
- } else {
- for (var i = 0; i < frame.rule[1].length; ++i) {
- var p = xpathTokenPrecedence(frame.rule[1][i]);
- ret = Math.max(ret, p);
- }
- }
- } else if (frame.tag) { /* TOKEN match */
- ret = xpathTokenPrecedence(frame.tag);
-
- } else if (frame.length) { /* Q_ match */
- for (var j = 0; j < frame.length; ++j) {
- var p = xpathGrammarPrecedence(frame[j]);
- ret = Math.max(ret, p);
- }
- }
-
- return ret;
-}
-
-function stackToString(stack) {
- var ret = '';
- for (var i = 0; i < stack.length; ++i) {
- if (ret) {
- ret += '\n';
- }
- ret += stack[i].tag.label;
- }
- return ret;
-}
-
-
-// XPath expression evaluation context. An XPath context consists of a
-// DOM node, a list of DOM nodes that contains this node, a number
-// that represents the position of the single node in the list, and a
-// current set of variable bindings. (See XPath spec.)
-//
-// The interface of the expression context:
-//
-// Constructor -- gets the node, its position, the node set it
-// belongs to, and a parent context as arguments. The parent context
-// is used to implement scoping rules for variables: if a variable
-// is not found in the current context, it is looked for in the
-// parent context, recursively. Except for node, all arguments have
-// default values: default position is 0, default node set is the
-// set that contains only the node, and the default parent is null.
-//
-// Notice that position starts at 0 at the outside interface;
-// inside XPath expressions this shows up as position()=1.
-//
-// clone() -- creates a new context with the current context as
-// parent. If passed as argument to clone(), the new context has a
-// different node, position, or node set. What is not passed is
-// inherited from the cloned context.
-//
-// setVariable(name, expr) -- binds given XPath expression to the
-// name.
-//
-// getVariable(name) -- what the name says.
-//
-// setNode(node, position) -- sets the context to the new node and
-// its corresponding position. Needed to implement scoping rules for
-// variables in XPath. (A variable is visible to all subsequent
-// siblings, not only to its children.)
-
-function ExprContext(node, position, nodelist, parent) {
- this.node = node;
- this.position = position || 0;
- this.nodelist = nodelist || [ node ];
- this.variables = {};
- this.parent = parent || null;
- this.root = parent ? parent.root : node.ownerDocument;
-}
-
-ExprContext.prototype.clone = function(node, position, nodelist) {
- return new
- ExprContext(node || this.node,
- typeof position != 'undefined' ? position : this.position,
- nodelist || this.nodelist, this);
-};
-
-ExprContext.prototype.setVariable = function(name, value) {
- this.variables[name] = value;
-};
-
-ExprContext.prototype.getVariable = function(name) {
- if (typeof this.variables[name] != 'undefined') {
- return this.variables[name];
-
- } else if (this.parent) {
- return this.parent.getVariable(name);
-
- } else {
- return null;
- }
-}
-
-ExprContext.prototype.setNode = function(node, position) {
- this.node = node;
- this.position = position;
-}
-
-
-// XPath expression values. They are what XPath expressions evaluate
-// to. Strangely, the different value types are not specified in the
-// XPath syntax, but only in the semantics, so they don't show up as
-// nonterminals in the grammar. Yet, some expressions are required to
-// evaluate to particular types, and not every type can be coerced
-// into every other type. Although the types of XPath values are
-// similar to the types present in JavaScript, the type coercion rules
-// are a bit peculiar, so we explicitly model XPath types instead of
-// mapping them onto JavaScript types. (See XPath spec.)
-//
-// The four types are:
-//
-// StringValue
-//
-// NumberValue
-//
-// BooleanValue
-//
-// NodeSetValue
-//
-// The common interface of the value classes consists of methods that
-// implement the XPath type coercion rules:
-//
-// stringValue() -- returns the value as a JavaScript String,
-//
-// numberValue() -- returns the value as a JavaScript Number,
-//
-// booleanValue() -- returns the value as a JavaScript Boolean,
-//
-// nodeSetValue() -- returns the value as a JavaScript Array of DOM
-// Node objects.
-//
-
-function StringValue(value) {
- this.value = value;
- this.type = 'string';
-}
-
-StringValue.prototype.stringValue = function() {
- return this.value;
-}
-
-StringValue.prototype.booleanValue = function() {
- return this.value.length > 0;
-}
-
-StringValue.prototype.numberValue = function() {
- return this.value - 0;
-}
-
-StringValue.prototype.nodeSetValue = function() {
- throw this + ' ' + Error().stack;
-}
-
-function BooleanValue(value) {
- this.value = value;
- this.type = 'boolean';
-}
-
-BooleanValue.prototype.stringValue = function() {
- return '' + this.value;
-}
-
-BooleanValue.prototype.booleanValue = function() {
- return this.value;
-}
-
-BooleanValue.prototype.numberValue = function() {
- return this.value ? 1 : 0;
-}
-
-BooleanValue.prototype.nodeSetValue = function() {
- throw this + ' ' + Error().stack;
-}
-
-function NumberValue(value) {
- this.value = value;
- this.type = 'number';
-}
-
-NumberValue.prototype.stringValue = function() {
- return '' + this.value;
-}
-
-NumberValue.prototype.booleanValue = function() {
- return !!this.value;
-}
-
-NumberValue.prototype.numberValue = function() {
- return this.value - 0;
-}
-
-NumberValue.prototype.nodeSetValue = function() {
- throw this + ' ' + Error().stack;
-}
-
-function NodeSetValue(value) {
- this.value = value;
- this.type = 'node-set';
-}
-
-NodeSetValue.prototype.stringValue = function() {
- if (this.value.length == 0) {
- return '';
- } else {
- return xmlValue(this.value[0]);
- }
-}
-
-NodeSetValue.prototype.booleanValue = function() {
- return this.value.length > 0;
-}
-
-NodeSetValue.prototype.numberValue = function() {
- return this.stringValue() - 0;
-}
-
-NodeSetValue.prototype.nodeSetValue = function() {
- return this.value;
-};
-
-// XPath expressions. They are used as nodes in the parse tree and
-// possess an evaluate() method to compute an XPath value given an XPath
-// context. Expressions are returned from the parser. Teh set of
-// expression classes closely mirrors the set of non terminal symbols
-// in the grammar. Every non trivial nonterminal symbol has a
-// corresponding expression class.
-//
-// The common expression interface consists of the following methods:
-//
-// evaluate(context) -- evaluates the expression, returns a value.
-//
-// toString() -- returns the XPath text representation of the
-// expression (defined in xsltdebug.js).
-//
-// parseTree(indent) -- returns a parse tree representation of the
-// expression (defined in xsltdebug.js).
-
-function TokenExpr(m) {
- this.value = m;
-}
-
-TokenExpr.prototype.evaluate = function() {
- return new StringValue(this.value);
-};
-
-function LocationExpr() {
- this.absolute = false;
- this.steps = [];
-}
-
-LocationExpr.prototype.appendStep = function(s) {
- this.steps.push(s);
-}
-
-LocationExpr.prototype.prependStep = function(s) {
- var steps0 = this.steps;
- this.steps = [ s ];
- for (var i = 0; i < steps0.length; ++i) {
- this.steps.push(steps0[i]);
- }
-};
-
-LocationExpr.prototype.evaluate = function(ctx) {
- var start;
- if (this.absolute) {
- start = ctx.root;
-
- } else {
- start = ctx.node;
- }
-
- var nodes = [];
- xPathStep(nodes, this.steps, 0, start, ctx);
- return new NodeSetValue(nodes);
-};
-
-function xPathStep(nodes, steps, step, input, ctx) {
- var s = steps[step];
- var ctx2 = ctx.clone(input);
- var nodelist = s.evaluate(ctx2).nodeSetValue();
-
- for (var i = 0; i < nodelist.length; ++i) {
- if (step == steps.length - 1) {
- nodes.push(nodelist[i]);
- } else {
- xPathStep(nodes, steps, step + 1, nodelist[i], ctx);
- }
- }
-}
-
-function StepExpr(axis, nodetest, predicate) {
- this.axis = axis;
- this.nodetest = nodetest;
- this.predicate = predicate || [];
-}
-
-StepExpr.prototype.appendPredicate = function(p) {
- this.predicate.push(p);
-}
-
-StepExpr.prototype.evaluate = function(ctx) {
- var input = ctx.node;
- var nodelist = [];
-
- // NOTE(mesch): When this was a switch() statement, it didn't work
- // in Safari/2.0. Not sure why though; it resulted in the JavaScript
- // console output "undefined" (without any line number or so).
-
- if (this.axis == xpathAxis.ANCESTOR_OR_SELF) {
- nodelist.push(input);
- for (var n = input.parentNode; n; n = input.parentNode) {
- nodelist.push(n);
- }
-
- } else if (this.axis == xpathAxis.ANCESTOR) {
- for (var n = input.parentNode; n; n = input.parentNode) {
- nodelist.push(n);
- }
-
- } else if (this.axis == xpathAxis.ATTRIBUTE) {
- copyArray(nodelist, input.attributes);
-
- } else if (this.axis == xpathAxis.CHILD) {
- copyArray(nodelist, input.childNodes);
-
- } else if (this.axis == xpathAxis.DESCENDANT_OR_SELF) {
- nodelist.push(input);
- xpathCollectDescendants(nodelist, input);
-
- } else if (this.axis == xpathAxis.DESCENDANT) {
- xpathCollectDescendants(nodelist, input);
-
- } else if (this.axis == xpathAxis.FOLLOWING) {
- for (var n = input.parentNode; n; n = n.parentNode) {
- for (var nn = n.nextSibling; nn; nn = nn.nextSibling) {
- nodelist.push(nn);
- xpathCollectDescendants(nodelist, nn);
- }
- }
-
- } else if (this.axis == xpathAxis.FOLLOWING_SIBLING) {
- for (var n = input.nextSibling; n; n = input.nextSibling) {
- nodelist.push(n);
- }
-
- } else if (this.axis == xpathAxis.NAMESPACE) {
- alert('not implemented: axis namespace');
-
- } else if (this.axis == xpathAxis.PARENT) {
- if (input.parentNode) {
- nodelist.push(input.parentNode);
- }
-
- } else if (this.axis == xpathAxis.PRECEDING) {
- for (var n = input.parentNode; n; n = n.parentNode) {
- for (var nn = n.previousSibling; nn; nn = nn.previousSibling) {
- nodelist.push(nn);
- xpathCollectDescendantsReverse(nodelist, nn);
- }
- }
-
- } else if (this.axis == xpathAxis.PRECEDING_SIBLING) {
- for (var n = input.previousSibling; n; n = input.previousSibling) {
- nodelist.push(n);
- }
-
- } else if (this.axis == xpathAxis.SELF) {
- nodelist.push(input);
-
- } else {
- throw 'ERROR -- NO SUCH AXIS: ' + this.axis;
- }
-
- // process node test
- var nodelist0 = nodelist;
- nodelist = [];
- for (var i = 0; i < nodelist0.length; ++i) {
- var n = nodelist0[i];
- if (this.nodetest.evaluate(ctx.clone(n, i, nodelist0)).booleanValue()) {
- nodelist.push(n);
- }
- }
-
- // process predicates
- for (var i = 0; i < this.predicate.length; ++i) {
- var nodelist0 = nodelist;
- nodelist = [];
- for (var ii = 0; ii < nodelist0.length; ++ii) {
- var n = nodelist0[ii];
- if (this.predicate[i].evaluate(ctx.clone(n, ii, nodelist0)).booleanValue()) {
- nodelist.push(n);
- }
- }
- }
-
- return new NodeSetValue(nodelist);
-};
-
-function NodeTestAny() {
- this.value = new BooleanValue(true);
-}
-
-NodeTestAny.prototype.evaluate = function(ctx) {
- return this.value;
-};
-
-function NodeTestElement() {}
-
-NodeTestElement.prototype.evaluate = function(ctx) {
- return new BooleanValue(ctx.node.nodeType == DOM_ELEMENT_NODE);
-}
-
-function NodeTestText() {}
-
-NodeTestText.prototype.evaluate = function(ctx) {
- return new BooleanValue(ctx.node.nodeType == DOM_TEXT_NODE);
-}
-
-function NodeTestComment() {}
-
-NodeTestComment.prototype.evaluate = function(ctx) {
- return new BooleanValue(ctx.node.nodeType == DOM_COMMENT_NODE);
-}
-
-function NodeTestPI(target) {
- this.target = target;
-}
-
-NodeTestPI.prototype.evaluate = function(ctx) {
- return new
- BooleanValue(ctx.node.nodeType == DOM_PROCESSING_INSTRUCTION_NODE &&
- (!this.target || ctx.node.nodeName == this.target));
-}
-
-function NodeTestNC(nsprefix) {
- this.regex = new RegExp("^" + nsprefix + ":");
- this.nsprefix = nsprefix;
-}
-
-NodeTestNC.prototype.evaluate = function(ctx) {
- var n = ctx.node;
- return new BooleanValue(this.regex.match(n.nodeName));
-}
-
-function NodeTestName(name) {
- this.name = name;
-}
-
-NodeTestName.prototype.evaluate = function(ctx) {
- var n = ctx.node;
- // NOTE (Patrick Lightbody): this change allows node selection to be case-insensitive
- return new BooleanValue(n.nodeName.toUpperCase() == this.name.toUpperCase());
-}
-
-function PredicateExpr(expr) {
- this.expr = expr;
-}
-
-PredicateExpr.prototype.evaluate = function(ctx) {
- var v = this.expr.evaluate(ctx);
- if (v.type == 'number') {
- // NOTE(mesch): Internally, position is represented starting with
- // 0, however in XPath position starts with 1. See functions
- // position() and last().
- return new BooleanValue(ctx.position == v.numberValue() - 1);
- } else {
- return new BooleanValue(v.booleanValue());
- }
-};
-
-function FunctionCallExpr(name) {
- this.name = name;
- this.args = [];
-}
-
-FunctionCallExpr.prototype.appendArg = function(arg) {
- this.args.push(arg);
-};
-
-FunctionCallExpr.prototype.evaluate = function(ctx) {
- var fn = '' + this.name.value;
- var f = this.xpathfunctions[fn];
- if (f) {
- return f.call(this, ctx);
- } else {
- Log.write('XPath NO SUCH FUNCTION ' + fn);
- return new BooleanValue(false);
- }
-};
-
-FunctionCallExpr.prototype.xpathfunctions = {
- 'last': function(ctx) {
- assert(this.args.length == 0);
- // NOTE(mesch): XPath position starts at 1.
- return new NumberValue(ctx.nodelist.length);
- },
-
- 'position': function(ctx) {
- assert(this.args.length == 0);
- // NOTE(mesch): XPath position starts at 1.
- return new NumberValue(ctx.position + 1);
- },
-
- 'count': function(ctx) {
- assert(this.args.length == 1);
- var v = this.args[0].evaluate(ctx);
- return new NumberValue(v.nodeSetValue().length);
- },
-
- 'id': function(ctx) {
- assert(this.args.length == 1);
- var e = this.args.evaluate(ctx);
- var ret = [];
- var ids;
- if (e.type == 'node-set') {
- ids = [];
- for (var i = 0; i < e.length; ++i) {
- var v = xmlValue(e[i]).split(/\s+/);
- for (var ii = 0; ii < v.length; ++ii) {
- ids.push(v[ii]);
- }
- }
- } else {
- ids = e.split(/\s+/);
- }
- var d = ctx.node.ownerDocument;
- for (var i = 0; i < ids.length; ++i) {
- var n = d.getElementById(ids[i]);
- if (n) {
- ret.push(n);
- }
- }
- return new NodeSetValue(ret);
- },
-
- 'local-name': function(ctx) {
- alert('not implmented yet: XPath function local-name()');
- },
-
- 'namespace-uri': function(ctx) {
- alert('not implmented yet: XPath function namespace-uri()');
- },
-
- 'name': function(ctx) {
- assert(this.args.length == 1 || this.args.length == 0);
- var n;
- if (this.args.length == 0) {
- n = [ ctx.node ];
- } else {
- n = this.args[0].evaluate(ctx).nodeSetValue();
- }
-
- if (n.length == 0) {
- return new StringValue('');
- } else {
- return new StringValue(n[0].nodeName);
- }
- },
-
- 'string': function(ctx) {
- assert(this.args.length == 1 || this.args.length == 0);
- if (this.args.length == 0) {
- return new StringValue(new NodeSetValue([ ctx.node ]).stringValue());
- } else {
- return new StringValue(this.args[0].evaluate(ctx).stringValue());
- }
- },
-
- 'concat': function(ctx) {
- var ret = '';
- for (var i = 0; i < this.args.length; ++i) {
- ret += this.args[i].evaluate(ctx).stringValue();
- }
- return new StringValue(ret);
- },
-
- 'starts-with': function(ctx) {
- assert(this.args.length == 2);
- var s0 = this.args[0].evaluate(ctx).stringValue();
- var s1 = this.args[1].evaluate(ctx).stringValue();
- return new BooleanValue(s0.indexOf(s1) == 0);
- },
-
- 'contains': function(ctx) {
- assert(this.args.length == 2);
- var s0 = this.args[0].evaluate(ctx).stringValue();
- var s1 = this.args[1].evaluate(ctx).stringValue();
- return new BooleanValue(s0.indexOf(s1) != -1);
- },
-
- 'substring-before': function(ctx) {
- assert(this.args.length == 2);
- var s0 = this.args[0].evaluate(ctx).stringValue();
- var s1 = this.args[1].evaluate(ctx).stringValue();
- var i = s0.indexOf(s1);
- var ret;
- if (i == -1) {
- ret = '';
- } else {
- ret = s0.substr(0,i);
- }
- return new StringValue(ret);
- },
-
- 'substring-after': function(ctx) {
- assert(this.args.length == 2);
- var s0 = this.args[0].evaluate(ctx).stringValue();
- var s1 = this.args[1].evaluate(ctx).stringValue();
- var i = s0.indexOf(s1);
- var ret;
- if (i == -1) {
- ret = '';
- } else {
- ret = s0.substr(i + s1.length);
- }
- return new StringValue(ret);
- },
-
- 'substring': function(ctx) {
- // NOTE: XPath defines the position of the first character in a
- // string to be 1, in JavaScript this is 0 ([XPATH] Section 4.2).
- assert(this.args.length == 2 || this.args.length == 3);
- var s0 = this.args[0].evaluate(ctx).stringValue();
- var s1 = this.args[1].evaluate(ctx).numberValue();
- var ret;
- if (this.args.length == 2) {
- var i1 = Math.max(0, Math.round(s1) - 1);
- ret = s0.substr(i1);
-
- } else {
- var s2 = this.args[2].evaluate(ctx).numberValue();
- var i0 = Math.round(s1) - 1;
- var i1 = Math.max(0, i0);
- var i2 = Math.round(s2) - Math.max(0, -i0);
- ret = s0.substr(i1, i2);
- }
- return new StringValue(ret);
- },
-
- 'string-length': function(ctx) {
- var s;
- if (this.args.length > 0) {
- s = this.args[0].evaluate(ctx).stringValue();
- } else {
- s = new NodeSetValue([ ctx.node ]).stringValue();
- }
- return new NumberValue(s.length);
- },
-
- 'normalize-space': function(ctx) {
- var s;
- if (this.args.length > 0) {
- s = this.args[0].evaluate(ctx).stringValue();
- } else {
- s = new NodeSetValue([ ctx.node ]).stringValue();
- }
- s = s.replace(/^\s*/,'').replace(/\s*$/,'').replace(/\s+/g, ' ');
- return new StringValue(s);
- },
-
- 'translate': function(ctx) {
- assert(this.args.length == 3);
- var s0 = this.args[0].evaluate(ctx).stringValue();
- var s1 = this.args[1].evaluate(ctx).stringValue();
- var s2 = this.args[2].evaluate(ctx).stringValue();
-
- for (var i = 0; i < s1.length; ++i) {
- s0 = s0.replace(new RegExp(s1.charAt(i), 'g'), s2.charAt(i));
- }
- return new StringValue(s0);
- },
-
- 'boolean': function(ctx) {
- assert(this.args.length == 1);
- return new BooleanValue(this.args[0].evaluate(ctx).booleanValue());
- },
-
- 'not': function(ctx) {
- assert(this.args.length == 1);
- var ret = !this.args[0].evaluate(ctx).booleanValue();
- return new BooleanValue(ret);
- },
-
- 'true': function(ctx) {
- assert(this.args.length == 0);
- return new BooleanValue(true);
- },
-
- 'false': function(ctx) {
- assert(this.args.length == 0);
- return new BooleanValue(false);
- },
-
- 'lang': function(ctx) {
- assert(this.args.length == 1);
- var lang = this.args[0].evaluate(ctx).stringValue();
- var xmllang;
- var n = ctx.node;
- while (n && n != n.parentNode /* just in case ... */) {
- xmllang = n.getAttribute('xml:lang');
- if (xmllang) {
- break;
- }
- n = n.parentNode;
- }
- if (!xmllang) {
- return new BooleanValue(false);
- } else {
- var re = new RegExp('^' + lang + '$', 'i');
- return new BooleanValue(xmllang.match(re) ||
- xmllang.replace(/_.*$/,'').match(re));
- }
- },
-
- 'number': function(ctx) {
- assert(this.args.length == 1 || this.args.length == 0);
-
- if (this.args.length == 1) {
- return new NumberValue(this.args[0].evaluate(ctx).numberValue());
- } else {
- return new NumberValue(new NodeSetValue([ ctx.node ]).numberValue());
- }
- },
-
- 'sum': function(ctx) {
- assert(this.args.length == 1);
- var n = this.args[0].evaluate(ctx).nodeSetValue();
- var sum = 0;
- for (var i = 0; i < n.length; ++i) {
- sum += xmlValue(n[i]) - 0;
- }
- return new NumberValue(sum);
- },
-
- 'floor': function(ctx) {
- assert(this.args.length == 1);
- var num = this.args[0].evaluate(ctx).numberValue();
- return new NumberValue(Math.floor(num));
- },
-
- 'ceiling': function(ctx) {
- assert(this.args.length == 1);
- var num = this.args[0].evaluate(ctx).numberValue();
- return new NumberValue(Math.ceil(num));
- },
-
- 'round': function(ctx) {
- assert(this.args.length == 1);
- var num = this.args[0].evaluate(ctx).numberValue();
- return new NumberValue(Math.round(num));
- },
-
- // TODO(mesch): The following functions are custom. There is a
- // standard that defines how to add functions, which should be
- // applied here.
-
- 'ext-join': function(ctx) {
- assert(this.args.length == 2);
- var nodes = this.args[0].evaluate(ctx).nodeSetValue();
- var delim = this.args[1].evaluate(ctx).stringValue();
- var ret = '';
- for (var i = 0; i < nodes.length; ++i) {
- if (ret) {
- ret += delim;
- }
- ret += xmlValue(nodes[i]);
- }
- return new StringValue(ret);
- },
-
- // ext-if() evaluates and returns its second argument, if the
- // boolean value of its first argument is true, otherwise it
- // evaluates and returns its third argument.
-
- 'ext-if': function(ctx) {
- assert(this.args.length == 3);
- if (this.args[0].evaluate(ctx).booleanValue()) {
- return this.args[1].evaluate(ctx);
- } else {
- return this.args[2].evaluate(ctx);
- }
- },
-
- 'ext-sprintf': function(ctx) {
- assert(this.args.length >= 1);
- var args = [];
- for (var i = 0; i < this.args.length; ++i) {
- args.push(this.args[i].evaluate(ctx).stringValue());
- }
- return new StringValue(sprintf.apply(null, args));
- },
-
- // ext-cardinal() evaluates its single argument as a number, and
- // returns the current node that many times. It can be used in the
- // select attribute to iterate over an integer range.
-
- 'ext-cardinal': function(ctx) {
- assert(this.args.length >= 1);
- var c = this.args[0].evaluate(ctx).numberValue();
- var ret = [];
- for (var i = 0; i < c; ++i) {
- ret.push(ctx.node);
- }
- return new NodeSetValue(ret);
- }
-};
-
-function UnionExpr(expr1, expr2) {
- this.expr1 = expr1;
- this.expr2 = expr2;
-}
-
-UnionExpr.prototype.evaluate = function(ctx) {
- var nodes1 = this.expr1.evaluate(ctx).nodeSetValue();
- var nodes2 = this.expr2.evaluate(ctx).nodeSetValue();
- var I1 = nodes1.length;
- for (var i2 = 0; i2 < nodes2.length; ++i2) {
- for (var i1 = 0; i1 < I1; ++i1) {
- if (nodes1[i1] == nodes2[i2]) {
- // break inner loop and continue outer loop, labels confuse
- // the js compiler, so we don't use them here.
- i1 = I1;
- }
- }
- nodes1.push(nodes2[i2]);
- }
- return new NodeSetValue(nodes2);
-};
-
-function PathExpr(filter, rel) {
- this.filter = filter;
- this.rel = rel;
-}
-
-PathExpr.prototype.evaluate = function(ctx) {
- var nodes = this.filter.evaluate(ctx).nodeSetValue();
- var nodes1 = [];
- for (var i = 0; i < nodes.length; ++i) {
- var nodes0 = this.rel.evaluate(ctx.clone(nodes[i], i, nodes)).nodeSetValue();
- for (var ii = 0; ii < nodes0.length; ++ii) {
- nodes1.push(nodes0[ii]);
- }
- }
- return new NodeSetValue(nodes1);
-};
-
-function FilterExpr(expr, predicate) {
- this.expr = expr;
- this.predicate = predicate;
-}
-
-FilterExpr.prototype.evaluate = function(ctx) {
- var nodes = this.expr.evaluate(ctx).nodeSetValue();
- for (var i = 0; i < this.predicate.length; ++i) {
- var nodes0 = nodes;
- nodes = [];
- for (var j = 0; j < nodes0.length; ++j) {
- var n = nodes0[j];
- if (this.predicate[i].evaluate(ctx.clone(n, j, nodes0)).booleanValue()) {
- nodes.push(n);
- }
- }
- }
-
- return new NodeSetValue(nodes);
-}
-
-function UnaryMinusExpr(expr) {
- this.expr = expr;
-}
-
-UnaryMinusExpr.prototype.evaluate = function(ctx) {
- return new NumberValue(-this.expr.evaluate(ctx).numberValue());
-};
-
-function BinaryExpr(expr1, op, expr2) {
- this.expr1 = expr1;
- this.expr2 = expr2;
- this.op = op;
-}
-
-BinaryExpr.prototype.evaluate = function(ctx) {
- var ret;
- switch (this.op.value) {
- case 'or':
- ret = new BooleanValue(this.expr1.evaluate(ctx).booleanValue() ||
- this.expr2.evaluate(ctx).booleanValue());
- break;
-
- case 'and':
- ret = new BooleanValue(this.expr1.evaluate(ctx).booleanValue() &&
- this.expr2.evaluate(ctx).booleanValue());
- break;
-
- case '+':
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() +
- this.expr2.evaluate(ctx).numberValue());
- break;
-
- case '-':
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() -
- this.expr2.evaluate(ctx).numberValue());
- break;
-
- case '*':
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() *
- this.expr2.evaluate(ctx).numberValue());
- break;
-
- case 'mod':
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() %
- this.expr2.evaluate(ctx).numberValue());
- break;
-
- case 'div':
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() /
- this.expr2.evaluate(ctx).numberValue());
- break;
-
- case '=':
- ret = this.compare(ctx, function(x1, x2) { return x1 == x2; });
- break;
-
- case '!=':
- ret = this.compare(ctx, function(x1, x2) { return x1 != x2; });
- break;
-
- case '<':
- ret = this.compare(ctx, function(x1, x2) { return x1 < x2; });
- break;
-
- case '<=':
- ret = this.compare(ctx, function(x1, x2) { return x1 <= x2; });
- break;
-
- case '>':
- ret = this.compare(ctx, function(x1, x2) { return x1 > x2; });
- break;
-
- case '>=':
- ret = this.compare(ctx, function(x1, x2) { return x1 >= x2; });
- break;
-
- default:
- alert('BinaryExpr.evaluate: ' + this.op.value);
- }
- return ret;
-};
-
-BinaryExpr.prototype.compare = function(ctx, cmp) {
- var v1 = this.expr1.evaluate(ctx);
- var v2 = this.expr2.evaluate(ctx);
-
- var ret;
- if (v1.type == 'node-set' && v2.type == 'node-set') {
- var n1 = v1.nodeSetValue();
- var n2 = v2.nodeSetValue();
- ret = false;
- for (var i1 = 0; i1 < n1.length; ++i1) {
- for (var i2 = 0; i2 < n2.length; ++i2) {
- if (cmp(xmlValue(n1[i1]), xmlValue(n2[i2]))) {
- ret = true;
- // Break outer loop. Labels confuse the jscompiler and we
- // don't use them.
- i2 = n2.length;
- i1 = n1.length;
- }
- }
- }
-
- } else if (v1.type == 'node-set' || v2.type == 'node-set') {
-
- if (v1.type == 'number') {
- var s = v1.numberValue();
- var n = v2.nodeSetValue();
-
- ret = false;
- for (var i = 0; i < n.length; ++i) {
- var nn = xmlValue(n[i]) - 0;
- if (cmp(s, nn)) {
- ret = true;
- break;
- }
- }
-
- } else if (v2.type == 'number') {
- var n = v1.nodeSetValue();
- var s = v2.numberValue();
-
- ret = false;
- for (var i = 0; i < n.length; ++i) {
- var nn = xmlValue(n[i]) - 0;
- if (cmp(nn, s)) {
- ret = true;
- break;
- }
- }
-
- } else if (v1.type == 'string') {
- var s = v1.stringValue();
- var n = v2.nodeSetValue();
-
- ret = false;
- for (var i = 0; i < n.length; ++i) {
- var nn = xmlValue(n[i]);
- if (cmp(s, nn)) {
- ret = true;
- break;
- }
- }
-
- } else if (v2.type == 'string') {
- var n = v1.nodeSetValue();
- var s = v2.stringValue();
-
- ret = false;
- for (var i = 0; i < n.length; ++i) {
- var nn = xmlValue(n[i]);
- if (cmp(nn, s)) {
- ret = true;
- break;
- }
- }
-
- } else {
- ret = cmp(v1.booleanValue(), v2.booleanValue());
- }
-
- } else if (v1.type == 'boolean' || v2.type == 'boolean') {
- ret = cmp(v1.booleanValue(), v2.booleanValue());
-
- } else if (v1.type == 'number' || v2.type == 'number') {
- ret = cmp(v1.numberValue(), v2.numberValue());
-
- } else {
- ret = cmp(v1.stringValue(), v2.stringValue());
- }
-
- return new BooleanValue(ret);
-}
-
-function LiteralExpr(value) {
- this.value = value;
-}
-
-LiteralExpr.prototype.evaluate = function(ctx) {
- return new StringValue(this.value);
-};
-
-function NumberExpr(value) {
- this.value = value;
-}
-
-NumberExpr.prototype.evaluate = function(ctx) {
- return new NumberValue(this.value);
-};
-
-function VariableExpr(name) {
- this.name = name;
-}
-
-VariableExpr.prototype.evaluate = function(ctx) {
- return ctx.getVariable(this.name);
-}
-
-// Factory functions for semantic values (i.e. Expressions) of the
-// productions in the grammar. When a production is matched to reduce
-// the current parse state stack, the function is called with the
-// semantic values of the matched elements as arguments, and returns
-// another semantic value. The semantic value is a node of the parse
-// tree, an expression object with an evaluate() method that evaluates the
-// expression in an actual context. These factory functions are used
-// in the specification of the grammar rules, below.
-
-function makeTokenExpr(m) {
- return new TokenExpr(m);
-}
-
-function passExpr(e) {
- return e;
-}
-
-function makeLocationExpr1(slash, rel) {
- rel.absolute = true;
- return rel;
-}
-
-function makeLocationExpr2(dslash, rel) {
- rel.absolute = true;
- rel.prependStep(makeAbbrevStep(dslash.value));
- return rel;
-}
-
-function makeLocationExpr3(slash) {
- var ret = new LocationExpr();
- ret.appendStep(makeAbbrevStep('.'));
- ret.absolute = true;
- return ret;
-}
-
-function makeLocationExpr4(dslash) {
- var ret = new LocationExpr();
- ret.absolute = true;
- ret.appendStep(makeAbbrevStep(dslash.value));
- return ret;
-}
-
-function makeLocationExpr5(step) {
- var ret = new LocationExpr();
- ret.appendStep(step);
- return ret;
-}
-
-function makeLocationExpr6(rel, slash, step) {
- rel.appendStep(step);
- return rel;
-}
-
-function makeLocationExpr7(rel, dslash, step) {
- rel.appendStep(makeAbbrevStep(dslash.value));
- return rel;
-}
-
-function makeStepExpr1(dot) {
- return makeAbbrevStep(dot.value);
-}
-
-function makeStepExpr2(ddot) {
- return makeAbbrevStep(ddot.value);
-}
-
-function makeStepExpr3(axisname, axis, nodetest) {
- return new StepExpr(axisname.value, nodetest);
-}
-
-function makeStepExpr4(at, nodetest) {
- return new StepExpr('attribute', nodetest);
-}
-
-function makeStepExpr5(nodetest) {
- return new StepExpr('child', nodetest);
-}
-
-function makeStepExpr6(step, predicate) {
- step.appendPredicate(predicate);
- return step;
-}
-
-function makeAbbrevStep(abbrev) {
- switch (abbrev) {
- case '//':
- return new StepExpr('descendant-or-self', new NodeTestAny);
-
- case '.':
- return new StepExpr('self', new NodeTestAny);
-
- case '..':
- return new StepExpr('parent', new NodeTestAny);
- }
-}
-
-function makeNodeTestExpr1(asterisk) {
- return new NodeTestElement;
-}
-
-function makeNodeTestExpr2(ncname, colon, asterisk) {
- return new NodeTestNC(ncname.value);
-}
-
-function makeNodeTestExpr3(qname) {
- return new NodeTestName(qname.value);
-}
-
-function makeNodeTestExpr4(typeo, parenc) {
- var type = typeo.value.replace(/\s*\($/, '');
- switch(type) {
- case 'node':
- return new NodeTestAny;
-
- case 'text':
- return new NodeTestText;
-
- case 'comment':
- return new NodeTestComment;
-
- case 'processing-instruction':
- return new NodeTestPI;
- }
-}
-
-function makeNodeTestExpr5(typeo, target, parenc) {
- var type = typeo.replace(/\s*\($/, '');
- if (type != 'processing-instruction') {
- throw type + ' ' + Error().stack;
- }
- return new NodeTestPI(target.value);
-}
-
-function makePredicateExpr(pareno, expr, parenc) {
- return new PredicateExpr(expr);
-}
-
-function makePrimaryExpr(pareno, expr, parenc) {
- return expr;
-}
-
-function makeFunctionCallExpr1(name, pareno, parenc) {
- return new FunctionCallExpr(name);
-}
-
-function makeFunctionCallExpr2(name, pareno, arg1, args, parenc) {
- var ret = new FunctionCallExpr(name);
- ret.appendArg(arg1);
- for (var i = 0; i < args.length; ++i) {
- ret.appendArg(args[i]);
- }
- return ret;
-}
-
-function makeArgumentExpr(comma, expr) {
- return expr;
-}
-
-function makeUnionExpr(expr1, pipe, expr2) {
- return new UnionExpr(expr1, expr2);
-}
-
-function makePathExpr1(filter, slash, rel) {
- return new PathExpr(filter, rel);
-}
-
-function makePathExpr2(filter, dslash, rel) {
- rel.prependStep(makeAbbrevStep(dslash.value));
- return new PathExpr(filter, rel);
-}
-
-function makeFilterExpr(expr, predicates) {
- if (predicates.length > 0) {
- return new FilterExpr(expr, predicates);
- } else {
- return expr;
- }
-}
-
-function makeUnaryMinusExpr(minus, expr) {
- return new UnaryMinusExpr(expr);
-}
-
-function makeBinaryExpr(expr1, op, expr2) {
- return new BinaryExpr(expr1, op, expr2);
-}
-
-function makeLiteralExpr(token) {
- // remove quotes from the parsed value:
- var value = token.value.substring(1, token.value.length - 1);
- return new LiteralExpr(value);
-}
-
-function makeNumberExpr(token) {
- return new NumberExpr(token.value);
-}
-
-function makeVariableReference(dollar, name) {
- return new VariableExpr(name.value);
-}
-
-// Used before parsing for optimization of common simple cases. See
-// the begin of xpathParse() for which they are.
-function makeSimpleExpr(expr) {
- if (expr.charAt(0) == '$') {
- return new VariableExpr(expr.substr(1));
- } else if (expr.charAt(0) == '@') {
- var a = new NodeTestName(expr.substr(1));
- var b = new StepExpr('attribute', a);
- var c = new LocationExpr();
- c.appendStep(b);
- return c;
- } else if (expr.match(/^[0-9]+$/)) {
- return new NumberExpr(expr);
- } else {
- var a = new NodeTestName(expr);
- var b = new StepExpr('child', a);
- var c = new LocationExpr();
- c.appendStep(b);
- return c;
- }
-}
-
-function makeSimpleExpr2(expr) {
- var steps = expr.split('/');
- var c = new LocationExpr();
- for (var i in steps) {
- var a = new NodeTestName(steps[i]);
- var b = new StepExpr('child', a);
- c.appendStep(b);
- }
- return c;
-}
-
-// The axes of XPath expressions.
-
-var xpathAxis = {
- ANCESTOR_OR_SELF: 'ancestor-or-self',
- ANCESTOR: 'ancestor',
- ATTRIBUTE: 'attribute',
- CHILD: 'child',
- DESCENDANT_OR_SELF: 'descendant-or-self',
- DESCENDANT: 'descendant',
- FOLLOWING_SIBLING: 'following-sibling',
- FOLLOWING: 'following',
- NAMESPACE: 'namespace',
- PARENT: 'parent',
- PRECEDING_SIBLING: 'preceding-sibling',
- PRECEDING: 'preceding',
- SELF: 'self'
-};
-
-var xpathAxesRe = [
- xpathAxis.ANCESTOR_OR_SELF,
- xpathAxis.ANCESTOR,
- xpathAxis.ATTRIBUTE,
- xpathAxis.CHILD,
- xpathAxis.DESCENDANT_OR_SELF,
- xpathAxis.DESCENDANT,
- xpathAxis.FOLLOWING_SIBLING,
- xpathAxis.FOLLOWING,
- xpathAxis.NAMESPACE,
- xpathAxis.PARENT,
- xpathAxis.PRECEDING_SIBLING,
- xpathAxis.PRECEDING,
- xpathAxis.SELF
-].join('|');
-
-
-// The tokens of the language. The label property is just used for
-// generating debug output. The prec property is the precedence used
-// for shift/reduce resolution. Default precedence is 0 as a lookahead
-// token and 2 on the stack. TODO(mesch): this is certainly not
-// necessary and too complicated. Simplify this!
-
-// NOTE: tabular formatting is the big exception, but here it should
-// be OK.
-
-var TOK_PIPE = { label: "|", prec: 17, re: new RegExp("^\\|") };
-var TOK_DSLASH = { label: "//", prec: 19, re: new RegExp("^//") };
-var TOK_SLASH = { label: "/", prec: 30, re: new RegExp("^/") };
-var TOK_AXIS = { label: "::", prec: 20, re: new RegExp("^::") };
-var TOK_COLON = { label: ":", prec: 1000, re: new RegExp("^:") };
-var TOK_AXISNAME = { label: "[axis]", re: new RegExp('^(' + xpathAxesRe + ')') };
-var TOK_PARENO = { label: "(", prec: 34, re: new RegExp("^\\(") };
-var TOK_PARENC = { label: ")", re: new RegExp("^\\)") };
-var TOK_DDOT = { label: "..", prec: 34, re: new RegExp("^\\.\\.") };
-var TOK_DOT = { label: ".", prec: 34, re: new RegExp("^\\.") };
-var TOK_AT = { label: "@", prec: 34, re: new RegExp("^@") };
-
-var TOK_COMMA = { label: ",", re: new RegExp("^,") };
-
-var TOK_OR = { label: "or", prec: 10, re: new RegExp("^or\\b") };
-var TOK_AND = { label: "and", prec: 11, re: new RegExp("^and\\b") };
-var TOK_EQ = { label: "=", prec: 12, re: new RegExp("^=") };
-var TOK_NEQ = { label: "!=", prec: 12, re: new RegExp("^!=") };
-var TOK_GE = { label: ">=", prec: 13, re: new RegExp("^>=") };
-var TOK_GT = { label: ">", prec: 13, re: new RegExp("^>") };
-var TOK_LE = { label: "<=", prec: 13, re: new RegExp("^<=") };
-var TOK_LT = { label: "<", prec: 13, re: new RegExp("^<") };
-var TOK_PLUS = { label: "+", prec: 14, re: new RegExp("^\\+"), left: true };
-var TOK_MINUS = { label: "-", prec: 14, re: new RegExp("^\\-"), left: true };
-var TOK_DIV = { label: "div", prec: 15, re: new RegExp("^div\\b"), left: true };
-var TOK_MOD = { label: "mod", prec: 15, re: new RegExp("^mod\\b"), left: true };
-
-var TOK_BRACKO = { label: "[", prec: 32, re: new RegExp("^\\[") };
-var TOK_BRACKC = { label: "]", re: new RegExp("^\\]") };
-var TOK_DOLLAR = { label: "$", re: new RegExp("^\\$") };
-
-var TOK_NCNAME = { label: "[ncname]", re: new RegExp('^[a-z][-\\w]*','i') };
-
-var TOK_ASTERISK = { label: "*", prec: 15, re: new RegExp("^\\*"), left: true };
-var TOK_LITERALQ = { label: "[litq]", prec: 20, re: new RegExp("^'[^\\']*'") };
-var TOK_LITERALQQ = {
- label: "[litqq]",
- prec: 20,
- re: new RegExp('^"[^\\"]*"')
-};
-
-var TOK_NUMBER = {
- label: "[number]",
- prec: 35,
- re: new RegExp('^\\d+(\\.\\d*)?') };
-
-var TOK_QNAME = {
- label: "[qname]",
- re: new RegExp('^([a-z][-\\w]*:)?[a-z][-\\w]*','i')
-};
-
-var TOK_NODEO = {
- label: "[nodetest-start]",
- re: new RegExp('^(processing-instruction|comment|text|node)\\(')
-};
-
-// The table of the tokens of our grammar, used by the lexer: first
-// column the tag, second column a regexp to recognize it in the
-// input, third column the precedence of the token, fourth column a
-// factory function for the semantic value of the token.
-//
-// NOTE: order of this list is important, because the first match
-// counts. Cf. DDOT and DOT, and AXIS and COLON.
-
-var xpathTokenRules = [
- TOK_DSLASH,
- TOK_SLASH,
- TOK_DDOT,
- TOK_DOT,
- TOK_AXIS,
- TOK_COLON,
- TOK_AXISNAME,
- TOK_NODEO,
- TOK_PARENO,
- TOK_PARENC,
- TOK_BRACKO,
- TOK_BRACKC,
- TOK_AT,
- TOK_COMMA,
- TOK_OR,
- TOK_AND,
- TOK_NEQ,
- TOK_EQ,
- TOK_GE,
- TOK_GT,
- TOK_LE,
- TOK_LT,
- TOK_PLUS,
- TOK_MINUS,
- TOK_ASTERISK,
- TOK_PIPE,
- TOK_MOD,
- TOK_DIV,
- TOK_LITERALQ,
- TOK_LITERALQQ,
- TOK_NUMBER,
- TOK_QNAME,
- TOK_NCNAME,
- TOK_DOLLAR
-];
-
-// All the nonterminals of the grammar. The nonterminal objects are
-// identified by object identity; the labels are used in the debug
-// output only.
-var XPathLocationPath = { label: "LocationPath" };
-var XPathRelativeLocationPath = { label: "RelativeLocationPath" };
-var XPathAbsoluteLocationPath = { label: "AbsoluteLocationPath" };
-var XPathStep = { label: "Step" };
-var XPathNodeTest = { label: "NodeTest" };
-var XPathPredicate = { label: "Predicate" };
-var XPathLiteral = { label: "Literal" };
-var XPathExpr = { label: "Expr" };
-var XPathPrimaryExpr = { label: "PrimaryExpr" };
-var XPathVariableReference = { label: "Variablereference" };
-var XPathNumber = { label: "Number" };
-var XPathFunctionCall = { label: "FunctionCall" };
-var XPathArgumentRemainder = { label: "ArgumentRemainder" };
-var XPathPathExpr = { label: "PathExpr" };
-var XPathUnionExpr = { label: "UnionExpr" };
-var XPathFilterExpr = { label: "FilterExpr" };
-var XPathDigits = { label: "Digits" };
-
-var xpathNonTerminals = [
- XPathLocationPath,
- XPathRelativeLocationPath,
- XPathAbsoluteLocationPath,
- XPathStep,
- XPathNodeTest,
- XPathPredicate,
- XPathLiteral,
- XPathExpr,
- XPathPrimaryExpr,
- XPathVariableReference,
- XPathNumber,
- XPathFunctionCall,
- XPathArgumentRemainder,
- XPathPathExpr,
- XPathUnionExpr,
- XPathFilterExpr,
- XPathDigits
-];
-
-// Quantifiers that are used in the productions of the grammar.
-var Q_01 = { label: "?" };
-var Q_MM = { label: "*" };
-var Q_1M = { label: "+" };
-
-// Tag for left associativity (right assoc is implied by undefined).
-var ASSOC_LEFT = true;
-
-// The productions of the grammar. Columns of the table:
-//
-// - target nonterminal,
-// - pattern,
-// - precedence,
-// - semantic value factory
-//
-// The semantic value factory is a function that receives parse tree
-// nodes from the stack frames of the matched symbols as arguments and
-// returns an a node of the parse tree. The node is stored in the top
-// stack frame along with the target object of the rule. The node in
-// the parse tree is an expression object that has an evaluate() method
-// and thus evaluates XPath expressions.
-//
-// The precedence is used to decide between reducing and shifting by
-// comparing the precendence of the rule that is candidate for
-// reducing with the precedence of the look ahead token. Precedence of
-// -1 means that the precedence of the tokens in the pattern is used
-// instead. TODO: It shouldn't be necessary to explicitly assign
-// precedences to rules.
-
-var xpathGrammarRules =
- [
- [ XPathLocationPath, [ XPathRelativeLocationPath ], 18,
- passExpr ],
- [ XPathLocationPath, [ XPathAbsoluteLocationPath ], 18,
- passExpr ],
-
- [ XPathAbsoluteLocationPath, [ TOK_SLASH, XPathRelativeLocationPath ], 18,
- makeLocationExpr1 ],
- [ XPathAbsoluteLocationPath, [ TOK_DSLASH, XPathRelativeLocationPath ], 18,
- makeLocationExpr2 ],
-
- [ XPathAbsoluteLocationPath, [ TOK_SLASH ], 0,
- makeLocationExpr3 ],
- [ XPathAbsoluteLocationPath, [ TOK_DSLASH ], 0,
- makeLocationExpr4 ],
-
- [ XPathRelativeLocationPath, [ XPathStep ], 31,
- makeLocationExpr5 ],
- [ XPathRelativeLocationPath,
- [ XPathRelativeLocationPath, TOK_SLASH, XPathStep ], 31,
- makeLocationExpr6 ],
- [ XPathRelativeLocationPath,
- [ XPathRelativeLocationPath, TOK_DSLASH, XPathStep ], 31,
- makeLocationExpr7 ],
-
- [ XPathStep, [ TOK_DOT ], 33,
- makeStepExpr1 ],
- [ XPathStep, [ TOK_DDOT ], 33,
- makeStepExpr2 ],
- [ XPathStep,
- [ TOK_AXISNAME, TOK_AXIS, XPathNodeTest ], 33,
- makeStepExpr3 ],
- [ XPathStep, [ TOK_AT, XPathNodeTest ], 33,
- makeStepExpr4 ],
- [ XPathStep, [ XPathNodeTest ], 33,
- makeStepExpr5 ],
- [ XPathStep, [ XPathStep, XPathPredicate ], 33,
- makeStepExpr6 ],
-
- [ XPathNodeTest, [ TOK_ASTERISK ], 33,
- makeNodeTestExpr1 ],
- [ XPathNodeTest, [ TOK_NCNAME, TOK_COLON, TOK_ASTERISK ], 33,
- makeNodeTestExpr2 ],
- [ XPathNodeTest, [ TOK_QNAME ], 33,
- makeNodeTestExpr3 ],
- [ XPathNodeTest, [ TOK_NODEO, TOK_PARENC ], 33,
- makeNodeTestExpr4 ],
- [ XPathNodeTest, [ TOK_NODEO, XPathLiteral, TOK_PARENC ], 33,
- makeNodeTestExpr5 ],
-
- [ XPathPredicate, [ TOK_BRACKO, XPathExpr, TOK_BRACKC ], 33,
- makePredicateExpr ],
-
- [ XPathPrimaryExpr, [ XPathVariableReference ], 33,
- passExpr ],
- [ XPathPrimaryExpr, [ TOK_PARENO, XPathExpr, TOK_PARENC ], 33,
- makePrimaryExpr ],
- [ XPathPrimaryExpr, [ XPathLiteral ], 30,
- passExpr ],
- [ XPathPrimaryExpr, [ XPathNumber ], 30,
- passExpr ],
- [ XPathPrimaryExpr, [ XPathFunctionCall ], 30,
- passExpr ],
-
- [ XPathFunctionCall, [ TOK_QNAME, TOK_PARENO, TOK_PARENC ], -1,
- makeFunctionCallExpr1 ],
- [ XPathFunctionCall,
- [ TOK_QNAME, TOK_PARENO, XPathExpr, XPathArgumentRemainder, Q_MM,
- TOK_PARENC ], -1,
- makeFunctionCallExpr2 ],
- [ XPathArgumentRemainder, [ TOK_COMMA, XPathExpr ], -1,
- makeArgumentExpr ],
-
- [ XPathUnionExpr, [ XPathPathExpr ], 20,
- passExpr ],
- [ XPathUnionExpr, [ XPathUnionExpr, TOK_PIPE, XPathPathExpr ], 20,
- makeUnionExpr ],
-
- [ XPathPathExpr, [ XPathLocationPath ], 20,
- passExpr ],
- [ XPathPathExpr, [ XPathFilterExpr ], 19,
- passExpr ],
- [ XPathPathExpr,
- [ XPathFilterExpr, TOK_SLASH, XPathRelativeLocationPath ], 20,
- makePathExpr1 ],
- [ XPathPathExpr,
- [ XPathFilterExpr, TOK_DSLASH, XPathRelativeLocationPath ], 20,
- makePathExpr2 ],
-
- [ XPathFilterExpr, [ XPathPrimaryExpr, XPathPredicate, Q_MM ], 20,
- makeFilterExpr ],
-
- [ XPathExpr, [ XPathPrimaryExpr ], 16,
- passExpr ],
- [ XPathExpr, [ XPathUnionExpr ], 16,
- passExpr ],
-
- [ XPathExpr, [ TOK_MINUS, XPathExpr ], -1,
- makeUnaryMinusExpr ],
-
- [ XPathExpr, [ XPathExpr, TOK_OR, XPathExpr ], -1,
- makeBinaryExpr ],
- [ XPathExpr, [ XPathExpr, TOK_AND, XPathExpr ], -1,
- makeBinaryExpr ],
-
- [ XPathExpr, [ XPathExpr, TOK_EQ, XPathExpr ], -1,
- makeBinaryExpr ],
- [ XPathExpr, [ XPathExpr, TOK_NEQ, XPathExpr ], -1,
- makeBinaryExpr ],
-
- [ XPathExpr, [ XPathExpr, TOK_LT, XPathExpr ], -1,
- makeBinaryExpr ],
- [ XPathExpr, [ XPathExpr, TOK_LE, XPathExpr ], -1,
- makeBinaryExpr ],
- [ XPathExpr, [ XPathExpr, TOK_GT, XPathExpr ], -1,
- makeBinaryExpr ],
- [ XPathExpr, [ XPathExpr, TOK_GE, XPathExpr ], -1,
- makeBinaryExpr ],
-
- [ XPathExpr, [ XPathExpr, TOK_PLUS, XPathExpr ], -1,
- makeBinaryExpr, ASSOC_LEFT ],
- [ XPathExpr, [ XPathExpr, TOK_MINUS, XPathExpr ], -1,
- makeBinaryExpr, ASSOC_LEFT ],
-
- [ XPathExpr, [ XPathExpr, TOK_ASTERISK, XPathExpr ], -1,
- makeBinaryExpr, ASSOC_LEFT ],
- [ XPathExpr, [ XPathExpr, TOK_DIV, XPathExpr ], -1,
- makeBinaryExpr, ASSOC_LEFT ],
- [ XPathExpr, [ XPathExpr, TOK_MOD, XPathExpr ], -1,
- makeBinaryExpr, ASSOC_LEFT ],
-
- [ XPathLiteral, [ TOK_LITERALQ ], -1,
- makeLiteralExpr ],
- [ XPathLiteral, [ TOK_LITERALQQ ], -1,
- makeLiteralExpr ],
-
- [ XPathNumber, [ TOK_NUMBER ], -1,
- makeNumberExpr ],
-
- [ XPathVariableReference, [ TOK_DOLLAR, TOK_QNAME ], 200,
- makeVariableReference ]
- ];
-
-// That function computes some optimizations of the above data
-// structures and will be called right here. It merely takes the
-// counter variables out of the global scope.
-
-var xpathRules = [];
-
-function xpathParseInit() {
- if (xpathRules.length) {
- return;
- }
-
- // Some simple optimizations for the xpath expression parser: sort
- // grammar rules descending by length, so that the longest match is
- // first found.
-
- xpathGrammarRules.sort(function(a,b) {
- var la = a[1].length;
- var lb = b[1].length;
- if (la < lb) {
- return 1;
- } else if (la > lb) {
- return -1;
- } else {
- return 0;
- }
- });
-
- var k = 1;
- for (var i = 0; i < xpathNonTerminals.length; ++i) {
- xpathNonTerminals[i].key = k++;
- }
-
- for (i = 0; i < xpathTokenRules.length; ++i) {
- xpathTokenRules[i].key = k++;
- }
-
- Log.write('XPath parse INIT: ' + k + ' rules');
-
- // Another slight optimization: sort the rules into bins according
- // to the last element (observing quantifiers), so we can restrict
- // the match against the stack to the subest of rules that match the
- // top of the stack.
- //
- // TODO(mesch): What we actually want is to compute states as in
- // bison, so that we don't have to do any explicit and iterated
- // match against the stack.
-
- function push_(array, position, element) {
- if (!array[position]) {
- array[position] = [];
- }
- array[position].push(element);
- }
-
- for (i = 0; i < xpathGrammarRules.length; ++i) {
- var rule = xpathGrammarRules[i];
- var pattern = rule[1];
-
- for (var j = pattern.length - 1; j >= 0; --j) {
- if (pattern[j] == Q_1M) {
- push_(xpathRules, pattern[j-1].key, rule);
- break;
-
- } else if (pattern[j] == Q_MM || pattern[j] == Q_01) {
- push_(xpathRules, pattern[j-1].key, rule);
- --j;
-
- } else {
- push_(xpathRules, pattern[j].key, rule);
- break;
- }
- }
- }
-
- Log.write('XPath parse INIT: ' + xpathRules.length + ' rule bins');
-
- var sum = 0;
- mapExec(xpathRules, function(i) {
- if (i) {
- sum += i.length;
- }
- });
-
- Log.write('XPath parse INIT: ' + (sum / xpathRules.length) + ' average bin size');
-}
-
-// Local utility functions that are used by the lexer or parser.
-
-function xpathCollectDescendants(nodelist, node) {
- for (var n = node.firstChild; n; n = n.nextSibling) {
- nodelist.push(n);
- arguments.callee(nodelist, n);
- }
-}
-
-function xpathCollectDescendantsReverse(nodelist, node) {
- for (var n = node.lastChild; n; n = n.previousSibling) {
- nodelist.push(n);
- arguments.callee(nodelist, n);
- }
-}
-
-
-// The entry point for the library: match an expression against a DOM
-// node. Returns an XPath value.
-function xpathDomEval(expr, node) {
- var expr1 = xpathParse(expr);
- var ret = expr1.evaluate(new ExprContext(node));
- return ret;
-}
-
-// Utility function to sort a list of nodes. Used by xsltSort() and
-// nxslSelect().
-function xpathSort(input, sort) {
- if (sort.length == 0) {
- return;
- }
-
- var sortlist = [];
-
- for (var i = 0; i < input.nodelist.length; ++i) {
- var node = input.nodelist[i];
- var sortitem = { node: node, key: [] };
- var context = input.clone(node, 0, [ node ]);
-
- for (var j = 0; j < sort.length; ++j) {
- var s = sort[j];
- var value = s.expr.evaluate(context);
-
- var evalue;
- if (s.type == 'text') {
- evalue = value.stringValue();
- } else if (s.type == 'number') {
- evalue = value.numberValue();
- }
- sortitem.key.push({ value: evalue, order: s.order });
- }
-
- // Make the sort stable by adding a lowest priority sort by
- // id. This is very convenient and furthermore required by the
- // spec ([XSLT] - Section 10 Sorting).
- sortitem.key.push({ value: i, order: 'ascending' });
-
- sortlist.push(sortitem);
- }
-
- sortlist.sort(xpathSortByKey);
-
- var nodes = [];
- for (var i = 0; i < sortlist.length; ++i) {
- nodes.push(sortlist[i].node);
- }
- input.nodelist = nodes;
- input.setNode(nodes[0], 0);
-}
-
-
-// Sorts by all order criteria defined. According to the JavaScript
-// spec ([ECMA] Section 11.8.5), the compare operators compare strings
-// as strings and numbers as numbers.
-//
-// NOTE: In browsers which do not follow the spec, this breaks only in
-// the case that numbers should be sorted as strings, which is very
-// uncommon.
-
-function xpathSortByKey(v1, v2) {
- // NOTE: Sort key vectors of different length never occur in
- // xsltSort.
-
- for (var i = 0; i < v1.key.length; ++i) {
- var o = v1.key[i].order == 'descending' ? -1 : 1;
- if (v1.key[i].value > v2.key[i].value) {
- return +1 * o;
- } else if (v1.key[i].value < v2.key[i].value) {
- return -1 * o;
- }
- }
-
- return 0;
-}
diff --git a/tests/FunctionalTests/selenium/php/TestRunner.php b/tests/FunctionalTests/selenium/php/TestRunner.php deleted file mode 100644 index 9bb5ada3..00000000 --- a/tests/FunctionalTests/selenium/php/TestRunner.php +++ /dev/null @@ -1,170 +0,0 @@ - -<html> - -<head> -<HTA:APPLICATION ID="SeleniumHTARunner" APPLICATIONNAME="Selenium" > -<!-- the previous line is only relevant if you rename this - file to "TestRunner.hta" --> - -<!-- The copyright notice and other comments have been moved to after the HTA declaration, - to work-around a bug in IE on Win2K whereby the HTA application doesn't function correctly --> -<!-- -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. ---> -<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" /> - -<title>Selenium Functional Test Runner</title> -<link rel="stylesheet" type="text/css" href="<?php echo $base_dir; ?>core/selenium.css" /> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-browserdetect.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-browserbot.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/prototype-1.4.0.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/find_matching_child.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-api.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-commandhandlers.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-executionloop.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-testrunner.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-logging.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-version.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/htmlutils.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/xpath/misc.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/xpath/dom.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/xpath/xpath.js"></script> -<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>prado-functional-test.js"></script> -<script language="JavaScript" type="text/javascript"> - function openDomViewer() { - var autFrame = document.getElementById('myiframe'); - var autFrameDocument = getIframeDocument(autFrame); - this.rootDocument = autFrameDocument; - var domViewer = window.open('<?php echo $base_dir; ?>core/domviewer/domviewer.html'); - return false; - } - - Logger.prototype.openLogWindow = function() - { - this.logWindow = window.open( - "<?php echo $base_dir; ?>core/SeleniumLog.html", "SeleniumLog", - "width=600,height=250,bottom=0,right=0,status,scrollbars,resizable" - ); - return this.logWindow; - } - - var post_results_to = "<?php echo $driver; ?>"; - -</script> -</head> - -<body onLoad="start();"> - - <table class="layout"> - <form action="" name="controlPanel"> - - <!-- Suite, Test, Control Panel --> - - <tr class="selenium"> - <td width="25%" height="30%" ><iframe name="testSuiteFrame" id="testSuiteFrame" src="<?php echo $driver; ?>?testSuites" application="yes"></iframe></td> - <td width="50%" height="30%" ><iframe name="testFrame" id="testFrame" application="yes"></iframe></td> - - <td width="25%"> - <table class="layout"> - <tr class="selenium"> - <th width="25%" height="1" class="header"> - <h1><a href="http://selenium.thoughtworks.com" title="The Selenium Project">Selenium</a> TestRunner</h1> - </th> - </tr> - <tr> - <td width="25%" height="30%" id="controlPanel"> - - <fieldset> - <legend>Execute Tests</legend> - - <div> - <input id="modeRun" type="radio" name="runMode" value="0" checked="checked"/><label for="modeRun">Run</label> - <input id="modeWalk" type="radio" name="runMode" value="500" /><label for="modeWalk">Walk</label> - <input id="modeStep" type="radio" name="runMode" value="-1" /><label for="modeStep">Step</label> - </div> - - <div> - <button type="button" id="runSuite" onClick="startTestSuite();" - title="Run the entire Test-Suite"> - <strong>All</strong> - </button> - <button type="button" id="runTest" onClick="runSingleTest();" - title="Run the current Test"> - <em>Selected</em> - </button> - <button type="button" id="continueTest" disabled="disabled" - title="Continue the Test"> - Continue - </button> - </div> - - </fieldset> - - <table id="stats" align="center"> - <tr> - <td colspan="2" align="right">Elapsed:</td> - <td id="elapsedTime" colspan="2">00.00</td> - </tr> - <tr> - <th colspan="2">Tests</th> - <th colspan="2">Commands</th> - </tr> - <tr> - <td class="count" id="testRuns">0</td> - <td>run</td> - <td class="count" id="commandPasses">0</td> - <td>passed</td> - </tr> - <tr> - <td class="count" id="testFailures">0</td> - <td>failed</td> - <td class="count" id="commandFailures">0</td> - <td>failed</td> - </tr> - <tr> - <td colspan="2"></td> - <td class="count" id="commandErrors">0</td> - <td>incomplete</td> - </tr> - </table> - - <fieldset> - <legend>Tools</legend> - - <button type="button" id="domViewer1" onClick="openDomViewer();"> - View DOM - </button> - <button type="button" onClick="LOG.show();"> - Show Log - </button> - - </fieldset> - - </td> - </tr> - </table> - </td> - </tr> - - <!-- AUT --> - - <tr> - <td colspan="3" height="70%"><iframe name="myiframe" id="myiframe" src="<?php echo $base_dir; ?>core/TestRunner-splash.html"></iframe></td> - </tr> - </form> - </table> - -</body> -</html>
\ No newline at end of file diff --git a/tests/FunctionalTests/selenium/php/results.php b/tests/FunctionalTests/selenium/php/results.php deleted file mode 100644 index 77dab43b..00000000 --- a/tests/FunctionalTests/selenium/php/results.php +++ /dev/null @@ -1,160 +0,0 @@ -<?php - -class SeleniumTestCaseResult -{ - public $name; - public $commands = array(); - public $result = 'passed'; - public $failures = array(); -} - -class SeleniumTestResult -{ - public $result = 'passed'; - public $totalTime = 0; - public $numTestPasses = 0; - public $numTestFailures = 0; - public $numCommandPasses = 0; - public $numCommandFailures = 0; - public $numCommandErrors = 0; - public $suites = array(); - public $browser = ''; - public $date; - - public function __construct() - { - $this->parse_data(); - $this->browser = $_SERVER['HTTP_USER_AGENT']; - $this->date = time(); - } - - protected function parse_data() - { - $this->result = $_POST['result']; // failed || passed - $this->totalTime = $_POST['totalTime']; - $this->numTestPasses = $_POST['numTestPasses']; - $this->numTestFailures = $_POST['numTestFailures']; - $this->numCommandPasses = $_POST['numCommandPasses']; - $this->numCommandFailures = $_POST['numCommandFailures']; - $this->numCommandErrors = $_POST['numCommandErrors']; - - foreach($_POST['tests'] as $test) - { - $case = new SeleniumTestCaseResult(); - $case->name = $test['testcase']; - $case->commands = $test['commands']; - for($i = 0; $i < count($case->commands); $i++) - { - //$trace = $case->commands[$i]['trace']; - //$trace = html_entity_decode($trace); - //$case->commands[$i]['trace'] = @unserialize($trace); - if($case->commands[$i]['result'] == 'failed') - { - $case->result = 'failed'; - array_push($case->failures, $case->commands[$i]); - } - } - - $this->suites[$case->name] = $case; - } - - } -} - -class SeleniumHtmlReporter -{ - protected $test; - - public function __construct($result) - { - $this->test = $result; - } - - protected function renderHeader() - { - $contents = <<<EOD -<html> -<head> -<title>Functional Test Results</title> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> -<style type="text/css"> -body {font-family:"Verdana";font-weight:normal;color:black;background-color:white;} -.failed { background-color: red; } .error0 { background-color: lightgray; } -.info { padding: 0.5em; margin-top: 1em; color: white; } -.passed { background-color: green; } -.error_case div { padding: 0.3em 0.2em; margin: 0.5em 0; } -.error_msg { padding: 0.5em; border-bottom:1px solid #ccc; } -.msg { color:#c00; } -.function { font-family:"Lucida Console";color: gray;} -.file { border-bottom: 1px dashed gray; } -.env { color: gray; font-size:10pt; padding: 0.5em; } -.odd { background-color: #fee; } -</style> -</head> -<body> -EOD; - return $contents; - } - - public function render() - { - echo $this->renderHeader(); - echo $this->renderBody(); - echo $this->renderFooter(); - } - - protected function renderBody() - { - /* SeleniumTestResult */ - $test = $this->test; - $total = count($test->suites); - $date = @strftime('%Y-%m-%d %H:%M',$test->date); -$contents = <<<EOD -<h1 class="suite">Functional Test Results</h1> -<div class="info {$test->result}"> - <strong>{$total}</strong> test cases completed, - <strong>{$test->numTestPasses}</strong> passes - ({$test->numCommandPasses} commands), and - <strong>{$test->numTestFailures}</strong> fails - ({$test->numCommandErrors} commands). -</div> -<div class="env"> - {$date}, {$test->browser} -</div> -EOD; - $count = 1; - foreach($test->suites as $suite) - { - foreach($suite->failures as $error) - $contents .= $this->getErrorMsg($suite, $error, $count++); - } - - return $contents; - } - - - protected function getErrorMsg($suite, $info, $count) - { - $parity = $count%2==0 ? 'even' : 'odd'; - $command = explode("|",$info['command']); -$msg = <<<EOD - <div class="error_msg {$parity}"> - <strong>#{$count}.</strong> - "<span class="msg">{$info['msg']}</span>" in - <span class="function"> - {$suite->name}::{$command[1]}('{$command[2]}'); - </span> - </div> -EOD; - - return $msg; - } - - protected function renderFooter() - { - return "</body></html>"; - } -} - - -?>
\ No newline at end of file diff --git a/tests/FunctionalTests/selenium/php/selenium.php b/tests/FunctionalTests/selenium/php/selenium.php deleted file mode 100644 index 960791b8..00000000 --- a/tests/FunctionalTests/selenium/php/selenium.php +++ /dev/null @@ -1,486 +0,0 @@ -<?php -/** - * Selenium PHP driver. Saves the test command in a "out" queue (in session), - * and for each selenese request, remove the first comand from the "out" queue - * and push the results into the "in" queque (also in session). When "out" queque - * is empty, write the results to disk. - * - * Usage: See ../../example.php - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the BSD License. - * - * Copyright(c) 2004 by Wei Zhuo. All rights reserved. - * - * To contact the author write to {@link mailto:weizhuo[at]gmail[dot]com Wei Zhuo} - * The latest version of PRADO can be obtained from: - * {@link http://prado.sourceforge.net/} - * - * @author Wei Zhuo <weizhuo[at]gmail[dot]com> - * @version $Revision: 1.66 $ $Date: Wed Nov 02 10:13:17 EST 2005 10:13:17 $ - * @package Prado.tests - */ - -/** - * Selenium automatic client runner, - * - * @author Wei Zhuo<weizhuo[at]gmail[dot]com> - * @version $Revision: 1.66 $ $Date: Fri Nov 04 13:20:12 EST 2005 13:20:12 $ - * @package Prado.tests - */ - -require_once(dirname(__FILE__).'/results.php'); - -class SeleniumTestRunner -{ - protected $driver; - protected $base_dir = ''; - - public function __construct($driver=null, $base_dir='../javascript/') - { - if(is_null($driver) && !(php_sapi_name() == 'cli')) - $driver = $_SERVER['SCRIPT_NAME']; - $this->driver = $driver; - $this->base_dir = $base_dir; - } - - public function render() - { - if((php_sapi_name() == 'cli')) return; - $file = dirname(__FILE__).'/TestRunner.php'; - $driver = $this->driver; - $base_dir = $this->base_dir; - include($file); - } - - public function getDriver() - { - return $this->driver; - } -} - -class SeleniumTestStorage -{ - protected $outputs = array(); - protected $tests = array(); - - public function getTests() - { - return $this->tests; - } - - public function addCommand($test_case_id, $command) - { - $data = array($test_case_id, $command); - array_push($this->outputs, $data); - } - - public function getCommand() - { - return array_shift($this->outputs); - } - - public function addTestCase($command, $trace_details, $test_name, $test_suite) - { - $data = array(0, 0, $command, "", $trace_details, $test_name, $test_suite); - array_push($this->tests, $data); - } -} - -class SeleneseInterpreter -{ - protected $storage; - protected $tracer; - - public function __construct($storage, $tracer) - { - $this->storage = $storage; - $this->tracer = $tracer; - } - - public function getTests() - { - return $this->storage->getTests(); - } - - public function getCommand() - { - $command = $this->storage->getCommand(); - return empty($command) ? "|testComplete|||" : "{$command[1]}<{$command[0]}>"; - } - - public function __call($func, $args) - { - if($func{0} == '_') return; - - $ID = isset($args[0]) ? $args[0] : ""; - $value = isset($args[1]) ? $args[1] : ""; - if(strpos(strtolower($func),'htmlpresent') || strpos(strtolower($func),'htmlnotpresent')) - $ID = htmlspecialchars($ID); - $command = array($func, $ID, $value); - $trace = debug_backtrace(); - - if(is_int(strpos(strtolower($func), 'visible'))) - $this->addCommand(array('pause','500',''),$trace); - - return $this->addCommand($command, $trace); - } - - protected function addCommand($command, $trace) - { - list($trace, $test, $suite) = $this->tracer->getTrace($trace); - $test_id = $this->storage->addTestCase($command, $trace, $test, $suite); - $this->storage->addCommand($test_id, $command); - } -} - -class SeleniumTestTrace -{ - protected $root; - - public function __construct($root) - { - $this->root = $root; - } - - public function getTrace($trace) - { - $group = array_pop($trace); - $info = $trace[3]; - $test = $group['args'][0]->getTestList(); - $i = count($test); - $name = $test[$i-2].'::'.$test[$i-1]; - $suite = $test[0]; - unset($info['object']); - /* - for($i = 0; $i < count($info['args']); $i++) - { - if($info['args'][$i] instanceof TControl) - $info['args'][$i] = $info['args'][$i]->ClientID; - }*/ - $file = str_replace($this->root, '', $info['file']); - $info['file'] = substr($file, 1); - return array($info, $name, $suite); - } -} - -class SimpleSeleniumProxyServer// extends SeleniumProxyServer -{ - protected $runner; - protected $int; - protected $result_file; - - public function __construct($runner, $int, $result_file) - { - $this->int = $int; - $this->runner = $runner; - $this->result_file = $result_file; - } - - public function proxy() - { - return $this->int; - } - - - public static function getInstance($root='/', $result_file='results.dat', $base_dir='selenium/') - { - static $instance; - if(!isset($instance)) - { - $storage = new SeleniumTestStorage(); - $tracer = new SeleniumTestTrace($root); - $interpreter = new SeleneseInterpreter($storage, $tracer); - $runner = new SeleniumTestRunner(null, $base_dir); - $instance = new SimpleSeleniumProxyServer($runner, $interpreter, $result_file); - } - $instance->serveResults(); - return $instance; - } - - public function handleRequest() - { - $client = new SeleniumTestRunnerServer($this->int, $this->runner); - $client->serve(); - return true; - } - - public function serveResults() - { - $result = null; - - if(isset($_POST['result'])) - { - $result = new SeleniumTestResult(); - file_put_contents($this->result_file, serialize($result)); - } - else if(isset($_GET['results'])) - { - if(is_file($this->result_file)) - $result = unserialize(file_get_contents($this->result_file)); - } - if(!is_null($result)) - { - $reporter = new SeleniumHtmlReporter($result); - $reporter->render(); - exit(); - } - } - -} - -class SeleniumTestSuiteWriter -{ - protected $suites; - protected $name; - protected $runner; - - function __construct($suites, $name, $runner) - { - $this->suites = $suites; - $this->name = $name; - $this->runner = $runner; - - } - - protected function renderHeader() - { - $contents = <<<EOD -<html> -<head> -<meta content="text/html; charset=UTF-8" http-equiv="content-type"> -<title>Test Suite</title> - -</head> - -<body> - -<table cellpadding="1" - cellspacing="1" - border="1"> - <tbody> - <tr><td><b>{$this->name}</b></td></tr> -EOD; - return $contents; - } - - public function render() - { - echo $this->renderHeader(); - foreach($this->suites as $name => $suite) - { - $file = $suite[0]['trace']['file']; - $file = strtr($file,'\\','/'); - $url = $this->runner->getDriver()."?case={$name}&file={$file}"; - echo "<tr>\n"; - echo "<td><a href=\"{$url}\">{$name}</a></td>\n"; - echo "</tr>\n"; - } - echo $this->renderFooter(); - } - - protected function getJsTraceInfo() - { - $contents = "var prado_trace = {};\n"; - foreach($this->suites as $name => $suite) - { - $name = $name; - $contents .= "prado_trace['{$name}'] = ["; - $cases = array(); - foreach($suite as $testcase) - $cases[] = "'".addslashes(htmlspecialchars(serialize($testcase['trace'])))."'"; - $contents .= implode(",\n", $cases)."];\n\n"; - } - return $contents; - } - - protected function renderFooter() - { - $trace = '';//$this->getJsTraceInfo(); - $contents = <<<EOD - </tbody> - </table> - <script type="text/javascript"> - /*<![CDATA[*/ - $trace - /*]]>*/ - </script> -</body> -</html> -EOD; - return $contents; - } -} - -class SeleniumTestCaseWriter -{ - protected $case; - protected $tests; - - function __construct($case, $tests) - { - $this->case = $case; - $this->tests = $tests; - } - - protected function renderHeader() - { - $contents = <<<EOD -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> -<title>{$this->case}</title> - <meta content="text/html; charset=UTF-8" http-equiv="content-type"> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1" id=TABLE1> - <tbody> - <tr> - <td rowspan="1" colspan="3"><strong>{$this->case}</strong></td> - </tr> -EOD; - return $contents; - } - - public function render() - { - echo $this->renderHeader(); - foreach($this->tests as $test) - { - $t = $test['test']; - if($t[0] == "open") - $t[1] = "<a href=\"{$t[1]}\" target=\"_blank\">{$t[1]}</a>"; - echo "<tr>\n"; - echo "<td>{$t[0]}</td>\n"; - echo "<td>{$t[1]}</td>\n"; - echo "<td>{$t[2]}</td>\n"; - echo "</tr>\n"; - } - echo $this->renderFooter(); - } - - protected function renderFooter() - { - $contents = <<<EOD - </tbody> -</table> -</body> -</html> -EOD; - return $contents; - } -} - -class SeleniumTestRunnerServer -{ - protected $cases = array(); - protected $trace = array(); - protected $name; - protected $runner; - - public function __construct($int, $runner) - { - $this->runner = $runner; - $this->initialize($int); - } - - protected function initialize($int) - { - foreach($int->getTests() as $command) - { - $case = $command[5]; - $this->cases[$case][] = - array('test' => $command[2], 'trace' => $command[4]); - if(is_null($this->name)) - $this->name = $command[6]; - } - } - - function serve() - { - if($this->isTestSuiteRequest()) - { - $testSuite = new SeleniumTestSuiteWriter($this->cases, - $this->name, $this->runner); - $testSuite->render(); - } - else if($this->isTestCaseRequest()) - { - if(($case = $this->getTestCaseRequest()) !== false) - { - - $testCase = new SeleniumTestCaseWriter($case, $this->getTestCase()); - $testCase->render(); - } - } - else - { - $this->runner->render(); - } - } - - protected function isTestSuiteRequest() - { - return isset($_GET['testSuites']); - } - - protected function isTestCaseRequest() - { - return isset($_GET['case']); - } - - public function isClientRequest() - { - return !$this->isTestSuiteRequest() && !$this->isTestCaseRequest(); - } - - protected function getTestCaseRequest() - { - $case = $_GET['case']; - if(isset($this->cases[$case])) - return $case; - else return false; - } - - protected function getTestCase() - { - $case = $_GET['case']; - if(isset($this->cases[$case])) - return $this->cases[$case]; - else - return array(); - } -} - - -class SeleniumTestCase extends UnitTestCase -{ - protected $selenium; - protected $Page; - - function __construct() - { - $server = SimpleSeleniumProxyServer::getInstance(); - if(!is_null($server)) - $this->selenium = $server->proxy(); - parent::__construct(); - } - - function getPage($class) - { - $info = new ReflectionClass($class); - return Prado::getApplication()->getTestPage($info->getFileName()); - } - - function __call($func, $args) - { - if(count($args) == 0) - return $this->selenium->{$func}(); - else if (count($args) == 1) - return $this->selenium->{$func}($args[0]); - else if (count($args) == 2) - return $this->selenium->{$func}($args[0], $args[1]); - } -} - -?>
\ No newline at end of file diff --git a/tests/FunctionalTests/selenium/prado-functional-test.js b/tests/FunctionalTests/selenium/prado-functional-test.js deleted file mode 100644 index 306f6a74..00000000 --- a/tests/FunctionalTests/selenium/prado-functional-test.js +++ /dev/null @@ -1,247 +0,0 @@ - -/** - * Override selenium implementation. - */ -Selenium.prototype.getAttribute = function(target) { - return this.page().findAttribute(target); -}; - - -/** - * Override selenium implementation. - */ -Selenium.prototype.isVisible = function(locator) { - var element; - element = this.page().findElement(locator); - - if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - var visibility = element.style["visibility"]; - else - var visibility = this.findEffectiveStyleProperty(element, "visibility"); - - var _isDisplayed = this._isDisplayed(element); - return (visibility != "hidden" && _isDisplayed); -}; - - -/** - * Override selenium implementation. - */ -Selenium.prototype._isDisplayed = function(element) { - if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - var display = element.style["display"]; - else - var display = this.findEffectiveStyleProperty(element, "display"); - if (display == "none") return false; - if (element.parentNode.style) { - return this._isDisplayed(element.parentNode); - } - return true; -}; - -Selenium.prototype.assertEmptySelection = function(selectLocator, optionLocator) -{ - /** - * Verifies that the selected option of a drop-down satisfies the optionSpecifier. - * - * <p>See the select command for more information about option locators.</p> - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @param optionLocator an option locator, typically just an option label (e.g. "John Smith") - */ - var element = this.page().findElement(selectLocator); - var locator = this.optionLocatorFactory.fromLocatorString(optionLocator); - return element.selectedIndex == -1; -} - -function runNextTest() { - if (!runAllTests) - return; - - suiteTable = getIframeDocument(getSuiteFrame()).getElementsByTagName("table")[0]; - - // Do not change the row color of the first row - if (currentRowInSuite > 0) { - // Provide test-status feedback - if (testFailed) { - setCellColor(suiteTable.rows, currentRowInSuite, 0, failColor); - } else { - setCellColor(suiteTable.rows, currentRowInSuite, 0, passColor); - } - - // Set the results from the previous test run - setResultsData(suiteTable, currentRowInSuite); - } - - currentRowInSuite++; - - // If we are done with all of the tests, set the title bar as pass or fail - if (currentRowInSuite >= suiteTable.rows.length) { - if (suiteFailed) { - setCellColor(suiteTable.rows, 0, 0, failColor); - } else { - setCellColor(suiteTable.rows, 0, 0, passColor); - } - - LOG.warn("next? ", "warn"); - // If this is an automated run (i.e., build script), then submit - // the test results by posting to a form - - postTestResults(suiteFailed, suiteTable); - } - - else { - // Make the current row blue - setCellColor(suiteTable.rows, currentRowInSuite, 0, workingColor); - - testLink = suiteTable.rows[currentRowInSuite].cells[0].getElementsByTagName("a")[0]; - testLink.focus(); - - var testFrame = getTestFrame(); - addLoadListener(testFrame, startTest); - - selenium.browserbot.setIFrameLocation(testFrame, testLink.href); - } -} - -// Post the results to a servlet, CGI-script, etc. The URL of the -// results-handler defaults to "/postResults", but an alternative location -// can be specified by providing a "resultsUrl" query parameter. -// -// Parameters passed to the results-handler 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"); - document.body.appendChild(form); - - form.id = "resultsForm"; - form.method="post"; - form.target="myiframe"; - - var resultsUrl = post_results_to; - if (!resultsUrl) { - resultsUrl = "./results.php"; - } - - var actionAndParameters = resultsUrl.split('?',2); - form.action = actionAndParameters[0]; - LOG.warn(form.action) - var resultsUrlQueryString = actionAndParameters[1]; - - form.createHiddenField = function(name, value) { - input = document.createElement("input"); - input.type = "hidden"; - input.name = name; - input.value = value; - this.appendChild(input); - }; - - if (resultsUrlQueryString) { - var clauses = resultsUrlQueryString.split('&'); - for (var i = 0; i < clauses.length; i++) { - var keyValuePair = clauses[i].split('=',2); - var key = unescape(keyValuePair[0]); - var value = unescape(keyValuePair[1]); - form.createHiddenField(key, value); - } - } - - form.createHiddenField("result", suiteFailed == true ? "failed" : "passed"); - - form.createHiddenField("totalTime", Math.floor((currentTime - startTime) / 1000)); - form.createHiddenField("numTestPasses", numTestPasses); - form.createHiddenField("numTestFailures", numTestFailures); - form.createHiddenField("numCommandPasses", numCommandPasses); - form.createHiddenField("numCommandFailures", numCommandFailures); - form.createHiddenField("numCommandErrors", numCommandErrors); - - // 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) { - var resultCell = suiteTable.rows[rowNum].cells[1]; - parse_resultCell(resultCell,rowNum,form); - //form.createHiddenField("tests[]", resultCell.innerHTML); - // remove the resultCell, so it's not included in the suite HTML - //resultCell.parentNode.removeChild(resultCell); - } - } - - // Add HTML for the suite itself - //form.createHiddenField("suite", suiteTable.parentNode.innerHTML); - - form.submit(); - document.body.removeChild(form); -} - -function parse_resultCell(resultCell,rowNum,form) -{ - var div = resultCell.childNodes[0]; - var table; - for(var i = 0; i<div.childNodes.length; i++) - { - if(div.childNodes[i].nodeName.toLowerCase() == 'table') - table = div.childNodes[i]; - } - //LOG.info(div.innerHTML); - var testname = table.rows[0].cells[0].firstChild.innerHTML; - var resultColor = get_color_status(table.rows[0]); - - form.createHiddenField("tests["+rowNum+"][testcase]",testname); - - //var trace = window.testSuiteFrame.prado_trace[testname]; - - for(var i = 1; i<table.rows.length; i++) - { - var msg = table.rows[i].getAttribute("title"); - var result = get_color_status(table.rows[i]); - var action = table.rows[i].cells[0].innerHTML; - var target = table.rows[i].cells[1].innerHTML; - var param = table.rows[i].cells[2].innerHTML; - var id = "tests["+rowNum+"][commands]["+(i-1)+"]"; - form.createHiddenField(id+"[command]", "|"+action+"|"+target+"|"+param+"|"); - form.createHiddenField(id+"[result]", result); - form.createHiddenField(id+"[msg]", msg); - //form.createHiddenField(id+"[trace]", trace[i-1]); - } -} - -function get_color_status(element) -{ - var color = element.getAttribute("bgcolor"); - if(color == passColor) return "passed"; - if(color == failColor) return "failed"; - if(color == doneColor) return "done"; - return ""; -} - - - - -Selenium.prototype.assertHTMLPresent = function(expectedValue) { - var actualValue = this.page().currentDocument.body.innerHTML; - if(actualValue.indexOf(expectedValue) >= 0) - return; - Assert.fail("Unable to find '"+(expectedValue.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "\""))+"' in document.body"); -}; - -Selenium.prototype.assertHTMLNotPresent = function(expectedValue) { - var actualValue = this.page().currentDocument.body.innerHTML; - if(actualValue.indexOf(expectedValue) < 0) - return; - Assert.fail("'"+(expectedValue.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "\""))+"' was found in document.body"); -};
\ No newline at end of file diff --git a/tests/FunctionalTests/tickets.php b/tests/FunctionalTests/tickets.php index 36511e73..ef8b52d6 100644 --- a/tests/FunctionalTests/tickets.php +++ b/tests/FunctionalTests/tickets.php @@ -1,8 +1,8 @@ <?php -require(dirname(__FILE__).'/PradoTester.php'); +require('../test_tools/functional_tests.php'); -$tester=new PradoTester(dirname(__FILE__).'/tickets/tests'); +$tester=new PradoFunctionalTester(dirname(__FILE__).'/tickets/tests'); $tester->run(new SimpleReporter()); ?>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/protected/pages/ClientScripTest.page b/tests/FunctionalTests/tickets/protected/pages/Ticket220.page index 8dbf7133..d5b6e182 100644 --- a/tests/FunctionalTests/features/protected/pages/ClientScripTest.page +++ b/tests/FunctionalTests/tickets/protected/pages/Ticket220.page @@ -1,13 +1,13 @@ <com:TContent ID="Content"> <h1>ClientScript Test</h1> - <com:TClientScript ScriptUrl=<%~ test.js %> ScriptPosition="Head"> + <com:TClientScript ScriptUrl=<%~ test.js %>> if(typeof(ClientScriptInfo) == "undefined") ClientScriptInfo = []; ClientScriptInfo.push("ok 3?") </com:TClientScript> - <com:TClientScript ScriptPosition="Begin"> + <com:TClientScript> if(typeof(ClientScriptInfo) == "undefined") ClientScriptInfo = []; ClientScriptInfo.push("ok 2!") @@ -16,12 +16,12 @@ <com:TLabel ID="label1" Text="Label 1" /> <input type="button" id="button1" value="update" /> - <com:TClientScript ScriptPosition="End" UsingPradoScripts="prado"> + <com:TClientScript UsingPradoScripts="prado"> Event.observe("button1", "click", function() { element = $("<%= $this->label1->ClientID %>"); if(element) - element.innerHTML = inspect(ClientScriptInfo); + element.innerHTML = "Label 1: "+inspect(ClientScriptInfo); else alert("failed"); }); diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket225.page b/tests/FunctionalTests/tickets/protected/pages/Ticket225.page new file mode 100644 index 00000000..362c4dce --- /dev/null +++ b/tests/FunctionalTests/tickets/protected/pages/Ticket225.page @@ -0,0 +1,14 @@ +<com:TContent ID="Content"> + <h1>RadioButton Group Tests</h1> + <com:TRadioButton ID="button1" Text="Button 1" GroupName="group1" /> + <com:TRadioButton ID="button2" Text="Button 2" GroupName="group1" /> + <com:TRadioButton ID="button3" Text="Button 3" GroupName="group1" /> + + <com:TRequiredFieldValidator id="validator1" + ControlToValidate="button1" + ErrorMessage="*" /> + + <com:TLabel ID="label1" Text="Label 1" /> + + <com:TButton ID="button4" Text="Show Groupings" OnClick="button4_Clicked" /> +</com:TContent>
\ No newline at end of file diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket225.php b/tests/FunctionalTests/tickets/protected/pages/Ticket225.php new file mode 100644 index 00000000..2cc3fc38 --- /dev/null +++ b/tests/FunctionalTests/tickets/protected/pages/Ticket225.php @@ -0,0 +1,19 @@ +<?php + +class Ticket225 extends TPage +{ + function button4_Clicked() + { + $this->label1->setText($this->getGroupIDs($this->button1)); + } + + private function getGroupIDs($radio) + { + $ids = ''; + foreach($radio->getRadioButtonsInGroup() as $control) + $ids .= " ".$control->getUniqueID(); + return $ids; + } +} + +?>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/protected/pages/test.js b/tests/FunctionalTests/tickets/protected/pages/test.js index e8e80b19..e8e80b19 100644 --- a/tests/FunctionalTests/features/protected/pages/test.js +++ b/tests/FunctionalTests/tickets/protected/pages/test.js diff --git a/tests/FunctionalTests/tickets/tests/Ticket220TestCase.php b/tests/FunctionalTests/tickets/tests/Ticket220TestCase.php new file mode 100644 index 00000000..0753f732 --- /dev/null +++ b/tests/FunctionalTests/tickets/tests/Ticket220TestCase.php @@ -0,0 +1,18 @@ +<?php + +class Ticket220TestCase extends SeleniumTestCase +{ + function test() + { + $base="ctl0_Content_"; + $this->open('tickets/index.php?page=Ticket220'); + $this->assertTextPresent('ClientScript Test'); + $this->assertText("{$base}label1", "Label 1"); + + $this->click("button1"); + $this->assertText("{$base}label1", 'Label 1: ["ok", "ok 3?", "ok 2!"]'); + $this->assertAlertNotPresent(); + } +} + +?>
\ No newline at end of file diff --git a/tests/FunctionalTests/tickets/tests/Ticket225TestCase.php b/tests/FunctionalTests/tickets/tests/Ticket225TestCase.php new file mode 100644 index 00000000..966e8383 --- /dev/null +++ b/tests/FunctionalTests/tickets/tests/Ticket225TestCase.php @@ -0,0 +1,24 @@ +<?php + +class Ticket225TestCase extends SeleniumTestCase +{ + function test() + { + $base="ctl0_Content_"; + $this->open('tickets/index.php?page=Ticket225'); + $this->assertTextPresent('RadioButton Group Tests'); + $this->assertText("{$base}label1", "Label 1"); + + $this->assertNotVisible("{$base}validator1"); + $this->click("{$base}button4"); + $this->assertVisible("{$base}validator1"); + + $this->click("{$base}button2"); + $this->clickAndWait("{$base}button4"); + + $this->assertText("{$base}label1", 'ctl0$Content$button1 ctl0$Content$button2 ctl0$Content$button3'); + $this->assertNotVisible("{$base}validator1"); + } +} + +?>
\ No newline at end of file diff --git a/tests/FunctionalTests/validators.php b/tests/FunctionalTests/validators.php index c86604c8..521cca56 100644 --- a/tests/FunctionalTests/validators.php +++ b/tests/FunctionalTests/validators.php @@ -1,8 +1,8 @@ <?php -require(dirname(__FILE__).'/PradoTester.php'); +require('../test_tools/functional_tests.php'); -$tester=new PradoTester(dirname(__FILE__).'/validators/tests'); +$tester=new PradoFunctionalTester(dirname(__FILE__).'/validators/tests'); $tester->run(new SimpleReporter()); ?>
\ No newline at end of file |