Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.405
diff -u -p -r1.405 bootstrap.inc
--- includes/bootstrap.inc	29 Jun 2010 18:50:36 -0000	1.405
+++ includes/bootstrap.inc	7 Jul 2010 11:53:36 -0000
@@ -2163,7 +2163,13 @@ function _drupal_bootstrap_database() {
   // running tests. However, for security reasons, it is imperative that we
   // validate we ourselves made the request.
   if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/^(simpletest\d+);/", $_SERVER['HTTP_USER_AGENT'], $matches)) {
-    if (!drupal_valid_test_ua($_SERVER['HTTP_USER_AGENT'])) {
+    $valid_hmac = drupal_valid_test_ua($_SERVER['HTTP_USER_AGENT']);
+  }
+  else if (isset($_COOKIE['simpletesthmac']) && preg_match("/^(simpletest\d+)____/", $_COOKIE['simpletesthmac'], $matches)) {
+    $valid_hmac = drupal_valid_test_cookie($_COOKIE['simpletesthmac']);
+  }
+  if (isset($valid_hmac)) {
+    if ($valid_hmac === FALSE) {
       header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
       exit;
     }
@@ -2279,13 +2285,48 @@ function drupal_generate_test_ua($prefix
     $filepath = DRUPAL_ROOT . '/includes/bootstrap.inc';
     $key = $drupal_hash_salt . filectime($filepath) . fileinode($filepath);
   }
-   // Generate a moderately secure HMAC based on the database credentials.
-   $salt = uniqid('', TRUE);
-   $check_string = $prefix . ';' . time() . ';' . $salt;
-   return  $check_string . ';' . drupal_hmac_base64($check_string, $key);
+  // Generate a moderately secure HMAC based on the database credentials.
+  $salt = uniqid('', TRUE);
+  $check_string = $prefix . ';' . time() . ';' . $salt;
+  return $check_string . ';' . drupal_hmac_base64($check_string, $key);
+}
+
+/**
+ * Validate the HMAC and timestamp of a cookie from simpletest.
+ */
+function drupal_valid_test_cookie($cookie) {
+  global $drupal_hash_salt;
+
+  list($prefix, $check_string, $hmac) = explode('____', $cookie);
+  // We use the salt from settings.php to make the HMAC key, since
+  // the database is not yet initialized and we can't access any Drupal variables.
+  // The file properties add more entropy not easily accessible to others.
+  $filepath = DRUPAL_ROOT . '/includes/bootstrap.inc';
+  $key = $drupal_hash_salt . filectime($filepath) . fileinode($filepath);
+  // The HMAC must match.
+  return $hmac == drupal_hmac_base64($check_string, $key);
 }
 
 /**
+ * Generate a cookiestring with a HMAC and timestamp for simpletest.
+ */
+function drupal_generate_test_cookie($prefix) {
+  global $drupal_hash_salt;
+  static $key;
+
+  if (!isset($key)) {
+    // We use the salt from settings.php to make the HMAC key, since
+    // the database is not yet initialized and we can't access any Drupal variables.
+    // The file properties add more entropy not easily accessible to others.
+    $filepath = DRUPAL_ROOT . '/includes/bootstrap.inc';
+    $key = $drupal_hash_salt . filectime($filepath) . fileinode($filepath);
+  }
+  // Generate a moderately secure HMAC based on the database credentials.
+  $salt = uniqid('', TRUE);
+  $check_string = md5($prefix . time() . $salt);
+  return 'simpletesthmac=' . $prefix . '____' . $check_string . '____' . drupal_hmac_base64($check_string, $key);
+}
+/**
  * Enables use of the theme system without requiring database access.
  *
  * Loads and initializes the theme system for site installs, updates and when
Index: modules/field_ui/field_ui.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.test,v
retrieving revision 1.18
diff -u -p -r1.18 field_ui.test
--- modules/field_ui/field_ui.test	27 Jun 2010 18:05:54 -0000	1.18
+++ modules/field_ui/field_ui.test	7 Jul 2010 11:53:37 -0000
@@ -398,3 +398,42 @@ class FieldUITestCase extends DrupalWebT
     $this->assertNoFieldByXPath('//table[@id="field-overview"]//span[@class="label-field"]', $label, t('Field does not appear in the overview page.'));
   }
 }
+
+/**
+ * Test the Field UI javascript.
+ */
+class FieldUiJavascriptTest extends DrupalSeleniumTestCase {
+
+  /**
+   * seleniumBrowserHost
+   * 
+   * @var string
+   */
+  protected $seleniumBrowserHost = 'drupal7.selenium';
+
+  /**
+   * seleniumHost 
+   * 
+   * @var string
+   */
+  protected $seleniumHost = 'selenium.server';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Field UI javascript tests',
+      'description' => 'Tests the javascript functionality of the Field UI.',
+      'group' => 'Field UI',
+    );
+  }
+
+  public function testFieldUiSelects() {
+    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types'));
+    $this->seleniumClient->open('user/login');
+    $this->seleniumClient->doCommand('type', array('edit-name', $admin_user->name));
+    $this->seleniumClient->doCommand('type', array('edit-pass', $admin_user->pass_raw));
+    $this->seleniumClient->doCommand('click', array('edit-submit'));
+    $this->seleniumClient->waitForPageToLoad(10000);
+    $this->assertTrue($this->seleniumClient->doCommand('assertTitle', array($admin_user->name . '*')), "We got logged in via Selenium RC");
+  }
+}
+
Index: modules/simpletest/drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v
retrieving revision 1.223
diff -u -p -r1.223 drupal_web_test_case.php
--- modules/simpletest/drupal_web_test_case.php	29 Jun 2010 18:24:10 -0000	1.223
+++ modules/simpletest/drupal_web_test_case.php	7 Jul 2010 11:53:39 -0000
@@ -3114,3 +3114,115 @@ function simpletest_verbose($message, $o
   }
   return FALSE;
 }
+
+require_once 'Testing/Selenium.php';
+
+class DrupalSeleniumTestCase extends DrupalWebTestCase {
+  
+  /**
+   * seleniumCookieName 
+   * 
+   * @var string
+   */
+  protected $seleniumCookie = '';
+
+  /**
+   * Selenium client instance.
+   * 
+   * @object Testing_Selenium
+   */
+  protected $seleniumClient;
+
+  /**
+   * browser 
+   * 
+   * @var string
+   */
+  protected $seleniumBrowser = 'firefox';
+
+  /**
+   * browserHost
+   * 
+   * @var string
+   */
+  protected $seleniumBrowserHost = '';
+
+  /**
+   * host 
+   * 
+   * @var string
+   */
+  protected $seleniumHost = 'localhost';
+
+  /**
+   * port 
+   * 
+   * @var int
+   */
+  protected $seleniumPort = 4444;
+
+  /**
+   * timeout 
+   * 
+   * @var int
+   */
+  protected $seleniumTimeout = 30000;
+
+  /**
+   * seleniumSessionId 
+   * 
+   * @var mixed
+   */
+  protected $seleniumSessionId = FALSE;
+
+  /**
+   * setUp 
+   * 
+   * @return void
+   */
+  protected function setUp() {
+    // Since this is a base class for many test cases, support the same
+    // flexibility that DrupalWebTestCase::setUp() has for the modules to be
+    // passed in as either an array or a variable number of string arguments.
+    $modules = func_get_args();
+    if (isset($modules[0]) && is_array($modules[0])) {
+      $modules = $modules[0];
+    }
+    parent::setUp($modules);
+
+    $this->seleniumClient = new DrupalSelenium(
+      $this->seleniumBrowser,
+      'http://' . $this->seleniumBrowserHost,
+      $this->seleniumHost,
+      $this->seleniumPort,
+      $this->seleniumTimeout
+    );
+    $this->seleniumSessionId = $this->seleniumClient->start();
+    $this->seleniumCookie = drupal_generate_test_cookie($this->databasePrefix);
+    $this->seleniumClient->open('/');
+    $this->seleniumClient->createCookie($this->seleniumCookie, 'path=/,max_age=100000,domain=.' . $this->seleniumBrowserHost);
+  }
+
+  protected function tearDown() {
+    $this->seleniumClient->stop();
+    $this->seleniumClient = NULL;
+    parent::tearDown();
+  }
+
+}
+
+class DrupalSelenium extends Testing_Selenium {
+
+  /**
+   * Overide so we can get at the return value.
+   * 
+   * @param mixed $command 
+   * @param array $args 
+   * @return string
+   */
+  public function doCommand($command, $args = array()) {
+    return parent::doCommand($command, $args);
+  }
+
+}
+
