BookTest.php 22.2 KB
Newer Older
1
2
<?php

3
namespace Drupal\Tests\book\Functional;
4

5
use Drupal\Component\Render\FormattableMarkup;
6
use Drupal\Core\Cache\Cache;
7
use Drupal\Tests\BrowserTestBase;
8
use Drupal\user\RoleInterface;
9

10
/**
11
12
13
 * Create a book, add pages, and test book interface.
 *
 * @group book
14
 */
15
class BookTest extends BrowserTestBase {
16

17
18
  use BookTestTrait;

19
  /**
20
   * Modules to install.
21
22
23
   *
   * @var array
   */
24
25
26
27
28
29
  protected static $modules = [
    'book',
    'block',
    'node_access_test',
    'book_test',
  ];
30

31
32
33
34
35
  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'classy';

36
37
38
39
40
  /**
   * A user with permission to view a book and access printer-friendly version.
   *
   * @var object
   */
41
  protected $webUser;
42
43
44
45
46
47

  /**
   * A user with permission to create and edit books and to administer blocks.
   *
   * @var object
   */
48
  protected $adminUser;
49

50
51
52
53
54
55
56
  /**
   * A user without the 'node test view' permission.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $webUserWithoutNodeAccess;

57
58
59
  /**
   * {@inheritdoc}
   */
60
  protected function setUp(): void {
61
    parent::setUp();
62
    $this->drupalPlaceBlock('system_breadcrumb_block');
63
    $this->drupalPlaceBlock('page_title_block');
64
65
66

    // node_access_test requires a node_access_rebuild().
    node_access_rebuild();
67

68
    // Create users.
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    $this->bookAuthor = $this->drupalCreateUser([
      'create new books',
      'create book content',
      'edit own book content',
      'add content to books',
    ]);
    $this->webUser = $this->drupalCreateUser([
      'access printer-friendly version',
      'node test view',
    ]);
    $this->webUserWithoutNodeAccess = $this->drupalCreateUser([
      'access printer-friendly version',
    ]);
    $this->adminUser = $this->drupalCreateUser([
      'create new books',
      'create book content',
      'edit any book content',
      'delete any book content',
      'add content to books',
      'administer blocks',
      'administer permissions',
      'administer book outlines',
      'node test view',
      'administer content types',
      'administer site configuration',
    ]);
95
  }
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  /**
   * Tests the book navigation cache context.
   *
   * @see \Drupal\book\Cache\BookNavigationCacheContext
   */
  public function testBookNavigationCacheContext() {
    // Create a page node.
    $this->drupalCreateContentType(['type' => 'page']);
    $page = $this->drupalCreateNode();

    // Create a book, consisting of book nodes.
    $book_nodes = $this->createBook();

    // Enable the debug output.
    \Drupal::state()->set('book_test.debug_book_navigation_cache_context', TRUE);
112
    Cache::invalidateTags(['book_test.debug_book_navigation_cache_context']);
113
114
115
116

    $this->drupalLogin($this->bookAuthor);

    // On non-node route.
117
    $this->drupalGet($this->adminUser->toUrl());
118
119
120
    $this->assertRaw('[route.book_navigation]=book.none');

    // On non-book node route.
121
    $this->drupalGet($page->toUrl());
122
123
124
    $this->assertRaw('[route.book_navigation]=book.none');

    // On book node route.
125
    $this->drupalGet($book_nodes[0]->toUrl());
126
    $this->assertRaw('[route.book_navigation]=0|2|3');
127
    $this->drupalGet($book_nodes[1]->toUrl());
128
    $this->assertRaw('[route.book_navigation]=0|2|3|4');
129
    $this->drupalGet($book_nodes[2]->toUrl());
130
    $this->assertRaw('[route.book_navigation]=0|2|3|5');
131
    $this->drupalGet($book_nodes[3]->toUrl());
132
    $this->assertRaw('[route.book_navigation]=0|2|6');
133
    $this->drupalGet($book_nodes[4]->toUrl());
134
135
136
    $this->assertRaw('[route.book_navigation]=0|2|7');
  }

137
138
139
  /**
   * Tests saving the book outline on an empty book.
   */
140
  public function testEmptyBook() {
141
    // Create a new empty book.
142
    $this->drupalLogin($this->bookAuthor);
143
144
145
146
    $book = $this->createBookNode('new');
    $this->drupalLogout();

    // Log in as a user with access to the book outline and save the form.
147
    $this->drupalLogin($this->adminUser);
148
149
    $this->drupalPostForm('admin/structure/book/' . $book->id(), [], t('Save book pages'));
    $this->assertText(t('Updated book @book.', ['@book' => $book->label()]));
150
151
  }

152
  /**
153
   * Tests book functionality through node interfaces.
154
   */
155
  public function testBook() {
156
157
158
    // Create new book.
    $nodes = $this->createBook();
    $book = $this->book;
159

160
    $this->drupalLogin($this->webUser);
161

162
163
    // Check that book pages display along with the correct outlines and
    // previous/next links.
164
165
166
167
168
169
    $this->checkBookNode($book, [$nodes[0], $nodes[3], $nodes[4]], FALSE, FALSE, $nodes[0], []);
    $this->checkBookNode($nodes[0], [$nodes[1], $nodes[2]], $book, $book, $nodes[1], [$book]);
    $this->checkBookNode($nodes[1], NULL, $nodes[0], $nodes[0], $nodes[2], [$book, $nodes[0]]);
    $this->checkBookNode($nodes[2], NULL, $nodes[1], $nodes[0], $nodes[3], [$book, $nodes[0]]);
    $this->checkBookNode($nodes[3], NULL, $nodes[2], $book, $nodes[4], [$book]);
    $this->checkBookNode($nodes[4], NULL, $nodes[3], $book, FALSE, [$book]);
170
171

    $this->drupalLogout();
172
    $this->drupalLogin($this->bookAuthor);
173
174
175
176
177

    // Check the presence of expected cache tags.
    $this->drupalGet('node/add/book');
    $this->assertCacheTag('config:book.settings');

178
179
180
181
182
183
184
185
186
187
    /*
     * Add Node 5 under Node 3.
     * Book
     *  |- Node 0
     *   |- Node 1
     *   |- Node 2
     *  |- Node 3
     *   |- Node 5
     *  |- Node 4
     */
188
189
    // Node 5.
    $nodes[] = $this->createBookNode($book->id(), $nodes[3]->book['nid']);
190
    $this->drupalLogout();
191
    $this->drupalLogin($this->webUser);
192
    // Verify the new outline - make sure we don't get stale cached data.
193
194
    $this->checkBookNode($nodes[3], [$nodes[5]], $nodes[2], $book, $nodes[5], [$book]);
    $this->checkBookNode($nodes[4], NULL, $nodes[5], $book, FALSE, [$book]);
195
    $this->drupalLogout();
196
    // Create a second book, and move an existing book page into it.
197
    $this->drupalLogin($this->bookAuthor);
198
    $other_book = $this->createBookNode('new');
199
    $node = $this->createBookNode($book->id());
200
    $edit = ['book[bid]' => $other_book->id()];
201
    $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
202
203

    $this->drupalLogout();
204
    $this->drupalLogin($this->webUser);
205
206
207
208
209

    // Check that the nodes in the second book are displayed correctly.
    // First we must set $this->book to the second book, so that the
    // correct regex will be generated for testing the outline.
    $this->book = $other_book;
210
211
    $this->checkBookNode($other_book, [$node], FALSE, FALSE, $node, []);
    $this->checkBookNode($node, NULL, $other_book, $other_book, FALSE, [$other_book]);
212

213
    // Test that we can save a book programmatically.
214
    $this->drupalLogin($this->bookAuthor);
215
216
    $book = $this->createBookNode('new');
    $book->save();
217
218
  }

219
220
221
  /**
   * Tests book export ("printer-friendly version") functionality.
   */
222
  public function testBookExport() {
223
224
    // Create a book.
    $nodes = $this->createBook();
225

226
    // Log in as web user and view printer-friendly version.
227
    $this->drupalLogin($this->webUser);
228
    $this->drupalGet('node/' . $this->book->id());
229
    $this->clickLink(t('Printer-friendly version'));
230

231
232
    // Make sure each part of the book is there.
    foreach ($nodes as $node) {
233
      $this->assertText($node->label(), 'Node title found in printer friendly version.');
234
      $this->assertRaw($node->body->processed, 'Node body found in printer friendly version.');
235
    }
236

237
    // Make sure we can't export an unsupported format.
238
    $this->drupalGet('book/export/foobar/' . $this->book->id());
239
    $this->assertSession()->statusCodeEquals(404);
240

241
242
    // Make sure we get a 404 on a not existing book node.
    $this->drupalGet('book/export/html/123');
243
    $this->assertSession()->statusCodeEquals(404);
244

245
246
    // Make sure an anonymous user cannot view printer-friendly version.
    $this->drupalLogout();
247

248
    // Load the book and verify there is no printer-friendly version link.
249
    $this->drupalGet('node/' . $this->book->id());
250
    $this->assertSession()->linkNotExists(t('Printer-friendly version'), 'Anonymous user is not shown link to printer-friendly version.');
251

252
    // Try getting the URL directly, and verify it fails.
253
    $this->drupalGet('book/export/html/' . $this->book->id());
254
    $this->assertSession()->statusCodeEquals(403);
255
256
257
258

    // Now grant anonymous users permission to view the printer-friendly
    // version and verify that node access restrictions still prevent them from
    // seeing it.
259
    user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, ['access printer-friendly version']);
260
    $this->drupalGet('book/export/html/' . $this->book->id());
261
    $this->assertSession()->statusCodeEquals(403);
262
  }
263

264
265
266
  /**
   * Tests the functionality of the book navigation block.
   */
267
  public function testBookNavigationBlock() {
268
    $this->drupalLogin($this->adminUser);
269

270
    // Enable the block.
271
    $block = $this->drupalPlaceBlock('book_navigation');
272

273
    // Give anonymous users the permission 'node test view'.
274
    $edit = [];
275
276
    $edit[RoleInterface::ANONYMOUS_ID . '[node test view]'] = TRUE;
    $this->drupalPostForm('admin/people/permissions/' . RoleInterface::ANONYMOUS_ID, $edit, t('Save permissions'));
277
    $this->assertText(t('The changes have been saved.'), "Permission 'node test view' successfully assigned to anonymous users.");
278

279
280
281
    // Test correct display of the block.
    $nodes = $this->createBook();
    $this->drupalGet('<front>');
282
    $this->assertText($block->label(), 'Book navigation block is displayed.');
283
    $this->assertText($this->book->label(), new FormattableMarkup('Link to book root (@title) is displayed.', ['@title' => $nodes[0]->label()]));
284
    $this->assertNoText($nodes[0]->label(), 'No links to individual book pages are displayed.');
285
  }
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  /**
   * Tests BookManager::getTableOfContents().
   */
  public function testGetTableOfContents() {
    // Create new book.
    $nodes = $this->createBook();
    $book = $this->book;

    $this->drupalLogin($this->bookAuthor);

    /*
     * Add Node 5 under Node 2.
     * Add Node 6, 7, 8, 9, 10, 11 under Node 3.
     * Book
     *  |- Node 0
     *   |- Node 1
     *   |- Node 2
     *    |- Node 5
     *  |- Node 3
     *   |- Node 6
     *    |- Node 7
     *     |- Node 8
     *      |- Node 9
     *       |- Node 10
     *        |- Node 11
     *  |- Node 4
     */
    foreach ([5 => 2, 6 => 3, 7 => 6, 8 => 7, 9 => 8, 10 => 9, 11 => 10] as $child => $parent) {
      $nodes[$child] = $this->createBookNode($book->id(), $nodes[$parent]->id());
    }
    $this->drupalGet($nodes[0]->toUrl('edit-form'));
318
    // Since Node 0 has children 2 levels deep, nodes 10 and 11 should not
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
    // appear in the selector.
    $this->assertNoOption('edit-book-pid', $nodes[10]->id());
    $this->assertNoOption('edit-book-pid', $nodes[11]->id());
    // Node 9 should be available as an option.
    $this->assertOption('edit-book-pid', $nodes[9]->id());

    // Get a shallow set of options.
    /** @var \Drupal\book\BookManagerInterface $manager */
    $manager = $this->container->get('book.manager');
    $options = $manager->getTableOfContents($book->id(), 3);
    $expected_nids = [$book->id(), $nodes[0]->id(), $nodes[1]->id(), $nodes[2]->id(), $nodes[3]->id(), $nodes[6]->id(), $nodes[4]->id()];
    $this->assertEqual(count($options), count($expected_nids));
    $diff = array_diff($expected_nids, array_keys($options));
    $this->assertTrue(empty($diff), 'Found all expected option keys');
    // Exclude Node 3.
334
335
    $options = $manager->getTableOfContents($book->id(), 3, [$nodes[3]->id()]);
    $expected_nids = [$book->id(), $nodes[0]->id(), $nodes[1]->id(), $nodes[2]->id(), $nodes[4]->id()];
336
337
338
339
340
    $this->assertEqual(count($options), count($expected_nids));
    $diff = array_diff($expected_nids, array_keys($options));
    $this->assertTrue(empty($diff), 'Found all expected option keys after excluding Node 3');
  }

341
  /**
342
   * Tests the book navigation block when an access module is installed.
343
   */
344
  public function testNavigationBlockOnAccessModuleInstalled() {
345
    $this->drupalLogin($this->adminUser);
346
    $block = $this->drupalPlaceBlock('book_navigation', ['block_mode' => 'book pages']);
347
348

    // Give anonymous users the permission 'node test view'.
349
    $edit = [];
350
351
    $edit[RoleInterface::ANONYMOUS_ID . '[node test view]'] = TRUE;
    $this->drupalPostForm('admin/people/permissions/' . RoleInterface::ANONYMOUS_ID, $edit, t('Save permissions'));
352
353
354
355
356
357
    $this->assertText(t('The changes have been saved.'), "Permission 'node test view' successfully assigned to anonymous users.");

    // Create a book.
    $this->createBook();

    // Test correct display of the block to registered users.
358
    $this->drupalLogin($this->webUser);
359
    $this->drupalGet('node/' . $this->book->id());
360
    $this->assertText($block->label(), 'Book navigation block is displayed to registered users.');
361
362
363
    $this->drupalLogout();

    // Test correct display of the block to anonymous users.
364
    $this->drupalGet('node/' . $this->book->id());
365
366
367
368
369
    $this->assertText($block->label(), 'Book navigation block is displayed to anonymous users.');

    // Test the 'book pages' block_mode setting.
    $this->drupalGet('<front>');
    $this->assertNoText($block->label(), 'Book navigation block is not shown on non-book pages.');
370
  }
371
372
373
374

  /**
   * Tests the access for deleting top-level book nodes.
   */
375
  public function testBookDelete() {
376
    $node_storage = $this->container->get('entity_type.manager')->getStorage('node');
377
378
    $nodes = $this->createBook();
    $this->drupalLogin($this->adminUser);
379
    $edit = [];
380

381
    // Ensure that the top-level book node cannot be deleted.
382
    $this->drupalGet('node/' . $this->book->id() . '/outline/remove');
383
    $this->assertSession()->statusCodeEquals(403);
384
385

    // Ensure that a child book node can be deleted.
386
    $this->drupalPostForm('node/' . $nodes[4]->id() . '/outline/remove', $edit, t('Remove'));
387
    $node_storage->resetCache([$nodes[4]->id()]);
388
389
390
    $node4 = $node_storage->load($nodes[4]->id());
    $this->assertTrue(empty($node4->book), 'Deleting child book node properly allowed.');

391
392
393
394
    // $nodes[4] is stale, trying to delete it directly will cause an error.
    $node4->delete();
    unset($nodes[4]);

395
    // Delete all child book nodes and retest top-level node deletion.
396
397
    $node_storage->delete($nodes);

398
    $this->drupalPostForm('node/' . $this->book->id() . '/outline/remove', $edit, t('Remove'));
399
    $node_storage->resetCache([$this->book->id()]);
400
401
402
403
404
405
    $node = $node_storage->load($this->book->id());
    $this->assertTrue(empty($node->book), 'Deleting childless top-level book node properly allowed.');

    // Tests directly deleting a book parent.
    $nodes = $this->createBook();
    $this->drupalLogin($this->adminUser);
406
    $this->drupalGet($this->book->toUrl('delete-form'));
407
408
    $this->assertRaw(t('%title is part of a book outline, and has associated child pages. If you proceed with deletion, the child pages will be relocated automatically.', ['%title' => $this->book->label()]));
    // Delete parent, and visit a child page.
409
410
    $this->drupalPostForm($this->book->toUrl('delete-form'), [], t('Delete'));
    $this->drupalGet($nodes[0]->toUrl());
411
    $this->assertSession()->statusCodeEquals(200);
412
413
414
415
416
417
418
419
420
421
    $this->assertText($nodes[0]->label());
    // The book parents should be updated.
    $node_storage = \Drupal::entityTypeManager()->getStorage('node');
    $node_storage->resetCache();
    $child = $node_storage->load($nodes[0]->id());
    $this->assertEqual($child->id(), $child->book['bid'], 'Child node book ID updated when parent is deleted.');
    // 3rd-level children should now be 2nd-level.
    $second = $node_storage->load($nodes[1]->id());
    $this->assertEqual($child->id(), $second->book['bid'], '3rd-level child node is now second level when top-level node is deleted.');
  }
422

423
424
425
426
  /**
   * Tests outline of a book.
   */
  public function testBookOutline() {
427
    $this->drupalLogin($this->bookAuthor);
428
429

    // Create new node not yet a book.
430
    $empty_book = $this->drupalCreateNode(['type' => 'book']);
431
    $this->drupalGet('node/' . $empty_book->id() . '/outline');
432
    $this->assertSession()->linkNotExists(t('Book outline'), 'Book Author is not allowed to outline');
433

434
    $this->drupalLogin($this->adminUser);
435
436
437
    $this->drupalGet('node/' . $empty_book->id() . '/outline');
    $this->assertRaw(t('Book outline'));
    $this->assertOptionSelected('edit-book-bid', 0, 'Node does not belong to a book');
438
    $this->assertSession()->linkNotExists(t('Remove from book outline'));
439

440
    $edit = [];
441
442
    $edit['book[bid]'] = '1';
    $this->drupalPostForm('node/' . $empty_book->id() . '/outline', $edit, t('Add to book outline'));
443
    $node = \Drupal::entityTypeManager()->getStorage('node')->load($empty_book->id());
444
445
446
447
448
449
450
    // Test the book array.
    $this->assertEqual($node->book['nid'], $empty_book->id());
    $this->assertEqual($node->book['bid'], $empty_book->id());
    $this->assertEqual($node->book['depth'], 1);
    $this->assertEqual($node->book['p1'], $empty_book->id());
    $this->assertEqual($node->book['pid'], '0');

451
    // Create new book.
452
    $this->drupalLogin($this->bookAuthor);
453
454
    $book = $this->createBookNode('new');

455
    $this->drupalLogin($this->adminUser);
456
457
    $this->drupalGet('node/' . $book->id() . '/outline');
    $this->assertRaw(t('Book outline'));
458
    $this->clickLink(t('Remove from book outline'));
459
    $this->assertRaw(t('Are you sure you want to remove %title from the book hierarchy?', ['%title' => $book->label()]));
460
461

    // Create a new node and set the book after the node was created.
462
463
    $node = $this->drupalCreateNode(['type' => 'book']);
    $edit = [];
464
465
    $edit['book[bid]'] = $node->id();
    $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
466
    $node = \Drupal::entityTypeManager()->getStorage('node')->load($node->id());
467
468
469
470
471
472
473
474
475
476
477

    // Test the book array.
    $this->assertEqual($node->book['nid'], $node->id());
    $this->assertEqual($node->book['bid'], $node->id());
    $this->assertEqual($node->book['depth'], 1);
    $this->assertEqual($node->book['p1'], $node->id());
    $this->assertEqual($node->book['pid'], '0');

    // Test the form itself.
    $this->drupalGet('node/' . $node->id() . '/edit');
    $this->assertOptionSelected('edit-book-bid', $node->id());
478
  }
479

480
481
482
483
484
485
486
  /**
   * Tests that saveBookLink() returns something.
   */
  public function testSaveBookLink() {
    $book_manager = \Drupal::service('book.manager');

    // Mock a link for a new book.
487
    $link = ['nid' => 1, 'has_children' => 0, 'original_bid' => 0, 'parent_depth_limit' => 8, 'pid' => 0, 'weight' => 0, 'bid' => 1];
488
489
490
491
492
493
494
495
496
497
498
499
    $new = TRUE;

    // Save the link.
    $return = $book_manager->saveBookLink($link, $new);

    // Add the link defaults to $link so we have something to compare to the return from saveBookLink().
    $link += $book_manager->getLinkDefaults($link['nid']);

    // Test the return from saveBookLink.
    $this->assertEqual($return, $link);
  }

500
501
502
503
504
505
506
  /**
   * Tests the listing of all books.
   */
  public function testBookListing() {
    // Create a new book.
    $this->createBook();

507
    // Must be a user with 'node test view' permission since node_access_test is installed.
508
    $this->drupalLogin($this->webUser);
509
510
511
512
513
514

    // Load the book page and assert the created book title is displayed.
    $this->drupalGet('book');

    $this->assertText($this->book->label(), 'The book title is displayed on the book listing page.');
  }
515
516
517
518
519
520
521
522
523

  /**
   * Tests the administrative listing of all books.
   */
  public function testAdminBookListing() {
    // Create a new book.
    $this->createBook();

    // Load the book page and assert the created book title is displayed.
524
    $this->drupalLogin($this->adminUser);
525
526
527
528
    $this->drupalGet('admin/structure/book');
    $this->assertText($this->book->label(), 'The book title is displayed on the administrative book listing page.');
  }

529
530
531
532
533
534
535
536
537
538
539
540
541
542
  /**
   * Tests the administrative listing of all book pages in a book.
   */
  public function testAdminBookNodeListing() {
    // Create a new book.
    $this->createBook();
    $this->drupalLogin($this->adminUser);

    // Load the book page list and assert the created book title is displayed
    // and action links are shown on list items.
    $this->drupalGet('admin/structure/book/' . $this->book->id());
    $this->assertText($this->book->label(), 'The book title is displayed on the administrative book listing page.');

    $elements = $this->xpath('//table//ul[@class="dropbutton"]/li/a');
543
    $this->assertEqual($elements[0]->getText(), 'View', 'View link is found from the list.');
544
545
  }

546
547
548
549
550
551
552
553
554
555
556
  /**
   * Ensure the loaded book in hook_node_load() does not depend on the user.
   */
  public function testHookNodeLoadAccess() {
    \Drupal::service('module_installer')->install(['node_access_test']);

    // Ensure that the loaded book in hook_node_load() does NOT depend on the
    // current user.
    $this->drupalLogin($this->bookAuthor);
    $this->book = $this->createBookNode('new');
    // Reset any internal static caching.
557
    $node_storage = \Drupal::entityTypeManager()->getStorage('node');
558
559
    $node_storage->resetCache();

560
    // Log in as user without access to the book node, so no 'node test view'
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
    // permission.
    // @see node_access_test_node_grants().
    $this->drupalLogin($this->webUserWithoutNodeAccess);
    $book_node = $node_storage->load($this->book->id());
    $this->assertTrue(!empty($book_node->book));
    $this->assertEqual($book_node->book['bid'], $this->book->id());

    // Reset the internal cache to retrigger the hook_node_load() call.
    $node_storage->resetCache();

    $this->drupalLogin($this->webUser);
    $book_node = $node_storage->load($this->book->id());
    $this->assertTrue(!empty($book_node->book));
    $this->assertEqual($book_node->book['bid'], $this->book->id());
  }

577
578
579
580
581
582
583
584
585
586
  /**
   * Tests the book navigation block when book is unpublished.
   *
   * There was a fatal error with "Show block only on book pages" block mode.
   */
  public function testBookNavigationBlockOnUnpublishedBook() {
    // Create a new book.
    $this->createBook();

    // Create administrator user.
587
588
589
590
591
    $administratorUser = $this->drupalCreateUser([
      'administer blocks',
      'administer nodes',
      'bypass node access',
    ]);
592
593
594
595
596
597
    $this->drupalLogin($administratorUser);

    // Enable the block with "Show block only on book pages" mode.
    $this->drupalPlaceBlock('book_navigation', ['block_mode' => 'book pages']);

    // Unpublish book node.
598
599
    $edit = ['status[value]' => FALSE];
    $this->drupalPostForm('node/' . $this->book->id() . '/edit', $edit, t('Save'));
600
601
602
603
604
605

    // Test node page.
    $this->drupalGet('node/' . $this->book->id());
    $this->assertText($this->book->label(), 'Unpublished book with "Show block only on book pages" book navigation settings.');
  }

606
}