3 namespace Drupal\Tests\history\Functional;
5 use Drupal\Component\Serialization\Json;
7 use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
8 use Drupal\Tests\BrowserTestBase;
9 use GuzzleHttp\Cookie\CookieJar;
12 * Tests the History endpoints.
16 class HistoryTest extends BrowserTestBase {
18 use AssertPageCacheContextsAndTagsTrait;
25 public static $modules = ['node', 'history'];
28 * The main user for testing.
35 * A page node for which to check content statistics.
42 * The cookie jar holding the testing session cookies for Guzzle requests.
44 * @var \GuzzleHttp\Client;
49 * The Guzzle HTTP client.
51 * @var \GuzzleHttp\Cookie\CookieJar;
55 protected function setUp() {
58 $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
60 $this->user = $this->drupalCreateUser(['create page content', 'access content']);
61 $this->drupalLogin($this->user);
62 $this->testNode = $this->drupalCreateNode(['type' => 'page', 'uid' => $this->user->id()]);
64 $this->client = $this->getHttpClient();
68 * Get node read timestamps from the server for the current user.
70 * @param array $node_ids
71 * An array of node IDs.
73 * @return \Psr\Http\Message\ResponseInterface
74 * The response object.
76 protected function getNodeReadTimestamps(array $node_ids) {
77 // Perform HTTP request.
78 $url = Url::fromRoute('history.get_last_node_view')
81 return $this->client->post($url, [
82 'body' => http_build_query(['node_ids' => $node_ids]),
83 'cookies' => $this->cookies,
85 'Accept' => 'application/json',
86 'Content-Type' => 'application/x-www-form-urlencoded',
88 'http_errors' => FALSE,
93 * Mark a node as read for the current user.
98 * @return \Psr\Http\Message\ResponseInterface
101 protected function markNodeAsRead($node_id) {
102 $url = Url::fromRoute('history.read_node', ['node' => $node_id], ['absolute' => TRUE])->toString();
103 return $this->client->post($url, [
104 'cookies' => $this->cookies,
106 'Accept' => 'application/json',
108 'http_errors' => FALSE,
113 * Verifies that the history endpoints work.
115 public function testHistory() {
116 $nid = $this->testNode->id();
118 // Retrieve "last read" timestamp for test node, for the current user.
119 $response = $this->getNodeReadTimestamps([$nid]);
120 $this->assertEquals(200, $response->getStatusCode());
121 $json = Json::decode($response->getBody());
122 $this->assertIdentical([1 => 0], $json, 'The node has not yet been read.');
125 $this->drupalGet('node/' . $nid);
126 $this->assertCacheContext('user.roles:authenticated');
127 // JavaScript present to record the node read.
128 $settings = $this->getDrupalSettings();
129 $libraries = explode(',', $settings['ajaxPageState']['libraries']);
130 $this->assertTrue(in_array('history/mark-as-read', $libraries), 'history/mark-as-read library is present.');
131 $this->assertEqual([$nid => TRUE], $settings['history']['nodesToMarkAsRead'], 'drupalSettings to mark node as read are present.');
133 // Simulate JavaScript: perform HTTP request to mark node as read.
134 $response = $this->markNodeAsRead($nid);
135 $this->assertEquals(200, $response->getStatusCode());
136 $timestamp = Json::decode($response->getBody());
137 $this->assertTrue(is_numeric($timestamp), 'Node has been marked as read. Timestamp received.');
139 // Retrieve "last read" timestamp for test node, for the current user.
140 $response = $this->getNodeReadTimestamps([$nid]);
141 $this->assertEquals(200, $response->getStatusCode());
142 $json = Json::decode($response->getBody());
143 $this->assertIdentical([1 => $timestamp], $json, 'The node has been read.');
145 // Failing to specify node IDs for the first endpoint should return a 404.
146 $response = $this->getNodeReadTimestamps([]);
147 $this->assertEquals(404, $response->getStatusCode());
149 // Accessing either endpoint as the anonymous user should return a 403.
150 $this->drupalLogout();
151 $response = $this->getNodeReadTimestamps([$nid]);
152 $this->assertEquals(403, $response->getStatusCode());
153 $response = $this->getNodeReadTimestamps([]);
154 $this->assertEquals(403, $response->getStatusCode());
155 $response = $this->markNodeAsRead($nid);
156 $this->assertEquals(403, $response->getStatusCode());
160 * Obtain the HTTP client and set the cookies.
162 * @return \GuzzleHttp\Client
163 * The client with BrowserTestBase configuration.
165 protected function getHttpClient() {
166 // Similar code is also employed to test CSRF tokens.
167 // @see \Drupal\Tests\system\Functional\CsrfRequestHeaderTest::testRouteAccess()
168 $domain = parse_url($this->getUrl(), PHP_URL_HOST);
169 $session_id = $this->getSession()->getCookie($this->getSessionName());
170 $this->cookies = CookieJar::fromArray([$this->getSessionName() => $session_id], $domain);
171 return $this->getSession()->getDriver()->getClient()->getClient();