outline-8.x-1.x-dev/tests/src/Functional/EntryParentsTest.php
tests/src/Functional/EntryParentsTest.php
<?php
namespace Drupal\Tests\outline\Functional;
use Drupal\outline\Entity\Outline;
use Drupal\outline\EntryInterface;
use Drupal\Tests\BrowserTestBase;
/**
* Tests managing outline parents through the user interface.
*
* @group outline
*/
class EntryParentsTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['outline_test'];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* The entry storage.
*
* @var \Drupal\outline\EntryStorageInterface
*/
protected $entryStorage;
/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* The ID of the outline used in this test.
*
* @var string
*/
protected $outlineId = 'test_outline';
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
/* @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
$entity_type_manager = $this->container->get('entity_type.manager');
$this->entryStorage = $entity_type_manager->getStorage('outline_entry');
$this->state = $this->container->get('state');
Outline::create(['oid' => $this->outlineId])->save();
$this->drupalLogin($this->drupalCreateUser(['administer outline']));
}
/**
* Tests specifying parents when creating entries.
*/
public function testAddWithParents() {
$this->drupalGet("/admin/structure/outline/manage/{$this->outlineId}/add");
$page = $this->getSession()->getPage();
// Create a entry without any parents.
$entry_1 = $this->submitAddEntryForm('Test entry 1');
$expected = [['target_id' => 0]];
$this->assertEquals($expected, $entry_1->get('parent')->getValue());
// Explicitly selecting <root> should have the same effect as not selecting
// anything.
$page->selectFieldOption('Parent entries', '<root>');
$entry_2 = $this->submitAddEntryForm('Test entry 2');
$this->assertEquals($expected, $entry_2->get('parent')->getValue());
// Create two entries with the previously created ones as parents,
// respectively.
$page->selectFieldOption('Parent entries', 'Test entry 1');
$entry_3 = $this->submitAddEntryForm('Test entry 3');
$expected = [['target_id' => $entry_1->id()]];
$this->assertEquals($expected, $entry_3->get('parent')->getValue());
$page->selectFieldOption('Parent entries', 'Test entry 2');
$entry_4 = $this->submitAddEntryForm('Test entry 4');
$expected = [['target_id' => $entry_2->id()]];
$this->assertEquals($expected, $entry_4->get('parent')->getValue());
// Create a entry with entry 3 as parent.
$page->selectFieldOption('Parent entries', '-Test entry 3');
$entry_5 = $this->submitAddEntryForm('Test entry 5');
$expected = [['target_id' => $entry_3->id()]];
$this->assertEquals($expected, $entry_5->get('parent')->getValue());
// Create a entry with multiple parents.
$page->selectFieldOption('Parent entries', '--Test entry 5');
$page->selectFieldOption('Parent entries', '-Test entry 4', TRUE);
$entry_6 = $this->submitAddEntryForm('Test entry 6');
$expected = [
['target_id' => $entry_5->id()],
['target_id' => $entry_4->id()],
];
$this->assertEquals($expected, $entry_6->get('parent')->getValue());
}
/**
* Creates a entry through the user interface and returns it.
*
* @param string $name
* The name of the entry to create.
*
* @return \Drupal\outline\EntryInterface
* The newly created outline entry.
*/
protected function submitAddEntryForm($name) {
$this->getSession()->getPage()->fillField('Name', $name);
$this->drupalPostForm(NULL, [], 'Save');
$result = $this->entryStorage
->getQuery()
->condition('name', $name)
->execute();
/* @var \Drupal\outline\EntryInterface $entry_1 */
$entry_1 = $this->entryStorage->load(reset($result));
$this->assertInstanceOf(EntryInterface::class, $entry_1);
return $entry_1;
}
/**
* Tests editing the parents of existing entries.
*/
public function testEditingParents() {
$entries = $this->doTestEditingSingleParent();
$entry_5 = array_pop($entries);
$entry_4 = array_pop($entries);
// Create a entry with multiple parents.
$entry_6 = $this->createEntry('Test entry 6', [
// Entry 5 comes before entry 4 in the user interface, so add the parents in
// the matching order.
$entry_5->id(),
$entry_4->id(),
]);
$this->drupalGet($entry_6->toUrl('edit-form'));
$this->assertParentOption('<root>');
$this->assertParentOption('Test entry 1');
$this->assertParentOption('-Test entry 3');
$this->assertParentOption('--Test entry 5', TRUE);
$this->assertParentOption('Test entry 2');
$this->assertParentOption('-Test entry 4', TRUE);
$this->drupalPostForm(NULL, [], 'Save');
$this->assertParentsUnchanged($entry_6);
}
/**
* Tests specifying parents when creating entries and a disabled parent form.
*/
public function testEditingParentsWithDisabledFormElement() {
// Disable the parent form element.
$this->state->set('outline_test.disable_parent_form_element', TRUE);
$this->drupalGet("/admin/structure/outline/manage/{$this->outlineId}/add");
$this->assertSession()->fieldDisabled('Parent entries');
$entries = $this->doTestEditingSingleParent();
$entry_5 = array_pop($entries);
$entry_4 = array_pop($entries);
// Create a entry with multiple parents.
$entry_6 = $this->createEntry('Test entry 6', [
// When the parent form element is disabled, its default value is used as
// the value which gets populated in ascending order of entry IDs.
$entry_4->id(),
$entry_5->id(),
]);
$this->drupalGet($entry_6->toUrl('edit-form'));
$this->assertParentOption('<root>');
$this->assertParentOption('Test entry 1');
$this->assertParentOption('-Test entry 3');
$this->assertParentOption('--Test entry 5', TRUE);
$this->assertParentOption('Test entry 2');
$this->assertParentOption('-Test entry 4', TRUE);
$this->drupalPostForm(NULL, [], 'Save');
$this->assertParentsUnchanged($entry_6);
}
/**
* Performs tests that edit entries with a single parent
*
* @return \Drupal\outline\EntryInterface[]
* A list of entries created for testing.
*/
protected function doTestEditingSingleParent() {
$entries = [];
// Create two entries without any parents.
$entry_1 = $this->createEntry('Test entry 1');
$this->drupalGet($entry_1->toUrl('edit-form'));
$this->assertParentOption('<root>', TRUE);
$this->drupalPostForm(NULL, [], 'Save');
$this->assertParentsUnchanged($entry_1);
$entries[] = $entry_1;
$entry_2 = $this->createEntry('Test entry 2');
$this->drupalGet($entry_2->toUrl('edit-form'));
$this->assertParentOption('<root>', TRUE);
$this->assertParentOption('Test entry 1');
$this->drupalPostForm(NULL, [], 'Save');
$this->assertParentsUnchanged($entry_2);
$entries[] = $entry_2;
// Create two entries with the previously created entries as parents,
// respectively.
$entry_3 = $this->createEntry('Test entry 3', [$entry_1->id()]);
$this->drupalGet($entry_3->toUrl('edit-form'));
$this->assertParentOption('<root>');
$this->assertParentOption('Test entry 1', TRUE);
$this->assertParentOption('Test entry 2');
$this->drupalPostForm(NULL, [], 'Save');
$this->assertParentsUnchanged($entry_3);
$entries[] = $entry_3;
$entry_4 = $this->createEntry('Test entry 4', [$entry_2->id()]);
$this->drupalGet($entry_4->toUrl('edit-form'));
$this->assertParentOption('<root>');
$this->assertParentOption('Test entry 1');
$this->assertParentOption('-Test entry 3');
$this->assertParentOption('Test entry 2', TRUE);
$this->drupalPostForm(NULL, [], 'Save');
$this->assertParentsUnchanged($entry_4);
$entries[] = $entry_4;
// Create a entry with entry 3 as parent.
$entry_5 = $this->createEntry('Test entry 5', [$entry_3->id()]);
$this->drupalGet($entry_5->toUrl('edit-form'));
$this->assertParentOption('<root>');
$this->assertParentOption('Test entry 1');
$this->assertParentOption('-Test entry 3', TRUE);
$this->assertParentOption('Test entry 2');
$this->assertParentOption('-Test entry 4');
$this->drupalPostForm(NULL, [], 'Save');
$this->assertParentsUnchanged($entry_5);
$entries[] = $entry_5;
return $entries;
}
/**
* Creates a entry, saves it and returns it.
*
* @param string $name
* The name of the entry to create
* @param int[] $parent_ids
* (optional) A list of parent entry IDs.
*
* @return \Drupal\outline\EntryInterface
* The created entry.
*/
protected function createEntry($name, array $parent_ids = []) {
/* @var \Drupal\outline\EntryInterface $entry */
$entry = $this->entryStorage->create([
'name' => $name,
'oid' => $this->outlineId,
]);
foreach ($parent_ids as $delta => $parent_id) {
$entry->get('parent')->set($delta, ['target_id' => $parent_id]);
}
$entry->save();
return $entry;
}
/**
* Asserts that an option in the parent form element of entries exists.
*
* @param string $option
* The label of the parent option.
* @param bool $selected
* (optional) Whether or not the option should be selected. Defaults to
* FALSE.
*/
protected function assertParentOption($option, $selected = FALSE) {
$option = $this->assertSession()->optionExists('Parent entries', $option);
if ($selected) {
$this->assertTrue($option->hasAttribute('selected'));
}
else {
$this->assertFalse($option->hasAttribute('selected'));
}
}
/**
* Asserts that the parents of the entry have not changed after saving.
*
* @param \Drupal\outline\EntryInterface $entry
* The entry to check.
*/
protected function assertParentsUnchanged(EntryInterface $entry) {
$saved_entry = $this->entryStorage->load($entry->id());
$expected = $entry->get('parent')->getValue();
$this->assertEquals($expected, $saved_entry->get('parent')->getValue());
}
}
