Move into nested docroot

This commit is contained in:
Rob Davies 2017-02-13 15:31:17 +00:00
parent 83a0d3a149
commit c8b70abde9
13405 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,6 @@
name: 'Book module breadcrumb tests'
type: module
description: 'Support module for book module breadcrumb testing.'
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,27 @@
<?php
/**
* @file
* Test module for testing the book module breadcrumb.
*/
use Drupal\Core\Access\AccessResultForbidden;
use Drupal\Core\Access\AccessResultNeutral;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
/**
* Implements hook_node_access().
*/
function book_breadcrumb_test_node_access(NodeInterface $node, $operation, AccountInterface $account) {
$config = \Drupal::config('book_breadcrumb_test.settings');
if ($config->get('hide') && $node->getTitle() == "you can't see me" && $operation == 'view') {
$access = new AccessResultForbidden();
}
else {
$access = new AccessResultNeutral();
}
$access->addCacheableDependency($config);
$access->addCacheableDependency($node);
return $access;
}

View file

@ -0,0 +1,9 @@
# Schema for the configuration files of the book_breadcrumb_test module.
book_breadcrumb_test.settings:
type: config_object
label: 'Book Breadcrumb Test module settings'
mapping:
hide:
type: boolean
label: 'Setting for hiding content'

View file

@ -0,0 +1,6 @@
name: 'Book module tests'
type: module
description: 'Support module for book module testing.'
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,22 @@
<?php
/**
* @file
* Test module for testing the book module.
*
* This module's functionality depends on the following state variables:
* - book_test.debug_book_navigation_cache_context: Used in NodeQueryAlterTest to enable the
* node_access_all grant realm.
*
* @see \Drupal\book\Tests\BookTest::testBookNavigationCacheContext()
*/
/**
* Implements hook_page_attachments().
*/
function book_test_page_attachments(array &$page) {
$page['#cache']['tags'][] = 'book_test.debug_book_navigation_cache_context';
if (\Drupal::state()->get('book_test.debug_book_navigation_cache_context', FALSE)) {
drupal_set_message(\Drupal::service('cache_contexts_manager')->convertTokensToKeys(['route.book_navigation'])->getKeys()[0]);
}
}

View file

@ -0,0 +1,9 @@
name: 'Book test views'
type: module
description: 'Provides default views for views book tests.'
package: Testing
version: VERSION
core: 8.x
dependencies:
- book
- views

View file

@ -0,0 +1,160 @@
<?php
namespace Drupal\Tests\book\FunctionalJavascript;
use Behat\Mink\Exception\ExpectationException;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
use Drupal\node\Entity\Node;
/**
* Tests Book javascript functionality.
*
* @group book
*/
class BookJavascriptTest extends JavascriptTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['book'];
/**
* Tests re-ordering of books.
*/
public function testBookOrdering() {
$book = Node::create([
'type' => 'book',
'title' => 'Book',
'book' => ['bid' => 'new'],
]);
$book->save();
$page1 = Node::create([
'type' => 'book',
'title' => '1st page',
'book' => ['bid' => $book->id(), 'pid' => $book->id(), 'weight' => 0],
]);
$page1->save();
$page2 = Node::create([
'type' => 'book',
'title' => '2nd page',
'book' => ['bid' => $book->id(), 'pid' => $book->id(), 'weight' => 1],
]);
$page2->save();
// Head to admin screen and attempt to re-order.
$this->drupalLogin($this->drupalCreateUser(['administer book outlines']));
$this->drupalGet('admin/structure/book/' . $book->id());
$page = $this->getSession()->getPage();
$weight_select1 = $page->findField("table[book-admin-{$page1->id()}][weight]");
$weight_select2 = $page->findField("table[book-admin-{$page2->id()}][weight]");
// Check that rows weight selects are hidden.
$this->assertFalse($weight_select1->isVisible());
$this->assertFalse($weight_select2->isVisible());
// Check that '2nd page' row is heavier than '1st page' row.
$this->assertGreaterThan($weight_select1->getValue(), $weight_select2->getValue());
// Check that '1st page' precedes the '2nd page'.
$this->assertOrderInPage(['1st page', '2nd page']);
// Check that the 'unsaved changes' text is not present in the message area.
$this->assertSession()->pageTextNotContains('You have unsaved changes.');
// Drag and drop the '1st page' row over the '2nd page' row.
// @todo: Test also the reverse, '2nd page' over '1st page', when
// https://www.drupal.org/node/2769825 is fixed.
// @see https://www.drupal.org/node/2769825
$dragged = $this->xpath("//tr[@data-drupal-selector='edit-table-book-admin-{$page1->id()}']//a[@class='tabledrag-handle']")[0];
$target = $this->xpath("//tr[@data-drupal-selector='edit-table-book-admin-{$page2->id()}']//a[@class='tabledrag-handle']")[0];
$dragged->dragTo($target);
// Give javascript some time to manipulate the DOM.
$this->assertJsCondition('jQuery(".tabledrag-changed-warning").is(":visible")');
// Check that the 'unsaved changes' text appeared in the message area.
$this->assertSession()->pageTextContains('You have unsaved changes.');
// Check that '2nd page' page precedes the '1st page'.
$this->assertOrderInPage(['2nd page', '1st page']);
$this->submitForm([], 'Save book pages');
$this->assertSession()->pageTextContains(new FormattableMarkup('Updated book @book.', ['@book' => $book->getTitle()]));
// Check that page reordering was done in the backend for drag-n-drop.
$page1 = Node::load($page1->id());
$page2 = Node::load($page2->id());
$this->assertGreaterThan($page2->book['weight'], $page1->book['weight']);
// Check again that '2nd page' is on top after form submit in the UI.
$this->assertOrderInPage(['2nd page', '1st page']);
// Toggle row weight selects as visible.
$page->findButton('Show row weights')->click();
// Check that rows weight selects are visible.
$this->assertTrue($weight_select1->isVisible());
$this->assertTrue($weight_select2->isVisible());
// Check that '1st page' row became heavier than '2nd page' row.
$this->assertGreaterThan($weight_select2->getValue(), $weight_select1->getValue());
// Reverse again using the weight fields. Use the current values so the test
// doesn't rely on knowing the values in the select boxes.
$value1 = $weight_select1->getValue();
$value2 = $weight_select2->getValue();
$weight_select1->setValue($value2);
$weight_select2->setValue($value1);
// Toggle row weight selects back to hidden.
$page->findButton('Hide row weights')->click();
// Check that rows weight selects are hidden again.
$this->assertFalse($weight_select1->isVisible());
$this->assertFalse($weight_select2->isVisible());
$this->submitForm([], 'Save book pages');
$this->assertSession()->pageTextContains(new FormattableMarkup('Updated book @book.', ['@book' => $book->getTitle()]));
// Check that the '1st page' is first again.
$this->assertOrderInPage(['1st page', '2nd page']);
// Check that page reordering was done in the backend for manual weight
// field usage.
$page1 = Node::load($page1->id());
$page2 = Node::load($page2->id());
$this->assertGreaterThan($page2->book['weight'], $page1->book['weight']);
}
/**
* Asserts that several pieces of markup are in a given order in the page.
*
* @param string[] $items
* An ordered list of strings.
*
* @throws \Behat\Mink\Exception\ExpectationException
* When any of the given string is not found.
*
* @todo Remove this once https://www.drupal.org/node/2817657 is committed.
*/
protected function assertOrderInPage(array $items) {
$session = $this->getSession();
$text = $session->getPage()->getHtml();
$strings = [];
foreach ($items as $item) {
if (($pos = strpos($text, $item)) === FALSE) {
throw new ExpectationException("Cannot find '$item' in the page", $session->getDriver());
}
$strings[$pos] = $item;
}
ksort($strings);
$ordered = implode(', ', array_map(function ($item) {
return "'$item'";
}, $items));
$this->assertSame($items, array_values($strings), "Found strings, ordered as: $ordered.");
}
}

View file

@ -0,0 +1,94 @@
<?php
namespace Drupal\Tests\book\Kernel;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests that the Book module cannot be uninstalled if books exist.
*
* @group book
*/
class BookUninstallTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user', 'field', 'filter', 'text', 'node', 'book'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installEntitySchema('node');
$this->installSchema('book', array('book'));
$this->installSchema('node', array('node_access'));
$this->installConfig(array('node', 'book', 'field'));
// For uninstall to work.
$this->installSchema('user', array('users_data'));
}
/**
* Tests the book_system_info_alter() method.
*/
public function testBookUninstall() {
// No nodes exist.
$validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
$this->assertEqual([], $validation_reasons, 'The book module is not required.');
$content_type = NodeType::create(array(
'type' => $this->randomMachineName(),
'name' => $this->randomString(),
));
$content_type->save();
$book_config = $this->config('book.settings');
$allowed_types = $book_config->get('allowed_types');
$allowed_types[] = $content_type->id();
$book_config->set('allowed_types', $allowed_types)->save();
$node = Node::create(array('title' => $this->randomString(), 'type' => $content_type->id()));
$node->book['bid'] = 'new';
$node->save();
// One node in a book but not of type book.
$validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
$this->assertEqual(['To uninstall Book, delete all content that is part of a book'], $validation_reasons['book']);
$book_node = Node::create(array('title' => $this->randomString(), 'type' => 'book'));
$book_node->book['bid'] = FALSE;
$book_node->save();
// Two nodes, one in a book but not of type book and one book node (which is
// not in a book).
$validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
$this->assertEqual(['To uninstall Book, delete all content that is part of a book'], $validation_reasons['book']);
$node->delete();
// One node of type book but not actually part of a book.
$validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
$this->assertEqual(['To uninstall Book, delete all content that has the Book content type'], $validation_reasons['book']);
$book_node->delete();
// No nodes exist therefore the book module is not required.
$module_data = _system_rebuild_module_data();
$this->assertFalse(isset($module_data['book']->info['required']), 'The book module is not required.');
$node = Node::create(array('title' => $this->randomString(), 'type' => $content_type->id()));
$node->save();
// One node exists but is not part of a book therefore the book module is
// not required.
$validation_reasons = \Drupal::service('module_installer')->validateUninstall(['book']);
$this->assertEqual([], $validation_reasons, 'The book module is not required.');
// Uninstall the Book module and check the node type is deleted.
\Drupal::service('module_installer')->uninstall(array('book'));
$this->assertNull(NodeType::load('book'), "The book node type does not exist.");
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace Drupal\Tests\book\Kernel\Migrate\d6;
use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Upgrade variables to book.settings.yml.
*
* @group migrate_drupal_6
*/
class MigrateBookConfigsTest extends MigrateDrupal6TestBase {
use SchemaCheckTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['book'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('d6_book_settings');
}
/**
* Tests migration of book variables to book.settings.yml.
*/
public function testBookSettings() {
$config = $this->config('book.settings');
$this->assertIdentical('book', $config->get('child_type'));
$this->assertIdentical('all pages', $config->get('block.navigation.mode'));
$this->assertIdentical(array('book'), $config->get('allowed_types'));
$this->assertConfigSchema(\Drupal::service('config.typed'), 'book.settings', $config->get());
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace Drupal\Tests\book\Kernel\Migrate\d6;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
use Drupal\node\Entity\Node;
/**
* Upgrade book structure.
*
* @group migrate_drupal_6
*/
class MigrateBookTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['book'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installSchema('book', ['book']);
$this->installSchema('node', ['node_access']);
$this->migrateContent();
$this->executeMigrations(['d6_node', 'd6_book']);
}
/**
* Tests the Drupal 6 book structure to Drupal 8 migration.
*/
public function testBook() {
$nodes = Node::loadMultiple(array(4, 5, 6, 7, 8));
$this->assertIdentical('4', $nodes[4]->book['bid']);
$this->assertIdentical('0', $nodes[4]->book['pid']);
$this->assertIdentical('4', $nodes[5]->book['bid']);
$this->assertIdentical('4', $nodes[5]->book['pid']);
$this->assertIdentical('4', $nodes[6]->book['bid']);
$this->assertIdentical('5', $nodes[6]->book['pid']);
$this->assertIdentical('4', $nodes[7]->book['bid']);
$this->assertIdentical('5', $nodes[7]->book['pid']);
$this->assertIdentical('8', $nodes[8]->book['bid']);
$this->assertIdentical('0', $nodes[8]->book['pid']);
$tree = \Drupal::service('book.manager')->bookTreeAllData(4);
$this->assertIdentical('4', $tree['49990 Node 4 4']['link']['nid']);
$this->assertIdentical('5', $tree['49990 Node 4 4']['below']['50000 Node 5 5']['link']['nid']);
$this->assertIdentical('6', $tree['49990 Node 4 4']['below']['50000 Node 5 5']['below']['50000 Node 6 6']['link']['nid']);
$this->assertIdentical('7', $tree['49990 Node 4 4']['below']['50000 Node 5 5']['below']['50000 Node 7 7']['link']['nid']);
$this->assertIdentical(array(), $tree['49990 Node 4 4']['below']['50000 Node 5 5']['below']['50000 Node 6 6']['below']);
$this->assertIdentical(array(), $tree['49990 Node 4 4']['below']['50000 Node 5 5']['below']['50000 Node 7 7']['below']);
}
}

View file

@ -0,0 +1,84 @@
<?php
namespace Drupal\Tests\book\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* @covers \Drupal\book\Plugin\migrate\source\d6\Book
* @group book
*/
class BookTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['book', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['book'] = [
[
'mlid' => '1',
'nid' => '4',
'bid' => '4',
],
];
$tests[0]['source_data']['menu_links'] = [
[
'menu_name' => 'book-toc-1',
'mlid' => '1',
'plid' => '0',
'link_path' => 'node/4',
'router_path' => 'node/%',
'link_title' => 'Test top book title',
'options' => 'a:0:{}',
'module' => 'book',
'hidden' => '0',
'external' => '0',
'has_children' => '1',
'expanded' => '0',
'weight' => '-10',
'depth' => '1',
'customized' => '0',
'p1' => '1',
'p2' => '0',
'p3' => '0',
'p4' => '0',
'p5' => '0',
'p6' => '0',
'p7' => '0',
'p8' => '0',
'p9' => '0',
'updated' => '0',
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'nid' => '4',
'bid' => '4',
'mlid' => '1',
'plid' => '0',
'weight' => '-10',
'p1' => '1',
'p2' => '0',
'p3' => '0',
'p4' => '0',
'p5' => '0',
'p6' => '0',
'p7' => '0',
'p8' => '0',
'p9' => '0',
],
];
return $tests;
}
}

View file

@ -0,0 +1,117 @@
<?php
namespace Drupal\Tests\book\Unit;
use Drupal\book\BookManager;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\book\BookManager
* @group book
*/
class BookManagerTest extends UnitTestCase {
/**
* The mocked entity manager.
*
* @var \Drupal\Core\Entity\EntityManager|\PHPUnit_Framework_MockObject_MockObject
*/
protected $entityManager;
/**
* The mocked config factory.
*
* @var \Drupal\Core\Config\ConfigFactory|\PHPUnit_Framework_MockObject_MockObject
*/
protected $configFactory;
/**
* The mocked translation manager.
*
* @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $translation;
/**
* The mocked renderer.
*
* @var \Drupal\Core\Render\RendererInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $renderer;
/**
* The tested book manager.
*
* @var \Drupal\book\BookManager
*/
protected $bookManager;
/**
* Book outline storage.
*
* @var \Drupal\book\BookOutlineStorageInterface
*/
protected $bookOutlineStorage;
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$this->translation = $this->getStringTranslationStub();
$this->configFactory = $this->getConfigFactoryStub(array());
$this->bookOutlineStorage = $this->getMock('Drupal\book\BookOutlineStorageInterface');
$this->renderer = $this->getMock('\Drupal\Core\Render\RendererInterface');
$this->bookManager = new BookManager($this->entityManager, $this->translation, $this->configFactory, $this->bookOutlineStorage, $this->renderer);
}
/**
* Tests the getBookParents() method.
*
* @dataProvider providerTestGetBookParents
*/
public function testGetBookParents($book, $parent, $expected) {
$this->assertEquals($expected, $this->bookManager->getBookParents($book, $parent));
}
/**
* Provides test data for testGetBookParents.
*
* @return array
* The test data.
*/
public function providerTestGetBookParents() {
$empty = array(
'p1' => 0,
'p2' => 0,
'p3' => 0,
'p4' => 0,
'p5' => 0,
'p6' => 0,
'p7' => 0,
'p8' => 0,
'p9' => 0,
);
return array(
// Provides a book without an existing parent.
array(
array('pid' => 0, 'nid' => 12),
array(),
array('depth' => 1, 'p1' => 12) + $empty,
),
// Provides a book with an existing parent.
array(
array('pid' => 11, 'nid' => 12),
array('nid' => 11, 'depth' => 1, 'p1' => 11,),
array('depth' => 2, 'p1' => 11, 'p2' => 12) + $empty,
),
// Provides a book with two existing parents.
array(
array('pid' => 11, 'nid' => 12),
array('nid' => 11, 'depth' => 2, 'p1' => 10, 'p2' => 11),
array('depth' => 3, 'p1' => 10, 'p2' => 11, 'p3' => 12) + $empty,
),
);
}
}

View file

@ -0,0 +1,98 @@
<?php
namespace Drupal\Tests\book\Unit;
use Drupal\simpletest\AssertHelperTrait;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\book\BookUninstallValidator
* @group book
*/
class BookUninstallValidatorTest extends UnitTestCase {
use AssertHelperTrait;
/**
* @var \Drupal\book\BookUninstallValidator|\PHPUnit_Framework_MockObject_MockObject
*/
protected $bookUninstallValidator;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->bookUninstallValidator = $this->getMockBuilder('Drupal\book\BookUninstallValidator')
->disableOriginalConstructor()
->setMethods(['hasBookOutlines', 'hasBookNodes'])
->getMock();
$this->bookUninstallValidator->setStringTranslation($this->getStringTranslationStub());
}
/**
* @covers ::validate
*/
public function testValidateNotBook() {
$this->bookUninstallValidator->expects($this->never())
->method('hasBookOutlines');
$this->bookUninstallValidator->expects($this->never())
->method('hasBookNodes');
$module = 'not_book';
$expected = [];
$reasons = $this->bookUninstallValidator->validate($module);
$this->assertSame($expected, $this->castSafeStrings($reasons));
}
/**
* @covers ::validate
*/
public function testValidateEntityQueryWithoutResults() {
$this->bookUninstallValidator->expects($this->once())
->method('hasBookOutlines')
->willReturn(FALSE);
$this->bookUninstallValidator->expects($this->once())
->method('hasBookNodes')
->willReturn(FALSE);
$module = 'book';
$expected = [];
$reasons = $this->bookUninstallValidator->validate($module);
$this->assertSame($expected, $this->castSafeStrings($reasons));
}
/**
* @covers ::validate
*/
public function testValidateEntityQueryWithResults() {
$this->bookUninstallValidator->expects($this->once())
->method('hasBookOutlines')
->willReturn(FALSE);
$this->bookUninstallValidator->expects($this->once())
->method('hasBookNodes')
->willReturn(TRUE);
$module = 'book';
$expected = ['To uninstall Book, delete all content that has the Book content type'];
$reasons = $this->bookUninstallValidator->validate($module);
$this->assertSame($expected, $this->castSafeStrings($reasons));
}
/**
* @covers ::validate
*/
public function testValidateOutlineStorage() {
$this->bookUninstallValidator->expects($this->once())
->method('hasBookOutlines')
->willReturn(TRUE);
$this->bookUninstallValidator->expects($this->never())
->method('hasBookNodes');
$module = 'book';
$expected = ['To uninstall Book, delete all content that is part of a book'];
$reasons = $this->bookUninstallValidator->validate($module);
$this->assertSame($expected, $this->castSafeStrings($reasons));
}
}

View file

@ -0,0 +1,65 @@
<?php
namespace Drupal\Tests\book\Unit\Menu;
use Drupal\Tests\Core\Menu\LocalTaskIntegrationTestBase;
/**
* Tests existence of book local tasks.
*
* @group book
*/
class BookLocalTasksTest extends LocalTaskIntegrationTestBase {
protected function setUp() {
$this->directoryList = array(
'book' => 'core/modules/book',
'node' => 'core/modules/node',
);
parent::setUp();
}
/**
* Tests local task existence.
*
* @dataProvider getBookAdminRoutes
*/
public function testBookAdminLocalTasks($route) {
$this->assertLocalTasks($route, array(
0 => array('book.admin', 'book.settings'),
));
}
/**
* Provides a list of routes to test.
*/
public function getBookAdminRoutes() {
return array(
array('book.admin'),
array('book.settings'),
);
}
/**
* Tests local task existence.
*
* @dataProvider getBookNodeRoutes
*/
public function testBookNodeLocalTasks($route) {
$this->assertLocalTasks($route, array(
0 => array('entity.node.book_outline_form', 'entity.node.canonical', 'entity.node.edit_form', 'entity.node.delete_form', 'entity.node.version_history',),
));
}
/**
* Provides a list of routes to test.
*/
public function getBookNodeRoutes() {
return array(
array('entity.node.canonical'),
array('entity.node.book_outline_form'),
);
}
}