Issue #2795049 by Jo Fitzgerald, boaloysius, legovaer, borisson_, klausi, dawehner: Convert web tests to browser tests for history module
							parent
							
								
									1ef413bec0
								
							
						
					
					
						commit
						fce944dd69
					
				| 
						 | 
					@ -1,148 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Drupal\history\Tests;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Drupal\Component\Serialization\Json;
 | 
					 | 
				
			||||||
use Drupal\simpletest\WebTestBase;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Tests the History endpoints.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @group history
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
class HistoryTest extends WebTestBase {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Modules to enable.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @var array
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public static $modules = ['node', 'history'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * The main user for testing.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @var object
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  protected $user;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * A page node for which to check content statistics.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @var object
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  protected $testNode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  protected function setUp() {
 | 
					 | 
				
			||||||
    parent::setUp();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $this->user = $this->drupalCreateUser(['create page content', 'access content']);
 | 
					 | 
				
			||||||
    $this->drupalLogin($this->user);
 | 
					 | 
				
			||||||
    $this->testNode = $this->drupalCreateNode(['type' => 'page', 'uid' => $this->user->id()]);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Get node read timestamps from the server for the current user.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @param array $node_ids
 | 
					 | 
				
			||||||
   *   An array of node IDs.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @return string
 | 
					 | 
				
			||||||
   *   The response body.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  protected function getNodeReadTimestamps(array $node_ids) {
 | 
					 | 
				
			||||||
    // Build POST values.
 | 
					 | 
				
			||||||
    $post = [];
 | 
					 | 
				
			||||||
    for ($i = 0; $i < count($node_ids); $i++) {
 | 
					 | 
				
			||||||
      $post['node_ids[' . $i . ']'] = $node_ids[$i];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Serialize POST values.
 | 
					 | 
				
			||||||
    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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Perform HTTP request.
 | 
					 | 
				
			||||||
    return $this->curlExec([
 | 
					 | 
				
			||||||
      CURLOPT_URL => \Drupal::url('history.get_last_node_view', [], ['absolute' => TRUE]),
 | 
					 | 
				
			||||||
      CURLOPT_POST => TRUE,
 | 
					 | 
				
			||||||
      CURLOPT_POSTFIELDS => $post,
 | 
					 | 
				
			||||||
      CURLOPT_HTTPHEADER => [
 | 
					 | 
				
			||||||
        'Accept: application/json',
 | 
					 | 
				
			||||||
        'Content-Type: application/x-www-form-urlencoded',
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
    ]);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Mark a node as read for the current user.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @param int $node_id
 | 
					 | 
				
			||||||
   *   A node ID.
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @return string
 | 
					 | 
				
			||||||
   *   The response body.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  protected function markNodeAsRead($node_id) {
 | 
					 | 
				
			||||||
    return $this->curlExec([
 | 
					 | 
				
			||||||
      CURLOPT_URL => \Drupal::url('history.read_node', ['node' => $node_id], ['absolute' => TRUE]),
 | 
					 | 
				
			||||||
      CURLOPT_HTTPHEADER => [
 | 
					 | 
				
			||||||
        'Accept: application/json',
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
    ]);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Verifies that the history endpoints work.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public function testHistory() {
 | 
					 | 
				
			||||||
    $nid = $this->testNode->id();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Retrieve "last read" timestamp for test node, for the current user.
 | 
					 | 
				
			||||||
    $response = $this->getNodeReadTimestamps([$nid]);
 | 
					 | 
				
			||||||
    $this->assertResponse(200);
 | 
					 | 
				
			||||||
    $json = Json::decode($response);
 | 
					 | 
				
			||||||
    $this->assertIdentical([1 => 0], $json, 'The node has not yet been read.');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // View the node.
 | 
					 | 
				
			||||||
    $this->drupalGet('node/' . $nid);
 | 
					 | 
				
			||||||
    $this->assertCacheContext('user.roles:authenticated');
 | 
					 | 
				
			||||||
    // JavaScript present to record the node read.
 | 
					 | 
				
			||||||
    $settings = $this->getDrupalSettings();
 | 
					 | 
				
			||||||
    $libraries = explode(',', $settings['ajaxPageState']['libraries']);
 | 
					 | 
				
			||||||
    $this->assertTrue(in_array('history/mark-as-read', $libraries), 'history/mark-as-read library is present.');
 | 
					 | 
				
			||||||
    $this->assertEqual([$nid => TRUE], $settings['history']['nodesToMarkAsRead'], 'drupalSettings to mark node as read are present.');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Simulate JavaScript: perform HTTP request to mark node as read.
 | 
					 | 
				
			||||||
    $response = $this->markNodeAsRead($nid);
 | 
					 | 
				
			||||||
    $this->assertResponse(200);
 | 
					 | 
				
			||||||
    $timestamp = Json::decode($response);
 | 
					 | 
				
			||||||
    $this->assertTrue(is_numeric($timestamp), 'Node has been marked as read. Timestamp received.');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Retrieve "last read" timestamp for test node, for the current user.
 | 
					 | 
				
			||||||
    $response = $this->getNodeReadTimestamps([$nid]);
 | 
					 | 
				
			||||||
    $this->assertResponse(200);
 | 
					 | 
				
			||||||
    $json = Json::decode($response);
 | 
					 | 
				
			||||||
    $this->assertIdentical([1 => $timestamp], $json, 'The node has been read.');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Failing to specify node IDs for the first endpoint should return a 404.
 | 
					 | 
				
			||||||
    $this->getNodeReadTimestamps([]);
 | 
					 | 
				
			||||||
    $this->assertResponse(404);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Accessing either endpoint as the anonymous user should return a 403.
 | 
					 | 
				
			||||||
    $this->drupalLogout();
 | 
					 | 
				
			||||||
    $this->getNodeReadTimestamps([$nid]);
 | 
					 | 
				
			||||||
    $this->assertResponse(403);
 | 
					 | 
				
			||||||
    $this->getNodeReadTimestamps([]);
 | 
					 | 
				
			||||||
    $this->assertResponse(403);
 | 
					 | 
				
			||||||
    $this->markNodeAsRead($nid);
 | 
					 | 
				
			||||||
    $this->assertResponse(403);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,174 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Drupal\Tests\history\Functional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Drupal\Component\Serialization\Json;
 | 
				
			||||||
 | 
					use Drupal\Core\Url;
 | 
				
			||||||
 | 
					use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
 | 
				
			||||||
 | 
					use Drupal\Tests\BrowserTestBase;
 | 
				
			||||||
 | 
					use GuzzleHttp\Cookie\CookieJar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Tests the History endpoints.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @group history
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class HistoryTest extends BrowserTestBase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  use AssertPageCacheContextsAndTagsTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Modules to enable.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public static $modules = ['node', 'history'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The main user for testing.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var object
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * A page node for which to check content statistics.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var object
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $testNode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The cookie jar holding the testing session cookies for Guzzle requests.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var \GuzzleHttp\Client;
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The Guzzle HTTP client.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var \GuzzleHttp\Cookie\CookieJar;
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $cookies;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function setUp() {
 | 
				
			||||||
 | 
					    parent::setUp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->user = $this->drupalCreateUser(['create page content', 'access content']);
 | 
				
			||||||
 | 
					    $this->drupalLogin($this->user);
 | 
				
			||||||
 | 
					    $this->testNode = $this->drupalCreateNode(['type' => 'page', 'uid' => $this->user->id()]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->client = $this->getHttpClient();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Get node read timestamps from the server for the current user.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param array $node_ids
 | 
				
			||||||
 | 
					   *   An array of node IDs.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return \Psr\Http\Message\ResponseInterface
 | 
				
			||||||
 | 
					   *   The response object.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function getNodeReadTimestamps(array $node_ids) {
 | 
				
			||||||
 | 
					    // Perform HTTP request.
 | 
				
			||||||
 | 
					    $url = Url::fromRoute('history.get_last_node_view')
 | 
				
			||||||
 | 
					      ->setAbsolute()
 | 
				
			||||||
 | 
					      ->toString();
 | 
				
			||||||
 | 
					    return $this->client->post($url, [
 | 
				
			||||||
 | 
					      'body' => http_build_query(['node_ids' => $node_ids]),
 | 
				
			||||||
 | 
					      'cookies' => $this->cookies,
 | 
				
			||||||
 | 
					      'headers' => [
 | 
				
			||||||
 | 
					        'Accept' => 'application/json',
 | 
				
			||||||
 | 
					        'Content-Type' => 'application/x-www-form-urlencoded',
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      'http_errors' => FALSE,
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Mark a node as read for the current user.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param int $node_id
 | 
				
			||||||
 | 
					   *   A node ID.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return \Psr\Http\Message\ResponseInterface
 | 
				
			||||||
 | 
					   *   The response body.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function markNodeAsRead($node_id) {
 | 
				
			||||||
 | 
					    $url = Url::fromRoute('history.read_node', ['node' => $node_id], ['absolute' => TRUE])->toString();
 | 
				
			||||||
 | 
					    return $this->client->post($url, [
 | 
				
			||||||
 | 
					      'cookies' => $this->cookies,
 | 
				
			||||||
 | 
					      'headers' => [
 | 
				
			||||||
 | 
					        'Accept' => 'application/json',
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      'http_errors' => FALSE,
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Verifies that the history endpoints work.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function testHistory() {
 | 
				
			||||||
 | 
					    $nid = $this->testNode->id();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve "last read" timestamp for test node, for the current user.
 | 
				
			||||||
 | 
					    $response = $this->getNodeReadTimestamps([$nid]);
 | 
				
			||||||
 | 
					    $this->assertEquals(200, $response->getStatusCode());
 | 
				
			||||||
 | 
					    $json = Json::decode($response->getBody());
 | 
				
			||||||
 | 
					    $this->assertIdentical([1 => 0], $json, 'The node has not yet been read.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // View the node.
 | 
				
			||||||
 | 
					    $this->drupalGet('node/' . $nid);
 | 
				
			||||||
 | 
					    $this->assertCacheContext('user.roles:authenticated');
 | 
				
			||||||
 | 
					    // JavaScript present to record the node read.
 | 
				
			||||||
 | 
					    $settings = $this->getDrupalSettings();
 | 
				
			||||||
 | 
					    $libraries = explode(',', $settings['ajaxPageState']['libraries']);
 | 
				
			||||||
 | 
					    $this->assertTrue(in_array('history/mark-as-read', $libraries), 'history/mark-as-read library is present.');
 | 
				
			||||||
 | 
					    $this->assertEqual([$nid => TRUE], $settings['history']['nodesToMarkAsRead'], 'drupalSettings to mark node as read are present.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Simulate JavaScript: perform HTTP request to mark node as read.
 | 
				
			||||||
 | 
					    $response = $this->markNodeAsRead($nid);
 | 
				
			||||||
 | 
					    $this->assertEquals(200, $response->getStatusCode());
 | 
				
			||||||
 | 
					    $timestamp = Json::decode($response->getBody());
 | 
				
			||||||
 | 
					    $this->assertTrue(is_numeric($timestamp), 'Node has been marked as read. Timestamp received.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Retrieve "last read" timestamp for test node, for the current user.
 | 
				
			||||||
 | 
					    $response = $this->getNodeReadTimestamps([$nid]);
 | 
				
			||||||
 | 
					    $this->assertEquals(200, $response->getStatusCode());
 | 
				
			||||||
 | 
					    $json = Json::decode($response->getBody());
 | 
				
			||||||
 | 
					    $this->assertIdentical([1 => $timestamp], $json, 'The node has been read.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Failing to specify node IDs for the first endpoint should return a 404.
 | 
				
			||||||
 | 
					    $response = $this->getNodeReadTimestamps([]);
 | 
				
			||||||
 | 
					    $this->assertEquals(404, $response->getStatusCode());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Accessing either endpoint as the anonymous user should return a 403.
 | 
				
			||||||
 | 
					    $this->drupalLogout();
 | 
				
			||||||
 | 
					    $response = $this->getNodeReadTimestamps([$nid]);
 | 
				
			||||||
 | 
					    $this->assertEquals(403, $response->getStatusCode());
 | 
				
			||||||
 | 
					    $response = $this->getNodeReadTimestamps([]);
 | 
				
			||||||
 | 
					    $this->assertEquals(403, $response->getStatusCode());
 | 
				
			||||||
 | 
					    $response = $this->markNodeAsRead($nid);
 | 
				
			||||||
 | 
					    $this->assertEquals(403, $response->getStatusCode());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Obtain the HTTP client and set the cookies.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return \GuzzleHttp\Client
 | 
				
			||||||
 | 
					   *   The client with BrowserTestBase configuration.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function getHttpClient() {
 | 
				
			||||||
 | 
					    // Similar code is also employed to test CSRF tokens.
 | 
				
			||||||
 | 
					    // @see \Drupal\Tests\system\Functional\CsrfRequestHeaderTest::testRouteAccess()
 | 
				
			||||||
 | 
					    $domain = parse_url($this->getUrl(), PHP_URL_HOST);
 | 
				
			||||||
 | 
					    $session_id = $this->getSession()->getCookie($this->getSessionName());
 | 
				
			||||||
 | 
					    $this->cookies = CookieJar::fromArray([$this->getSessionName() => $session_id], $domain);
 | 
				
			||||||
 | 
					    return $this->getSession()->getDriver()->getClient()->getClient();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue