class RevisionVersionHistoryTest
Same name in this branch
- main core/tests/Drupal/FunctionalTests/Entity/RevisionVersionHistoryTest.php \Drupal\FunctionalTests\Entity\RevisionVersionHistoryTest
Same name and namespace in other branches
- 11.x core/tests/Drupal/FunctionalTests/Entity/RevisionVersionHistoryTest.php \Drupal\FunctionalTests\Entity\RevisionVersionHistoryTest
- 10 core/tests/Drupal/FunctionalTests/Entity/RevisionVersionHistoryTest.php \Drupal\FunctionalTests\Entity\RevisionVersionHistoryTest
Tests version history page.
Attributes
#[CoversClass(VersionHistoryController::class)]
#[Group('Entity')]
#[RunTestsInSeparateProcesses]
Hierarchy
- class \Drupal\KernelTests\KernelTestBase implements \Drupal\Core\DependencyInjection\ServiceProviderInterface uses \Drupal\Tests\DrupalTestCaseTrait, \Drupal\KernelTests\AssertContentTrait, \Drupal\Tests\RandomGeneratorTrait, \Drupal\Tests\ConfigTestTrait, \Drupal\Tests\ExtensionListTestTrait, \Prophecy\PhpUnit\ProphecyTrait, \Drupal\Tests\BrowserHtmlDebugTrait, \Drupal\Tests\HttpKernelUiHelperTrait extends \PHPUnit\Framework\TestCase
- class \Drupal\KernelTests\Core\Entity\RevisionVersionHistoryTest uses \Drupal\Tests\user\Traits\UserCreationTrait extends \Drupal\KernelTests\KernelTestBase
Expanded class hierarchy of RevisionVersionHistoryTest
File
-
core/
tests/ Drupal/ KernelTests/ Core/ Entity/ RevisionVersionHistoryTest.php, line 21
Namespace
Drupal\KernelTests\Core\EntityView source
class RevisionVersionHistoryTest extends KernelTestBase {
use UserCreationTrait {
createUser as drupalCreateUser;
}
/**
* {@inheritdoc}
*/
protected static $modules = [
'entity_test',
'entity_test_revlog',
'user',
'system',
];
/**
* {@inheritdoc}
*/
protected function setUp() : void {
parent::setUp();
$this->installEntitySchema('entity_test_rev');
$this->installEntitySchema('entity_test_revlog');
$this->installEntitySchema('user');
$this->installConfig([
'system',
]);
}
/**
* Test all revisions appear, in order of revision creation.
*/
public function testOrder() : void {
/** @var \Drupal\entity_test_revlog\Entity\EntityTestWithRevisionLog $entity */
$entity = EntityTestWithRevisionLog::create([
'type' => 'entity_test_revlog',
]);
// Need label to be able to assert order.
$entity->setName('view all revisions');
$user = $this->drupalCreateUser([], 'first revision');
$entity->setRevisionUser($user);
$entity->setNewRevision();
$entity->save();
$entity->setNewRevision();
$user = $this->drupalCreateUser([], 'second revision');
$entity->setRevisionUser($user);
$entity->save();
$entity->setNewRevision();
$user = $this->drupalCreateUser([], 'third revision');
$entity->setRevisionUser($user);
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementsCount('css', 'table tbody tr', 3);
// Order is newest to oldest revision by creation order.
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', 'third revision');
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(2)', 'second revision');
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(3)', 'first revision');
}
/**
* Test current revision is indicated.
*
* @legacy-covers \Drupal\Core\Entity\Controller\VersionHistoryController::revisionOverview
*/
public function testCurrentRevision() : void {
/** @var \Drupal\entity_test\Entity\EntityTestRev $entity */
$entity = EntityTestRev::create([
'type' => 'entity_test_rev',
]);
// Need label to be able to assert order.
$entity->setName('view all revisions');
$entity->setNewRevision();
$entity->save();
$entity->setNewRevision();
$entity->save();
$entity->setNewRevision();
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementsCount('css', 'table tbody tr', 3);
// Current revision text is found on the latest revision row.
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', 'Current revision');
$this->assertSession()
->elementTextNotContains('css', 'table tbody tr:nth-child(2)', 'Current revision');
$this->assertSession()
->elementTextNotContains('css', 'table tbody tr:nth-child(3)', 'Current revision');
// Current revision row has 'revision-current' class.
$this->assertSession()
->elementAttributeContains('css', 'table tbody tr:nth-child(1)', 'class', 'revision-current');
}
/**
* Test description with entity implementing revision log.
*
* @legacy-covers ::getRevisionDescription
*/
public function testDescriptionRevLog() : void {
/** @var \Drupal\entity_test_revlog\Entity\EntityTestWithRevisionLog $entity */
$entity = EntityTestWithRevisionLog::create([
'type' => 'entity_test_revlog',
]);
$entity->setName('view all revisions');
$user = $this->drupalCreateUser([], $this->randomMachineName());
$entity->setRevisionUser($user);
$entity->setRevisionCreationTime((new \DateTime('2 February 2013 4:00:00pm'))->getTimestamp());
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', '2 Feb 2013 - 16:00');
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', $user->getAccountName());
}
/**
* Test description with entity implementing revision log, with empty values.
*
* @legacy-covers ::getRevisionDescription
*/
public function testDescriptionRevLogNullValues() : void {
$this->installConfig([
'user',
]);
$entity = EntityTestWithRevisionLog::create([
'type' => 'entity_test_revlog',
]);
$entity->setName('view all revisions')
->save();
// Check entity values are still null after saving; they did not receive
// values from currentUser or some other global context.
$this->assertNull($entity->getRevisionUser());
$this->assertNull($entity->getRevisionUserId());
$this->assertNull($entity->getRevisionLogMessage());
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', 'by Anonymous (not verified)');
}
/**
* Test description with entity, without revision log, no label access.
*
* @legacy-covers ::getRevisionDescription
*/
public function testDescriptionNoRevLogNoLabelAccess() : void {
/** @var \Drupal\entity_test\Entity\EntityTestRev $entity */
$entity = EntityTestRev::create([
'type' => 'entity_test_rev',
]);
$entity->setName('view all revisions');
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', '- Restricted access -');
$this->assertSession()
->elementTextNotContains('css', 'table tbody tr:nth-child(1)', $entity->getName());
}
/**
* Test description with entity, without revision log, with label access.
*
* @legacy-covers ::getRevisionDescription
*/
public function testDescriptionNoRevLogWithLabelAccess() : void {
// Permission grants 'view label' access.
$this->setCurrentUser($this->createUser([
'view test entity',
]));
/** @var \Drupal\entity_test\Entity\EntityTestRev $entity */
$entity = EntityTestRev::create([
'type' => 'entity_test_rev',
]);
$entity->setName('view all revisions');
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', $entity->getName());
$this->assertSession()
->elementTextNotContains('css', 'table tbody tr:nth-child(1)', '- Restricted access -');
}
/**
* Test revision link, without access to revision page.
*
* @legacy-covers ::getRevisionDescription
*/
public function testDescriptionLinkNoAccess() : void {
/** @var \Drupal\entity_test_revlog\Entity\EntityTestWithRevisionLog $entity */
$entity = EntityTestWithRevisionLog::create([
'type' => 'entity_test_revlog',
]);
$entity->setName('view all revisions');
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementsCount('css', 'table tbody tr', 1);
$this->assertSession()
->elementsCount('css', 'table tbody tr a', 0);
}
/**
* Test revision link, with access to revision page.
*
* Test two revisions. Usually the latest revision only checks canonical
* route access, whereas all others will check individual revision access.
*
* @legacy-covers ::getRevisionDescription
*/
public function testDescriptionLinkWithAccess() : void {
/** @var \Drupal\entity_test_revlog\Entity\EntityTestWithRevisionLog $entity */
$entity = EntityTestWithRevisionLog::create([
'type' => 'entity_test_revlog',
]);
// Revision has access to individual revision.
$entity->setName('view all revisions, view revision');
$entity->save();
$firstRevisionId = $entity->getRevisionId();
// Revision has access to canonical route.
$entity->setName('view all revisions, view');
$entity->setNewRevision();
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$row1Link = $this->assertSession()
->elementExists('css', 'table tbody tr:nth-child(1) a');
$this->assertEquals($entity->toUrl()
->toString(), $row1Link->getAttribute('href'));
// Reload revision so object has the properties to build a revision link.
/** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */
$storage = \Drupal::entityTypeManager()->getStorage('entity_test_revlog');
$firstRevision = $storage->loadRevision($firstRevisionId);
$row2Link = $this->assertSession()
->elementExists('css', 'table tbody tr:nth-child(2) a');
$this->assertEquals($firstRevision->toUrl('revision')
->toString(), $row2Link->getAttribute('href'));
}
/**
* Test revision log message if supported, and HTML tags are stripped.
*
* @legacy-covers ::getRevisionDescription
*/
public function testDescriptionRevisionLogMessage() : void {
/** @var \Drupal\entity_test_revlog\Entity\EntityTestWithRevisionLog $entity */
$entity = EntityTestWithRevisionLog::create([
'type' => 'entity_test_revlog',
]);
$entity->setName('view all revisions');
$entity->setRevisionLogMessage('<em>Hello</em> <script>world</script> <strong>123</strong>');
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
// Script tags are stripped, while admin-safe tags are retained.
$this->assertSession()
->elementContains('css', 'table tbody tr:nth-child(1)', '<em>Hello</em> world <strong>123</strong>');
}
/**
* Test revert operation.
*
* @legacy-covers ::buildRevertRevisionLink
*/
public function testOperationRevertRevision() : void {
/** @var \Drupal\entity_test_revlog\Entity\EntityTestWithRevisionLog $entity */
$entity = EntityTestWithRevisionLog::create([
'type' => 'entity_test_revlog',
]);
$entity->setName('view all revisions');
$entity->save();
$entity->setName('view all revisions, revert');
$entity->setNewRevision();
$entity->save();
$entity->setName('view all revisions, revert');
$entity->setNewRevision();
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementsCount('css', 'table tbody tr', 3);
// Latest revision does not have revert revision operation: reverting latest
// revision is not permitted.
$row1 = $this->assertSession()
->elementExists('css', 'table tbody tr:nth-child(1)');
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', 'Current revision');
$this->assertSession()
->elementNotExists('named', [
'link',
'Revert',
], $row1);
// Revision 2 has revert revision operation: granted access.
$row2 = $this->assertSession()
->elementExists('css', 'table tbody tr:nth-child(2)');
$this->assertSession()
->elementExists('named', [
'link',
'Revert',
], $row2);
// Revision 3 does not have revert revision operation: no access.
$row3 = $this->assertSession()
->elementExists('css', 'table tbody tr:nth-child(3)');
$this->assertSession()
->elementNotExists('named', [
'link',
'Revert',
], $row3);
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementsCount('css', 'table tbody tr', 3);
}
/**
* Test delete operation.
*
* @legacy-covers ::buildDeleteRevisionLink
*/
public function testOperationDeleteRevision() : void {
/** @var \Drupal\entity_test_revlog\Entity\EntityTestWithRevisionLog $entity */
$entity = EntityTestWithRevisionLog::create([
'type' => 'entity_test_revlog',
]);
$entity->setName('view all revisions');
$entity->save();
$entity->setName('view all revisions, delete revision');
$entity->setNewRevision();
$entity->save();
$entity->setName('view all revisions, delete revision');
$entity->setNewRevision();
$entity->save();
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementsCount('css', 'table tbody tr', 3);
// Latest revision does not have delete revision operation: deleting latest
// revision is not permitted.
$row1 = $this->assertSession()
->elementExists('css', 'table tbody tr:nth-child(1)');
$this->assertSession()
->elementTextContains('css', 'table tbody tr:nth-child(1)', 'Current revision');
$this->assertSession()
->elementNotExists('named', [
'link',
'Delete',
], $row1);
// Revision 2 has delete revision operation: granted access.
$row2 = $this->assertSession()
->elementExists('css', 'table tbody tr:nth-child(2)');
$this->assertSession()
->elementExists('named', [
'link',
'Delete',
], $row2);
// Revision 3 does not have delete revision operation: no access.
$row3 = $this->assertSession()
->elementExists('css', 'table tbody tr:nth-child(3)');
$this->assertSession()
->elementNotExists('named', [
'link',
'Delete',
], $row3);
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementsCount('css', 'table tbody tr', 3);
}
/**
* Test revisions are paginated.
*/
public function testRevisionsPagination() : void {
$this->installEntitySchema('entity_test_mulrev');
/** @var \Drupal\entity_test\Entity\EntityTestMulRev $entity */
$entity = EntityTestMulRev::create([
'type' => 'entity_test_mulrev',
'name' => 'view all revisions,view revision',
]);
$entity->save();
$firstRevisionId = $entity->getRevisionId();
for ($i = 0; $i < VersionHistoryController::REVISIONS_PER_PAGE; $i++) {
$entity->setNewRevision(TRUE);
// We need to change something on the entity for it to be considered a new
// revision to display. We need "view all revisions" and "view revision"
// in a comma separated string to grant access.
$entity->setName('view all revisions,view revision,' . $i)
->save();
}
// Create revisions without translation changes to ensure these do not
// affect pagination.
for ($i = 0; $i < VersionHistoryController::REVISIONS_PER_PAGE; $i++) {
$entity->setNewRevision(TRUE);
$entity->save();
}
$this->drupalGet($entity->toUrl('version-history'));
$this->assertSession()
->elementsCount('css', 'table tbody tr', VersionHistoryController::REVISIONS_PER_PAGE);
$this->assertSession()
->elementExists('css', '.pager');
/** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */
$storage = $this->container
->get('entity_type.manager')
->getStorage($entity->getEntityTypeId());
$firstRevision = $storage->loadRevision($firstRevisionId);
$secondRevision = $storage->loadRevision($firstRevisionId + 1);
// We should see everything up to the second revision, but not the first.
$this->assertSession()
->linkByHrefExists($secondRevision->toUrl('revision')
->toString());
$this->assertSession()
->linkByHrefNotExists($firstRevision->toUrl('revision')
->toString());
// The next page should show just the first revision.
$this->resetPagerState();
$this->clickLink('Go to next page');
$this->assertSession()
->elementsCount('css', 'table tbody tr', 1);
$this->assertSession()
->elementExists('css', '.pager');
$this->assertSession()
->linkByHrefNotExists($secondRevision->toUrl('revision')
->toString());
$this->assertSession()
->linkByHrefExists($firstRevision->toUrl('revision')
->toString());
}
/**
* Resets pager manager state between requests.
*
* The PagerManager service persists maxPagerElementId across requests in
* kernel tests, causing subsequent requests to use a different pager element
* ID than expected. This makes the 'page' query parameter not correspond to
* the correct pager element.
*
* @todo remove after https://www.drupal.org/project/drupal/issues/3609436
*/
protected function resetPagerState() : void {
$this->container
->set('pager.manager', new PagerManager($this->container
->get('pager.parameters')));
}
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.