annotate core/modules/book/tests/src/Functional/BookTestTrait.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Tests\book\Functional;
Chris@0 4
Chris@18 5 use Drupal\Core\Url;
Chris@17 6 use Drupal\Component\Render\FormattableMarkup;
Chris@0 7 use Drupal\Core\Entity\EntityInterface;
Chris@0 8
Chris@0 9 /**
Chris@0 10 * Provides common functionality for Book test classes.
Chris@0 11 */
Chris@0 12 trait BookTestTrait {
Chris@0 13
Chris@0 14 /**
Chris@0 15 * A book node.
Chris@0 16 *
Chris@0 17 * @var \Drupal\node\NodeInterface
Chris@0 18 */
Chris@0 19 protected $book;
Chris@0 20
Chris@0 21 /**
Chris@0 22 * A user with permission to create and edit books.
Chris@0 23 *
Chris@0 24 * @var \Drupal\Core\Session\AccountInterface
Chris@0 25 */
Chris@0 26 protected $bookAuthor;
Chris@0 27
Chris@0 28 /**
Chris@0 29 * Creates a new book with a page hierarchy.
Chris@0 30 *
Chris@0 31 * @param array $edit
Chris@0 32 * (optional) Field data in an associative array. Changes the current input
Chris@0 33 * fields (where possible) to the values indicated. Defaults to an empty
Chris@0 34 * array.
Chris@0 35 *
Chris@0 36 * @return \Drupal\node\NodeInterface[]
Chris@0 37 */
Chris@0 38 public function createBook($edit = []) {
Chris@0 39 // Create new book.
Chris@0 40 $this->drupalLogin($this->bookAuthor);
Chris@0 41
Chris@0 42 $this->book = $this->createBookNode('new', NULL, $edit);
Chris@0 43 $book = $this->book;
Chris@0 44
Chris@0 45 /*
Chris@0 46 * Add page hierarchy to book.
Chris@0 47 * Book
Chris@0 48 * |- Node 0
Chris@0 49 * |- Node 1
Chris@0 50 * |- Node 2
Chris@0 51 * |- Node 3
Chris@0 52 * |- Node 4
Chris@0 53 */
Chris@0 54 $nodes = [];
Chris@0 55 // Node 0.
Chris@0 56 $nodes[] = $this->createBookNode($book->id(), NULL, $edit);
Chris@0 57 // Node 1.
Chris@0 58 $nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid'], $edit);
Chris@0 59 // Node 2.
Chris@0 60 $nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid'], $edit);
Chris@0 61 // Node 3.
Chris@0 62 $nodes[] = $this->createBookNode($book->id(), NULL, $edit);
Chris@0 63 // Node 4.
Chris@0 64 $nodes[] = $this->createBookNode($book->id(), NULL, $edit);
Chris@0 65
Chris@0 66 $this->drupalLogout();
Chris@0 67
Chris@0 68 return $nodes;
Chris@0 69 }
Chris@0 70
Chris@0 71 /**
Chris@0 72 * Checks the outline of sub-pages; previous, up, and next.
Chris@0 73 *
Chris@0 74 * Also checks the printer friendly version of the outline.
Chris@0 75 *
Chris@0 76 * @param \Drupal\Core\Entity\EntityInterface $node
Chris@0 77 * Node to check.
Chris@0 78 * @param $nodes
Chris@0 79 * Nodes that should be in outline.
Chris@0 80 * @param $previous
Chris@0 81 * Previous link node.
Chris@0 82 * @param $up
Chris@0 83 * Up link node.
Chris@0 84 * @param $next
Chris@0 85 * Next link node.
Chris@0 86 * @param array $breadcrumb
Chris@0 87 * The nodes that should be displayed in the breadcrumb.
Chris@0 88 */
Chris@0 89 public function checkBookNode(EntityInterface $node, $nodes, $previous, $up, $next, array $breadcrumb) {
Chris@0 90 // $number does not use drupal_static as it should not be reset
Chris@0 91 // since it uniquely identifies each call to checkBookNode().
Chris@0 92 static $number = 0;
Chris@0 93 $this->drupalGet('node/' . $node->id());
Chris@0 94
Chris@0 95 // Check outline structure.
Chris@0 96 if ($nodes !== NULL) {
Chris@0 97 $this->assertPattern($this->generateOutlinePattern($nodes), format_string('Node @number outline confirmed.', ['@number' => $number]));
Chris@0 98 }
Chris@0 99 else {
Chris@0 100 $this->pass(format_string('Node %number does not have outline.', ['%number' => $number]));
Chris@0 101 }
Chris@0 102
Chris@0 103 // Check previous, up, and next links.
Chris@0 104 if ($previous) {
Chris@0 105 /** @var \Drupal\Core\Url $url */
Chris@18 106 $url = $previous->toUrl();
Chris@0 107 $url->setOptions(['attributes' => ['rel' => ['prev'], 'title' => t('Go to previous page')]]);
Chris@17 108 $text = new FormattableMarkup('<b>‹</b> @label', ['@label' => $previous->label()]);
Chris@0 109 $this->assertRaw(\Drupal::l($text, $url), 'Previous page link found.');
Chris@0 110 }
Chris@0 111
Chris@0 112 if ($up) {
Chris@0 113 /** @var \Drupal\Core\Url $url */
Chris@18 114 $url = $up->toUrl();
Chris@0 115 $url->setOptions(['attributes' => ['title' => t('Go to parent page')]]);
Chris@0 116 $this->assertRaw(\Drupal::l('Up', $url), 'Up page link found.');
Chris@0 117 }
Chris@0 118
Chris@0 119 if ($next) {
Chris@0 120 /** @var \Drupal\Core\Url $url */
Chris@18 121 $url = $next->toUrl();
Chris@0 122 $url->setOptions(['attributes' => ['rel' => ['next'], 'title' => t('Go to next page')]]);
Chris@17 123 $text = new FormattableMarkup('@label <b>›</b>', ['@label' => $next->label()]);
Chris@0 124 $this->assertRaw(\Drupal::l($text, $url), 'Next page link found.');
Chris@0 125 }
Chris@0 126
Chris@0 127 // Compute the expected breadcrumb.
Chris@0 128 $expected_breadcrumb = [];
Chris@18 129 $expected_breadcrumb[] = Url::fromRoute('<front>')->toString();
Chris@0 130 foreach ($breadcrumb as $a_node) {
Chris@18 131 $expected_breadcrumb[] = $a_node->toUrl()->toString();
Chris@0 132 }
Chris@0 133
Chris@0 134 // Fetch links in the current breadcrumb.
Chris@0 135 $links = $this->xpath('//nav[@class="breadcrumb"]/ol/li/a');
Chris@0 136 $got_breadcrumb = [];
Chris@0 137 foreach ($links as $link) {
Chris@0 138 $got_breadcrumb[] = $link->getAttribute('href');
Chris@0 139 }
Chris@0 140
Chris@0 141 // Compare expected and got breadcrumbs.
Chris@0 142 $this->assertIdentical($expected_breadcrumb, $got_breadcrumb, 'The breadcrumb is correctly displayed on the page.');
Chris@0 143
Chris@0 144 // Check printer friendly version.
Chris@0 145 $this->drupalGet('book/export/html/' . $node->id());
Chris@0 146 $this->assertText($node->label(), 'Printer friendly title found.');
Chris@0 147 $this->assertRaw($node->body->processed, 'Printer friendly body found.');
Chris@0 148
Chris@0 149 $number++;
Chris@0 150 }
Chris@0 151
Chris@0 152 /**
Chris@0 153 * Creates a regular expression to check for the sub-nodes in the outline.
Chris@0 154 *
Chris@0 155 * @param array $nodes
Chris@0 156 * An array of nodes to check in outline.
Chris@0 157 *
Chris@0 158 * @return string
Chris@0 159 * A regular expression that locates sub-nodes of the outline.
Chris@0 160 */
Chris@0 161 public function generateOutlinePattern($nodes) {
Chris@0 162 $outline = '';
Chris@0 163 foreach ($nodes as $node) {
Chris@0 164 $outline .= '(node\/' . $node->id() . ')(.*?)(' . $node->label() . ')(.*?)';
Chris@0 165 }
Chris@0 166
Chris@0 167 return '/<nav id="book-navigation-' . $this->book->id() . '"(.*?)<ul(.*?)' . $outline . '<\/ul>/s';
Chris@0 168 }
Chris@0 169
Chris@0 170 /**
Chris@0 171 * Creates a book node.
Chris@0 172 *
Chris@0 173 * @param int|string $book_nid
Chris@0 174 * A book node ID or set to 'new' to create a new book.
Chris@0 175 * @param int|null $parent
Chris@0 176 * (optional) Parent book reference ID. Defaults to NULL.
Chris@0 177 * @param array $edit
Chris@0 178 * (optional) Field data in an associative array. Changes the current input
Chris@0 179 * fields (where possible) to the values indicated. Defaults to an empty
Chris@0 180 * array.
Chris@0 181 *
Chris@0 182 * @return \Drupal\node\NodeInterface
Chris@0 183 * The created node.
Chris@0 184 */
Chris@0 185 public function createBookNode($book_nid, $parent = NULL, $edit = []) {
Chris@0 186 // $number does not use drupal_static as it should not be reset
Chris@0 187 // since it uniquely identifies each call to createBookNode().
Chris@0 188 // Used to ensure that when sorted nodes stay in same order.
Chris@0 189 static $number = 0;
Chris@0 190
Chris@0 191 $edit['title[0][value]'] = str_pad($number, 2, '0', STR_PAD_LEFT) . ' - SimpleTest test node ' . $this->randomMachineName(10);
Chris@0 192 $edit['body[0][value]'] = 'SimpleTest test body ' . $this->randomMachineName(32) . ' ' . $this->randomMachineName(32);
Chris@0 193 $edit['book[bid]'] = $book_nid;
Chris@0 194
Chris@0 195 if ($parent !== NULL) {
Chris@0 196 $this->drupalPostForm('node/add/book', $edit, t('Change book (update list of parents)'));
Chris@0 197
Chris@0 198 $edit['book[pid]'] = $parent;
Chris@0 199 $this->drupalPostForm(NULL, $edit, t('Save'));
Chris@0 200 // Make sure the parent was flagged as having children.
Chris@0 201 $parent_node = \Drupal::entityManager()->getStorage('node')->loadUnchanged($parent);
Chris@0 202 $this->assertFalse(empty($parent_node->book['has_children']), 'Parent node is marked as having children');
Chris@0 203 }
Chris@0 204 else {
Chris@0 205 $this->drupalPostForm('node/add/book', $edit, t('Save'));
Chris@0 206 }
Chris@0 207
Chris@0 208 // Check to make sure the book node was created.
Chris@0 209 $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
Chris@0 210 $this->assertNotNull(($node === FALSE ? NULL : $node), 'Book node found in database.');
Chris@0 211 $number++;
Chris@0 212
Chris@0 213 return $node;
Chris@0 214 }
Chris@0 215
Chris@0 216 }