Initial Drupal 11 with DDEV setup
This commit is contained in:
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\history\Functional;
|
||||
|
||||
use Drupal\Tests\system\Functional\Module\GenericModuleTestBase;
|
||||
|
||||
/**
|
||||
* Generic module test for history.
|
||||
*
|
||||
* @group history
|
||||
*/
|
||||
class GenericTest extends GenericModuleTestBase {}
|
||||
172
web/core/modules/history/tests/src/Functional/HistoryTest.php
Normal file
172
web/core/modules/history/tests/src/Functional/HistoryTest.php
Normal file
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\history\Functional;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Tests the History endpoints.
|
||||
*
|
||||
* @group history
|
||||
*/
|
||||
class HistoryTest extends BrowserTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['node', 'history'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* The main user for testing.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* A page node for which to check content statistics.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $testNode;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
|
||||
$this->user = $this->drupalCreateUser([
|
||||
'create page content',
|
||||
'edit own 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 \Psr\Http\Message\ResponseInterface
|
||||
* The response object.
|
||||
*/
|
||||
protected function getNodeReadTimestamps(array $node_ids): ResponseInterface {
|
||||
// Perform HTTP request.
|
||||
$http_client = $this->getHttpClient();
|
||||
$url = Url::fromRoute('history.get_last_node_view')
|
||||
->setAbsolute()
|
||||
->toString();
|
||||
|
||||
return $http_client->request('POST', $url, [
|
||||
'form_params' => ['node_ids' => $node_ids],
|
||||
'cookies' => $this->getSessionCookies(),
|
||||
'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): ResponseInterface {
|
||||
$http_client = $this->getHttpClient();
|
||||
$url = Url::fromRoute('history.read_node', ['node' => $node_id], ['absolute' => TRUE])->toString();
|
||||
|
||||
return $http_client->request('POST', $url, [
|
||||
'cookies' => $this->getSessionCookies(),
|
||||
'http_errors' => FALSE,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the history endpoints work.
|
||||
*/
|
||||
public function testHistory(): void {
|
||||
$nid = $this->testNode->id();
|
||||
|
||||
// Verify that previews of new entities do not create the history.
|
||||
$this->drupalGet("node/add/page");
|
||||
$this->submitForm(['title[0][value]' => 'Unsaved page'], 'Preview');
|
||||
$this->assertArrayNotHasKey('ajaxPageState', $this->getDrupalSettings());
|
||||
|
||||
// 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->assertSame([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->assertContains('history/mark-as-read', $libraries, 'history/mark-as-read library is present.');
|
||||
$this->assertEquals([$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->assertIsNumeric($timestamp);
|
||||
|
||||
// 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->assertSame([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());
|
||||
|
||||
// Verify that previews of existing entities do not update the history.
|
||||
$this->drupalGet("node/$nid/edit");
|
||||
$this->submitForm([], 'Preview');
|
||||
$this->assertArrayNotHasKey('ajaxPageState', $this->getDrupalSettings());
|
||||
|
||||
// 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());
|
||||
|
||||
// Additional check to ensure that we did not forget to verify anything.
|
||||
$rows = \Drupal::database()->select('history')
|
||||
->fields('history', ['nid', 'uid', 'timestamp'])
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $rows);
|
||||
$this->assertSame($this->user->id(), $rows[0]->uid);
|
||||
$this->assertSame($this->testNode->id(), $rows[0]->nid);
|
||||
$this->assertSame($timestamp, (int) $rows[0]->timestamp);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\history\Kernel\Views;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Tests the history timestamp handlers.
|
||||
*
|
||||
* @group history
|
||||
* @see \Drupal\history\Plugin\views\field\HistoryUserTimestamp
|
||||
* @see \Drupal\history\Plugin\views\filter\HistoryUserTimestamp
|
||||
*/
|
||||
class HistoryTimestampTest extends ViewsKernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['history', 'node'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_history'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp($import_test_views = TRUE): void {
|
||||
parent::setUp($import_test_views);
|
||||
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('history', ['history']);
|
||||
// Use history_test_theme because its marker is wrapped in a span so it can
|
||||
// be easily targeted with xpath.
|
||||
\Drupal::service('theme_installer')->install(['history_test_theme']);
|
||||
\Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme('history_test_theme'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the handlers.
|
||||
*/
|
||||
public function testHandlers(): void {
|
||||
$nodes = [];
|
||||
$node = Node::create([
|
||||
'title' => 'n1',
|
||||
'type' => 'default',
|
||||
]);
|
||||
$node->save();
|
||||
$nodes[] = $node;
|
||||
$node = Node::create([
|
||||
'title' => 'n2',
|
||||
'type' => 'default',
|
||||
]);
|
||||
$node->save();
|
||||
$nodes[] = $node;
|
||||
|
||||
$account = User::create(['name' => 'admin']);
|
||||
$account->save();
|
||||
\Drupal::currentUser()->setAccount($account);
|
||||
|
||||
$connection = Database::getConnection();
|
||||
$requestTime = \Drupal::time()->getRequestTime();
|
||||
$connection->insert('history')
|
||||
->fields([
|
||||
'uid' => $account->id(),
|
||||
'nid' => $nodes[0]->id(),
|
||||
'timestamp' => $requestTime - 100,
|
||||
])->execute();
|
||||
|
||||
$connection->insert('history')
|
||||
->fields([
|
||||
'uid' => $account->id(),
|
||||
'nid' => $nodes[1]->id(),
|
||||
'timestamp' => $requestTime + 100,
|
||||
])->execute();
|
||||
|
||||
$column_map = [
|
||||
'nid' => 'nid',
|
||||
];
|
||||
|
||||
// Test the history field.
|
||||
$view = Views::getView('test_history');
|
||||
$view->setDisplay('page_1');
|
||||
$this->executeView($view);
|
||||
$this->assertCount(2, $view->result);
|
||||
$output = $view->preview();
|
||||
$this->setRawContent(\Drupal::service('renderer')->renderRoot($output));
|
||||
$result = $this->xpath('//span[@class=:class]', [':class' => 'marker']);
|
||||
$this->assertCount(1, $result, 'Just one node is marked as new');
|
||||
|
||||
// Test the history filter.
|
||||
$view = Views::getView('test_history');
|
||||
$view->setDisplay('page_2');
|
||||
$this->executeView($view);
|
||||
$this->assertCount(1, $view->result);
|
||||
$this->assertIdenticalResultset($view, [['nid' => $nodes[0]->id()]], $column_map);
|
||||
|
||||
// Install Comment module and make sure that content types without comment
|
||||
// field will not break the view.
|
||||
// See \Drupal\history\Plugin\views\filter\HistoryUserTimestamp::query()
|
||||
\Drupal::service('module_installer')->install(['comment']);
|
||||
$view = Views::getView('test_history');
|
||||
$view->setDisplay('page_2');
|
||||
$this->executeView($view);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
name: 'History Test Theme'
|
||||
type: theme
|
||||
description: 'Theme for history tests.'
|
||||
version: VERSION
|
||||
base theme: stark
|
||||
@ -0,0 +1,20 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Theme override for a marker for new or updated content.
|
||||
*
|
||||
* Available variables:
|
||||
* - status: Number representing the marker status to display. Use the constants
|
||||
* below for comparison:
|
||||
* - MARK_NEW
|
||||
* - MARK_UPDATED
|
||||
* - MARK_READ
|
||||
*/
|
||||
#}
|
||||
{% if logged_in %}
|
||||
{% if status is constant('MARK_NEW') %}
|
||||
<span class="marker">{{ 'New'|t }}</span>
|
||||
{% elseif status is constant('MARK_UPDATED') %}
|
||||
<span class="marker">{{ 'Updated'|t }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user