Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / history / tests / src / Functional / HistoryTest.php
1 <?php
2
3 namespace Drupal\Tests\history\Functional;
4
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Core\Url;
7 use Drupal\Tests\BrowserTestBase;
8 use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
9 use GuzzleHttp\Cookie\CookieJar;
10
11 /**
12  * Tests the History endpoints.
13  *
14  * @group history
15  */
16 class HistoryTest extends BrowserTestBase {
17
18   use AssertPageCacheContextsAndTagsTrait;
19
20   /**
21    * Modules to enable.
22    *
23    * @var array
24    */
25   public static $modules = ['node', 'history'];
26
27   /**
28    * The main user for testing.
29    *
30    * @var object
31    */
32   protected $user;
33
34   /**
35    * A page node for which to check content statistics.
36    *
37    * @var object
38    */
39   protected $testNode;
40
41   /**
42    * The cookie jar holding the testing session cookies for Guzzle requests.
43    *
44    * @var \GuzzleHttp\Client;
45    */
46   protected $client;
47
48   /**
49    * The Guzzle HTTP client.
50    *
51    * @var \GuzzleHttp\Cookie\CookieJar;
52    */
53   protected $cookies;
54
55   protected function setUp() {
56     parent::setUp();
57
58     $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
59
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()]);
63
64     $this->client = $this->getHttpClient();
65   }
66
67   /**
68    * Get node read timestamps from the server for the current user.
69    *
70    * @param array $node_ids
71    *   An array of node IDs.
72    *
73    * @return \Psr\Http\Message\ResponseInterface
74    *   The response object.
75    */
76   protected function getNodeReadTimestamps(array $node_ids) {
77     // Perform HTTP request.
78     $url = Url::fromRoute('history.get_last_node_view')
79       ->setAbsolute()
80       ->toString();
81     return $this->client->post($url, [
82       'body' => http_build_query(['node_ids' => $node_ids]),
83       'cookies' => $this->cookies,
84       'headers' => [
85         'Accept' => 'application/json',
86         'Content-Type' => 'application/x-www-form-urlencoded',
87       ],
88       'http_errors' => FALSE,
89     ]);
90   }
91
92   /**
93    * Mark a node as read for the current user.
94    *
95    * @param int $node_id
96    *   A node ID.
97    *
98    * @return \Psr\Http\Message\ResponseInterface
99    *   The response body.
100    */
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,
105       'headers' => [
106         'Accept' => 'application/json',
107       ],
108       'http_errors' => FALSE,
109     ]);
110   }
111
112   /**
113    * Verifies that the history endpoints work.
114    */
115   public function testHistory() {
116     $nid = $this->testNode->id();
117
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.');
123
124     // View the node.
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.');
132
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.');
138
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.');
144
145     // Failing to specify node IDs for the first endpoint should return a 404.
146     $response = $this->getNodeReadTimestamps([]);
147     $this->assertEquals(404, $response->getStatusCode());
148
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());
157   }
158
159   /**
160    * Obtain the HTTP client and set the cookies.
161    *
162    * @return \GuzzleHttp\Client
163    *   The client with BrowserTestBase configuration.
164    */
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();
172   }
173
174 }