#346095 by Damien Tournoud: Implements a test framework for AHAH replacement.

From: Damien Tournoud <damien@tournoud.net>


---

 modules/simpletest/drupal_web_test_case.php |  328 ++++++++++++++++++++++-----
 modules/simpletest/simpletest.test          |  102 ++++++++
 modules/simpletest/tests/common.test        |    4 
 modules/statistics/statistics.test          |    2 
 modules/system/system.test                  |    4 
 modules/taxonomy/taxonomy.test              |    4 
 modules/user/user.test                      |    8 -
 7 files changed, 383 insertions(+), 69 deletions(-)


diff --git modules/simpletest/drupal_web_test_case.php modules/simpletest/drupal_web_test_case.php
index 04ba135..cc59fe9 100644
--- modules/simpletest/drupal_web_test_case.php
+++ modules/simpletest/drupal_web_test_case.php
@@ -49,13 +49,31 @@ class DrupalWebTestCase {
   protected $plainTextContent;
 
   /**
-   * The parsed version of the page.
+   * The parsed version of the current page.
    *
    * @var SimpleXMLElement
    */
   protected $elements = NULL;
 
   /**
+   * The DOM version of the current page.
+   *
+   * Only generated when parse() is called in javascript mode.
+   *
+   * @var DOMDocument
+   */
+  protected $domElements = NULL;
+
+  /**
+   * The javascript settings parsed from the current page.
+   *
+   * Only generated when parse() is called in javascript mode.
+   *
+   * @var array
+   */
+  protected $javascriptSettings = array();
+
+  /**
    * Whether a user is logged in the internal browser.
    *
    * @var bool
@@ -947,16 +965,21 @@ class DrupalWebTestCase {
    * @param $curl_options
    *   Custom cURL options.
    * @return
-   *   Content returned from the exec.
+   *   Array containing two keys:
+   *     'content': the server response,
+   *     'url': the effective URL used, after redirects if any.
    */
   protected function curlExec($curl_options) {
     $this->curlInitialize();
     $url = empty($curl_options[CURLOPT_URL]) ? curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL) : $curl_options[CURLOPT_URL];
     curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options);
     $this->headers = array();
-    $this->drupalSetContent(curl_exec($this->curlHandle), curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL));
-    $this->assertTrue($this->content !== FALSE, t('!method to !url, response is !length bytes.', array('!method' => !empty($curl_options[CURLOPT_NOBODY]) ? 'HEAD' : (empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST'), '!url' => $url, '!length' => strlen($this->content))), t('Browser'));
-    return $this->drupalGetContent();
+    $response = array(
+      'content' => curl_exec($this->curlHandle),
+      'url' => curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL),
+    );
+    $this->assertTrue($response['content'] !== FALSE, t('!method to !url, response is !length bytes.', array('!method' => !empty($curl_options[CURLOPT_NOBODY]) ? 'HEAD' : (empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST'), '!url' => $url, '!length' => strlen($response['content']))), t('Browser'));
+    return $response;
   }
 
   /**
@@ -995,26 +1018,43 @@ class DrupalWebTestCase {
   /**
    * Parse content returned from curlExec using DOM and SimpleXML.
    *
+   * @param $javascript_mode
+   *   Also generate a DOM object in $this->domElements,
+   *   and parse javascript settings.
    * @return
    *   A SimpleXMLElement or FALSE on failure.
    */
-  protected function parse() {
-    if (!$this->elements) {
-      // DOM can load HTML soup. But, HTML soup can throw warnings, supress
-      // them.
+  protected function parse($javascript_mode = FALSE) {
+    if (!$this->elements || ($javascript_mode && !$this->domElements)) {
+      // DOM can load HTML soup but that can throw warnings, suppress them.
       @$htmlDom = DOMDocument::loadHTML($this->content);
       if ($htmlDom) {
         $this->pass(t('Valid HTML found on "@path"', array('@path' => $this->getUrl())), t('Browser'));
         // It's much easier to work with simplexml than DOM, luckily enough
         // we can just simply import our DOM tree.
         $this->elements = simplexml_import_dom($htmlDom);
+        if ($javascript_mode) {
+          // Save the DOM version, as we need it for replacements in drupalAHAH().
+          $this->domElements = $htmlDom;
+
+          // Parse javascript settings from the page.
+          $embed_prefix = preg_quote("\n<!--//--><![CDATA[//><!--\njQuery.extend(Drupal.settings, ", '@');
+          $embed_suffix = preg_quote(");\n//--><!]]>\n", '@');
+
+          foreach ($this->elements->xpath("//script[not(@src)]") as $element) {
+            $content = (string) $element;
+            if (preg_match('@' . $embed_prefix . '(.*)' . $embed_suffix .'@m', $content, $matches)) {
+              $this->javascriptSettings = array_merge($this->javascriptSettings, json_decode($matches[1], TRUE));
+            }
+          }
+        }
+      }
+      else {
+        $this->fail(t('Parsed page successfully.'), t('Browser'));
+        return FALSE;
       }
     }
-    if (!$this->elements) {
-      $this->fail(t('Parsed page successfully.'), t('Browser'));
-    }
-
-    return $this->elements;
+    return TRUE;
   }
 
   /**
@@ -1036,19 +1076,37 @@ class DrupalWebTestCase {
     // We re-using a CURL connection here. If that connection still has certain
     // options set, it might change the GET into a POST. Make sure we clear out
     // previous options.
-    $out = $this->curlExec(array(CURLOPT_HTTPGET => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_NOBODY => FALSE, CURLOPT_HTTPHEADER => $headers));
+    $response = $this->curlExec(array(CURLOPT_HTTPGET => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_NOBODY => FALSE, CURLOPT_HTTPHEADER => $headers));
+    $this->drupalSetResponse($response['content'], $response['url']);
     $this->refreshVariables(); // Ensure that any changes to variables in the other thread are picked up.
 
     // Replace original page output with new output from redirected page(s).
     if (($new = $this->checkForMetaRefresh())) {
       $out = $new;
     }
-    return $out;
+    return $response['content'];
   }
 
   /**
-   * Execute a POST request on a Drupal page.
-   * It will be done as usual POST request with SimpleBrowser.
+   * Execute a POST request on a Drupal page and load the result in the internal browser.
+   *
+   * This function performs a GET request on the page specified by $path (or
+   * simply uses the currently loaded page if NULL is passed as $path) and looks
+   * for a form that matches the fields passed in $edit and the name of the
+   * submit button passed in $submit. It completes the passed field values with
+   * the default values of the form and posts the result to the form action URL.
+   *
+   * Usage example:
+   *
+   * @code
+   *  $edit = array(
+   *    'name' => 'admin',
+   *    'pass' => 'mypass',
+   *  );
+   *  $this->drupalPost('user/login', $edit, t('Login'));
+   * @endcode
+   *
+   * @see DrupalWebTestCase::drupalPostDirect()
    *
    * @param $path
    *   Location of the post form. Either a Drupal path or an absolute path or
@@ -1081,7 +1139,7 @@ class DrupalWebTestCase {
    *   An array containing additional HTTP request headers, each formatted as
    *   "name: value".
    */
-  protected function drupalPost($path, $edit, $submit, array $options = array(), array $headers = array()) {
+  protected function drupalPost($path, array $edit, $submit, array $options = array(), array $headers = array()) {
     $submit_matches = FALSE;
     if (isset($path)) {
       $html = $this->drupalGet($path, $options);
@@ -1101,35 +1159,9 @@ class DrupalWebTestCase {
         // We post only if we managed to handle every field in edit and the
         // submit button matches.
         if (!$edit && $submit_matches) {
-          if ($upload) {
-            // TODO: cURL handles file uploads for us, but the implementation
-            // is broken. This is a less than elegant workaround. Alternatives
-            // are being explored at #253506.
-            foreach ($upload as $key => $file) {
-              $file = realpath($file);
-              if ($file && is_file($file)) {
-                $post[$key] = '@' . $file;
-              }
-            }
-          }
-          else {
-            foreach ($post as $key => $value) {
-              // Encode according to application/x-www-form-urlencoded
-              // Both names and values needs to be urlencoded, according to
-              // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
-              $post[$key] = urlencode($key) . '=' . urlencode($value);
-            }
-            $post = implode('&', $post);
-          }
-          $out = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => $post, CURLOPT_HTTPHEADER => $headers));
-          // Ensure that any changes to variables in the other thread are picked up.
-          $this->refreshVariables();
-
-          // Replace original page output with new output from redirected page(s).
-          if (($new = $this->checkForMetaRefresh())) {
-            $out = $new;
-          }
-          return $out;
+          $response = $this->drupalPostDirect($action, $post, $upload, $headers);
+          $this->drupalSetResponse($response['content'], $response['url']);
+          return $response['content'];
         }
       }
       // We have not found a form which contained all fields of $edit.
@@ -1142,21 +1174,101 @@ class DrupalWebTestCase {
   }
 
   /**
+   * Execute a direct POST request on a specific URL, and return the result.
+   *
+   * This function perform a simple POST request to the given URL, by-passing
+   * the internal browser. It can be used to post values without checking the
+   * validity of posted values against existing forms, for example, for
+   * simulating AHAH requests.
+   *
+   * Unlike drupalPost(), this function doesn't load the result in the internal
+   * browser.
+   *
+   * Usage example:
+   *
+   * @code
+   *   $post = array(
+   *      'form_id' => 'my form id',
+   *      'title' => $this->randomName(),
+   *      'choice[new:0][chtext]' => $this->randomName(),
+   *      'choice[new:1][chtext]' => $this->randomName(),
+   *   );
+   *   $response = $this->drupalPostDirect(url('poll/js', array('absolute' => TRUE)), $post);
+   * @endcode
+   *
+   * @see DrupalWebTestCase::drupalPost()
+   *
+   * @param $action
+   *   The URL to post to, or NULL to post to the current page.
+   * @param  $post
+   *   Field data in an assocative array. A checkbox can be set to TRUE to be
+   *   checked and FALSE to be unchecked. Note that when a form contains file 
+   *   upload fields, other fields cannot start with the '@' character.
+   *
+   *   Multiple select fields can be set using name[] and setting each of the
+   *   possible values. Example:
+   *   $edit = array();
+   *   $edit['name[]'] = array('value1', 'value2');
+   * @param $upload
+   *   An associative array of files to upload.
+   * @param $options
+   *   Options to be forwarded to url().
+   * @param $headers
+   *   An array containing additional HTTP request headers, each formatted as
+   *   "name: value".
+   * @return
+   *   The response array returned by the server, in the format returned by curlExec().
+   */
+  protected function drupalPostDirect($action, array $post, array $upload = array(), array $headers = array()) {
+    if ($upload) {
+      // TODO: cURL handles file uploads for us, but the implementation
+      // is broken. This is a less than elegant workaround. Alternatives
+      // are being explored at #253506.
+      foreach ($upload as $key => $file) {
+        $file = realpath($file);
+        if ($file && is_file($file)) {
+          $post[$key] = '@' . $file;
+        }
+      }
+    }
+    else {
+      foreach ($post as $key => $value) {
+        // Encode according to application/x-www-form-urlencoded
+        // Both names and values needs to be urlencoded, according to
+        // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
+        $post[$key] = urlencode($key) . '=' . urlencode($value);
+      }
+      $post = implode('&', $post);
+    }
+    $response = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => $post, CURLOPT_HTTPHEADER => $headers));
+    // Ensure that any changes to variables in the other thread are picked up.
+    $this->refreshVariables();
+
+    // Replace original page output with new output from redirected page(s).
+    if (($new_response = $this->checkForMetaRefresh())) {
+      $response = $new_response;
+    }
+    return $response;
+  }
+
+  /**
    * Check for meta refresh tag and if found call drupalGet() recursively. This
    * function looks for the http-equiv attribute to be set to "Refresh"
    * and is case-sensitive.
    *
    * @return
-   *   Either the new page content or FALSE.
+   *   Either the new response array or FALSE.
    */
   protected function checkForMetaRefresh() {
-    if ($this->drupalGetContent() != '' && $this->parse()) {
+    if ($this->parse()) {
       $refresh = $this->xpath('//meta[@http-equiv="Refresh"]');
       if (!empty($refresh)) {
         // Parse the content attribute of the meta tag for the format:
         // "[delay]: URL=[page_to_redirect_to]".
         if (preg_match('/\d+;\s*URL=(?P<url>.*)/i', $refresh[0]['content'], $match)) {
-          return $this->drupalGet($this->getAbsoluteUrl(decode_entities($match['url'])));
+          $response = $this->drupalGet($this->getAbsoluteUrl(decode_entities($match['url'])));
+          $this->drupalSetResponse($response['content'], $response['url']);
+          return $response;
         }
       }
     }
@@ -1164,6 +1276,99 @@ class DrupalWebTestCase {
   }
 
   /**
+   * Trigger an AHAH even on a given form element.
+   *
+   * @param $element_id
+   *   The ID of the form element to use.
+   * @return
+   *   TRUE on success, FALSE on failure.
+   */
+  protected function drupalAHAH($element_id) {
+    global $base_root;
+
+    if ($this->parse(TRUE)) {
+
+      if (isset($this->javascriptSettings['ahah'][$element_id])) {
+        $settings = $this->javascriptSettings['ahah'][$element_id];
+      }
+      else {
+        $this->fail("The element %element_id has no AHAH settings.", array('%element_id' => $element_id));
+      }
+
+      // Find the form containing the element and post it to the AHAH url.
+      $response = NULL;
+      foreach ($this->xpath('//form') as $form) {
+        if ($form->xpath(".//*[@id = '" . $element_id . "']")) {
+          // We set $post based on this form items.
+          $edit = $post = $upload = array();
+          $this->handleForm($post, $edit, $upload, NULL, $form);
+
+          // The URL in javascript settings is already includes $base_path.
+          $action_url = $base_root . $settings['url'];
+          $response = $this->drupalPostDirect($action_url, $post, $upload);
+        }
+      }
+
+      if (!$this->assertTrue($response, t("Found a form containing the %element_id element", array('%element_id' => $element_id)))) {
+        return FALSE;
+      }
+
+      // The response is generated by drupal_to_js: we need to undo some escaping.
+      $response['content'] = json_decode(str_replace(array('\x3c', '\x3e', '\x26'), array("<", ">", "&"), $response['content']));
+
+      if (!$this->assertTrue(!empty($response['content']->status), t("JSON status is TRUE."))) {
+        return FALSE;
+      }
+
+      if (!$this->assertTrue(!empty($response['content']->data), t("JSON contains a valid answer."))) {
+        return FALSE;
+      }
+
+      // Import the resulting HTML, the <div> wrapper is added by ahah.js.
+      // For some reason, importing a node doesn't work when this is loaded
+      // with DOMDocument::loadHTML().
+      $result = DOMDocument::loadXML('<div>' . $response['content']->data . '</div>');
+      $new_element = $this->domElements->importNode($result->firstChild, TRUE);
+
+      // Select the node.
+      $xpath = new DOMXPath($this->domElements);
+      $wrappers = $xpath->query("//*[@id = '" . $settings['wrapper'] . "']");
+
+      foreach ($wrappers as $wrapper) {
+        switch ($settings['method']) {
+          case 'replace':
+            // Empty the wrapper.
+            while ($wrapper->firstChild) {
+              $wrapper->removeChild($wrapper->firstChild);
+            }
+            // Append the new child.
+            $wrapper->appendChild($new_element);
+            break;
+          case 'after':
+            $wrapper->parentNode->insertBefore($new_element, $wrapper->nextSibling);
+            break;
+          case 'append':
+            $wrapper->appendChild($new_element);
+            break;
+          case 'before':
+            $wrapper->parentNode->insertBefore($new_element, $wrapper);
+            break;
+          case 'prepend':
+            $wrapper->insertBefore($new_element, $wrapper->firstChild);
+            break;
+        }
+
+      }
+
+      // Finally, replace the content in the browser.
+      $this->content = $this->domElements->saveHTML();
+      $this->elements = simplexml_import_dom($this->domElements);
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
    * Retrieves only the headers for a Drupal path or an absolute path.
    *
    * @param $path
@@ -1178,9 +1383,11 @@ class DrupalWebTestCase {
    */
   protected function drupalHead($path, array $options = array(), array $headers = array()) {
     $options['absolute'] = TRUE;
-    $out = $this->curlExec(array(CURLOPT_NOBODY => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_HTTPHEADER => $headers));
+    $response = $this->curlExec(array(CURLOPT_NOBODY => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_HTTPHEADER => $headers));
+    $this->drupalSetResponse($response['content'], $response['url']);
+
     $this->refreshVariables(); // Ensure that any changes to variables in the other thread are picked up.
-    return $out;
+    return $response['content'];
   }
 
   /**
@@ -1555,19 +1762,26 @@ class DrupalWebTestCase {
   }
 
   /**
-   * Sets the raw HTML content. This can be useful when a page has been fetched
-   * outside of the internal browser and assertions need to be made on the
-   * returned page.
+   * Load a response into the internal browser.
+   *
+   * This can be useful when a page has been fetched outside of the internal
+   * browser and assertions need to be made on the returned page.
    *
    * A good example would be when testing drupal_http_request(). After fetching
    * the page the content can be set and page elements can be checked to ensure
    * that the function worked properly.
+   *
+   * @param $content
+   *   The HTML content of the current page.
+   * @param $url
+   *   The effective URL of the current page, after following redirects if any.
    */
-  protected function drupalSetContent($content, $url = 'internal:') {
+  protected function drupalSetResponse($content, $url = 'internal:') {
     $this->content = $content;
     $this->url = $url;
     $this->plainTextContent = FALSE;
     $this->elements = FALSE;
+    $this->javascriptSettings = array();
   }
 
   /**
diff --git modules/simpletest/simpletest.test modules/simpletest/simpletest.test
index a3a4a0c..e8c91a9 100644
--- modules/simpletest/simpletest.test
+++ modules/simpletest/simpletest.test
@@ -1,7 +1,7 @@
 <?php
 // $Id: simpletest.test,v 1.13 2008-12-11 20:11:40 dries Exp $
 
-class SimpleTestTestCase extends DrupalWebTestCase {
+class SimpleTestFunctionalTest extends DrupalWebTestCase {
   /**
    * The results array that has been parsed by getTestResults().
    */
@@ -262,3 +262,103 @@ class SimpleTestTestCase extends DrupalWebTestCase {
     return preg_match("/^simpletest\d+/", $_SERVER['HTTP_USER_AGENT']);
   }
 }
+
+/**
+ * Test AHAH testing features of SimpleTest.
+ */
+class SimpleTestAHAHUnitTest extends DrupalWebTestCase {
+  public function getInfo() {
+    return array(
+      'name' => t('SimpleTest AHAH'),
+      'description' => t('Tests AHAH testing features of SimpleTest.'),
+      'group' => t('SimpleTest')
+    );
+  }
+
+  public function setUp() {
+    // Load the testing module.
+    parent::setUp('simpletest_test');
+  }
+
+  function depthFirstExplore(SimpleXMLElement $node, $depth = 0) {
+    $values = array();
+    // Insert the current element.
+    $values[] = array(
+      $node->getName(),
+      (string) $node,
+      $depth,
+    );
+    foreach ($node as $child_node) {
+      $values = array_merge($values, $this->depthFirstExplore($child_node, $depth + 1));
+    }
+    return $values;
+  }
+
+  /**
+   * Assert that the HTML node tree is equivalent to an expected description.
+   *
+   * @param $element_id
+   *   The ID of the element to assert.
+   * @param $expected_tree
+   *   The expected tree, in topological order (see testAHAHReplace() for example).
+   */
+  function assertEquivalentHTML($element_id, array $expected_tree) {
+    $wrapper = $this->xpath("//*[@id = '" . $element_id . "']");
+    if ($this->assertTrue(isset($wrapper[0]), t('Found wrapper %wrapper', array('%wrapper' => $element_id)))) {
+      $this->assertIdentical($this->depthFirstExplore($wrapper[0]), $expected_tree, t('Expected HTML tree found in the wrapper.'));
+    }
+  }
+
+  function testAHAHReplacement() {
+    // Load the initial form.
+    $this->drupalGet('simpletest-test/form');
+
+    // Push the button "edit-replace":
+    // execute a AHAH 'replace' on the ahah2_internal wrapper.
+    $this->drupalAHAH('edit-replace');
+
+    // Equivalent HTML: <div id="ahah1_external"><div id="ahah1_internal"><div>new content</div></div></div>
+    $expected_result = array(
+      array('div', '', 0),
+      array('div', '', 1),
+      array('div', 'new content', 2),
+    );
+    $this->assertEquivalentHTML('ahah1_external', $expected_result);
+
+    // Push the button "edit-after":
+    // execute a AHAH 'after' on the ahah2_internal wrapper.
+    $this->drupalAHAH('edit-after');
+
+    // Equivalent HTML: <div id="ahah2_external"><div id="ahah2_internal">original content</div><div>new content</div></div>
+    $expected_result = array(
+      array('div', '', 0),
+      array('div', 'original content', 1),
+      array('div', 'new content', 1),
+    );
+    $this->assertEquivalentHTML('ahah2_external', $expected_result);
+
+    // Push the button "edit-append":
+    // execute a AHAH 'append' on the ahah3_external wrapper.
+    // Should return the same result as the previous test.
+    $this->drupalAHAH('edit-append');
+    $this->assertEquivalentHTML('ahah3_external', $expected_result);
+
+    // Push the button "edit-before":
+    // execute a AHAH 'before' on the ahah2_internal wrapper.
+    $this->drupalAHAH('edit-before');
+
+    // Equivalent HTML: <div id="ahah4_external"><div>new content</div><div id="ahah4_internal">original content</div></div>
+    $expected_result = array(
+      array('div', '', 0),
+      array('div', 'new content', 1),
+      array('div', 'original content', 1),
+    );
+    $this->assertEquivalentHTML('ahah4_external', $expected_result);
+
+    // Push the button "edit-prepend":
+    // execute a AHAH 'prepend' on the ahah5_external wrapper.
+    // Should return the same result as the previous test.
+    $this->drupalAHAH('edit-prepend');
+    $this->assertEquivalentHTML('ahah5_external', $expected_result);
+  }
+}
diff --git modules/simpletest/tests/common.test modules/simpletest/tests/common.test
index edfeb6c..7826376 100644
--- modules/simpletest/tests/common.test
+++ modules/simpletest/tests/common.test
@@ -226,7 +226,7 @@ class DrupalHTTPRequestTestCase extends DrupalWebTestCase {
     // Fetch page.
     $result = drupal_http_request(url('node', array('absolute' => TRUE)));
     $this->assertEqual($result->code, 200, t('Fetched page successfully.'));
-    $this->drupalSetContent($result->data);
+    $this->drupalSetResponse($result->data);
     $this->assertTitle(variable_get('site_name', 'Drupal'), t('Site title matches.'));
   }
 
@@ -238,7 +238,7 @@ class DrupalHTTPRequestTestCase extends DrupalWebTestCase {
     $auth = str_replace('http://', 'http://' . $username . ':' . $password .'@', $url);
     $result = drupal_http_request($auth);
 
-    $this->drupalSetContent($result->data);
+    $this->drupalSetResponse($result->data);
     $this->assertRaw($username, t('$_SERVER["PHP_AUTH_USER"] is passed correctly.'));
     $this->assertRaw($password, t('$_SERVER["PHP_AUTH_PW"] is passed correctly.'));
   }
diff --git modules/statistics/statistics.test modules/statistics/statistics.test
index e5d5dc3..5ced2c5 100644
--- modules/statistics/statistics.test
+++ modules/statistics/statistics.test
@@ -55,7 +55,7 @@ class StatisticsBlockVisitorsTestCase extends DrupalWebTestCase {
     $this->clickLink('unblock IP address');
     $this->assertRaw(t('Are you sure you want to delete %ip?', array('%ip' => $test_ip_address)), t('IP address deletion confirmation found.'));
     $edit = array();
-    $this->drupalPost('admin/settings/ip-blocking/delete/1', NULL, t('Delete'));
+    $this->drupalPost('admin/settings/ip-blocking/delete/1', array(), t('Delete'));
     $this->assertRaw(t('The IP address %ip was deleted.', array('%ip' => $test_ip_address)), t('IP address deleted.'));
   }
 }
diff --git modules/system/system.test modules/system/system.test
index 3d2ecab..990b2d2 100644
--- modules/system/system.test
+++ modules/system/system.test
@@ -63,7 +63,7 @@ class EnableDisableCoreTestCase extends DrupalWebTestCase {
     $edit['uninstall[aggregator]'] = 'aggregator';
     $this->drupalPost('admin/build/modules/uninstall', $edit, t('Uninstall'));
 
-    $this->drupalPost(NULL, NULL, t('Uninstall'));
+    $this->drupalPost(NULL, array(), t('Uninstall'));
     $this->assertText(t('The selected modules have been uninstalled.'), t('Modules status has been updated.'));
 
     // Check that hook_modules_uninstalled hook was invoked and check tables.
@@ -88,7 +88,7 @@ class EnableDisableCoreTestCase extends DrupalWebTestCase {
     $this->assertTableCount('languages', FALSE);
     $this->assertTableCount('locale', FALSE);
 
-    $this->drupalPost(NULL, NULL, t('Continue'));
+    $this->drupalPost(NULL, array(), t('Continue'));
     $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
 
     $this->assertModules(array('translation', 'locale'), TRUE);
diff --git modules/taxonomy/taxonomy.test modules/taxonomy/taxonomy.test
index 8d1b514..1411c99 100644
--- modules/taxonomy/taxonomy.test
+++ modules/taxonomy/taxonomy.test
@@ -129,7 +129,7 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
       $edit = array();
       $this->drupalPost('admin/content/taxonomy/' . $vocabulary->vid, $edit, t('Delete'));
       // Submit the confirm form for deletion.
-      $this->drupalPost(NULL, NULL, t('Delete'));
+      $this->drupalPost(NULL, array(), t('Delete'));
     }
     // Confirm that no vocabularies are found in the database.
     $this->assertFalse(taxonomy_get_vocabularies(), t('No vocabularies found in the database'));
@@ -162,7 +162,7 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
     $this->assertText(t('Deleting a vocabulary will delete all the terms in it. This action cannot be undone.'), t('[confirm deletion] Inform that all terms will be deleted.'));
 
     // Confirm deletion.
-    $this->drupalPost(NULL, NULL, t('Delete'));
+    $this->drupalPost(NULL, array(), t('Delete'));
     $this->assertRaw(t('Deleted vocabulary %name.', array('%name' => $vocabulary->name)), t('Vocabulary deleted'));
     $this->assertFalse(taxonomy_vocabulary_load($vid, TRUE), t('Vocabulary is not found in the database'));
   }
diff --git modules/user/user.test modules/user/user.test
index 4bcb026..92c0f03 100644
--- modules/user/user.test
+++ modules/user/user.test
@@ -60,7 +60,7 @@ class UserRegistrationTestCase extends DrupalWebTestCase {
     $this->drupalGet($url);
     $this->assertText(t('This login can be used only once.'), t('Login can be used only once.'));
 
-    $this->drupalPost(NULL, NULL, t('Log in'));
+    $this->drupalPost(NULL, array(), t('Log in'));
     $this->assertText(t('You have just used your one-time login link. It is no longer necessary to use this link to login. Please change your password.'), t('This link is no longer valid.'));
 
     // Change user password.
@@ -182,12 +182,12 @@ class UserDeleteTestCase extends DrupalWebTestCase {
 
     // Delete user.
     $this->drupalGet('user/' . $user->uid . '/edit');
-    $this->drupalPost(NULL, NULL, t('Delete'));
+    $this->drupalPost(NULL, array(), t('Delete'));
     $this->assertRaw(t('Are you sure you want to delete the account %name?', array('%name' => $user->name)), t('[confirm deletion] Asks for confirmation.'));
     $this->assertText(t('All submissions made by this user will be attributed to the anonymous account. This action cannot be undone.'), t('[confirm deletion] Inform that all submissions will be attributed to anonymouse account.'));
 
     // Confirm deletion.
-    $this->drupalPost(NULL, NULL, t('Delete'));
+    $this->drupalPost(NULL, array(), t('Delete'));
     $this->assertRaw(t('%name has been deleted.', array('%name' => $user->name)), t('User deleted'));
     $this->assertFalse(user_load($edit), t('User is not found in the database'));
   }
@@ -648,7 +648,7 @@ class UserBlocksUnitTests extends DrupalWebTestCase {
 
     // Test block output.
     $block = user_block_view('online');
-    $this->drupalSetContent($block['content']);
+    $this->drupalSetResponse($block['content']);
     $this->assertRaw(t('%members and %visitors', array('%members' => '2 users', '%visitors' => '2 guests')), t('Correct number of online users (2 users and 2 guests).'));
     $this->assertText($user1->name, t('Active user 1 found in online list.'));
     $this->assertText($user2->name, t('Active user 2 found in online list.'));
