You are here

public function BigPipeTest::testBigPipe in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/big_pipe/tests/src/Functional/BigPipeTest.php \Drupal\Tests\big_pipe\Functional\BigPipeTest::testBigPipe()

Tests BigPipe-delivered HTML responses when JavaScript is enabled.

Covers:

See also

\Drupal\big_pipe_test\BigPipePlaceholderTestCases

File

core/modules/big_pipe/tests/src/Functional/BigPipeTest.php, line 148

Class

BigPipeTest
Tests BigPipe's no-JS detection & response delivery (with and without JS).

Namespace

Drupal\Tests\big_pipe\Functional

Code

public function testBigPipe() {

  // Simulate production.
  $this
    ->config('system.logging')
    ->set('error_level', ERROR_REPORTING_HIDE)
    ->save();
  $this
    ->drupalLogin($this->rootUser);
  $this
    ->assertSessionCookieExists(TRUE);
  $this
    ->assertBigPipeNoJsCookieExists(FALSE);
  $connection = Database::getConnection();
  $log_count = $connection
    ->select('watchdog')
    ->countQuery()
    ->execute()
    ->fetchField();

  // By not calling performMetaRefresh() here, we simulate JavaScript being
  // enabled, because as far as the BigPipe module is concerned, JavaScript is
  // enabled in the browser as long as the BigPipe no-JS cookie is *not* set.
  // @see setUp()
  // @see performMetaRefresh()
  $this
    ->drupalGet(Url::fromRoute('big_pipe_test'));
  $this
    ->assertBigPipeResponseHeadersPresent();
  $this
    ->assertSession()
    ->responseHeaderNotContains('X-Drupal-Cache-Tags', 'cache_tag_set_in_lazy_builder');
  $this
    ->setCsrfTokenSeedInTestEnvironment();
  $cases = $this
    ->getTestCases();
  $this
    ->assertBigPipeNoJsPlaceholders([
    $cases['edge_case__invalid_html']->bigPipeNoJsPlaceholder => $cases['edge_case__invalid_html']->embeddedHtmlResponse,
    $cases['html_attribute_value']->bigPipeNoJsPlaceholder => $cases['html_attribute_value']->embeddedHtmlResponse,
    $cases['html_attribute_value_subset']->bigPipeNoJsPlaceholder => $cases['html_attribute_value_subset']->embeddedHtmlResponse,
  ]);
  $this
    ->assertBigPipePlaceholders([
    $cases['html']->bigPipePlaceholderId => Json::encode($cases['html']->embeddedAjaxResponseCommands),
    $cases['edge_case__html_non_lazy_builder']->bigPipePlaceholderId => Json::encode($cases['edge_case__html_non_lazy_builder']->embeddedAjaxResponseCommands),
    $cases['exception__lazy_builder']->bigPipePlaceholderId => NULL,
    $cases['exception__embedded_response']->bigPipePlaceholderId => NULL,
  ], [
    0 => $cases['edge_case__html_non_lazy_builder']->bigPipePlaceholderId,
    // The 'html' case contains the 'status messages' placeholder, which is
    // always rendered last.
    1 => $cases['html']->bigPipePlaceholderId,
  ]);
  $this
    ->assertSession()
    ->responseContains('</body>');

  // Verifying BigPipe assets are present.
  $this
    ->assertFalse(empty($this
    ->getDrupalSettings()), 'drupalSettings present.');
  $this
    ->assertContains('big_pipe/big_pipe', explode(',', $this
    ->getDrupalSettings()['ajaxPageState']['libraries']), 'BigPipe asset library is present.');

  // Verify that the two expected exceptions are logged as errors.
  $this
    ->assertEquals($log_count + 2, (int) $connection
    ->select('watchdog')
    ->countQuery()
    ->execute()
    ->fetchField(), 'Two new watchdog entries.');

  // Using dynamic select queries with the method range() allows contrib
  // database drivers the ability to insert their own limit and offset
  // functionality.
  $records = $connection
    ->select('watchdog', 'w')
    ->fields('w')
    ->orderBy('wid', 'DESC')
    ->range(0, 2)
    ->execute()
    ->fetchAll();
  $this
    ->assertEquals(RfcLogLevel::ERROR, $records[0]->severity);
  $this
    ->assertStringContainsString('Oh noes!', (string) unserialize($records[0]->variables)['@message']);
  $this
    ->assertEquals(RfcLogLevel::ERROR, $records[1]->severity);
  $this
    ->assertStringContainsString('You are not allowed to say llamas are not cool!', (string) unserialize($records[1]->variables)['@message']);

  // Verify that 4xx responses work fine. (4xx responses are handled by
  // subrequests to a route pointing to a controller with the desired output.)
  $this
    ->drupalGet(Url::fromUri('base:non-existing-path'));

  // Simulate development.
  // Verifying BigPipe provides useful error output when an error occurs
  // while rendering a placeholder if verbose error logging is enabled.
  $this
    ->config('system.logging')
    ->set('error_level', ERROR_REPORTING_DISPLAY_VERBOSE)
    ->save();
  $this
    ->drupalGet(Url::fromRoute('big_pipe_test'));

  // The 'edge_case__html_exception' case throws an exception.
  $this
    ->assertSession()
    ->pageTextContains('The website encountered an unexpected error. Please try again later');
  $this
    ->assertSession()
    ->pageTextContains('You are not allowed to say llamas are not cool!');

  // Check that stop signal and closing body tag are absent.
  $this
    ->assertSession()
    ->responseNotContains(BigPipe::STOP_SIGNAL);
  $this
    ->assertSession()
    ->responseNotContains('</body>');

  // The exception is expected. Do not interpret it as a test failure.
  unlink($this->root . '/' . $this->siteDirectory . '/error.log');
}