Verified Commit cdefa18d authored by Dave Long's avatar Dave Long
Browse files

test: #3608939 Move/split remaining parts of StandardPerformanceTest and StandardJavascriptTest

By: gábor hojtsy
By: catch
By: berdir
parent 56b32bec
Loading
Loading
Loading
Loading
+0 −80
Changes for core/profiles/standard/tests/src/FunctionalJavascript/StandardJavascriptTest.php: 0 added lines, 80 removed lines.
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Tests\standard\FunctionalJavascript;

use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\node\Entity\Node;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Tests Standard installation profile JavaScript expectations.
 */
#[Group('standard')]
#[RunTestsInSeparateProcesses]
class StandardJavascriptTest extends WebDriverTestBase {

  /**
   * {@inheritdoc}
   */
  protected $profile = 'standard';

  /**
   * Tests BigPipe accelerates particular Standard installation profile routes.
   */
  public function testBigPipe(): void {
    // Standard profile does not include a content type by default.
    $this->drupalCreateContentType(['type' => 'test_content', 'name' => 'Test Content']);

    $this->drupalLogin($this->drupalCreateUser([
      'access content',
    ]));

    $node = Node::create(['type' => 'test_content'])
      ->setTitle($this->randomMachineName())
      ->setPromoted(TRUE)
      ->setPublished();
    $node->save();

    // Front page: Zero placeholders.
    $this->drupalGet('');
    $this->assertBigPipePlaceholderReplacementCount(0);

    // Front page with warm render caches: Zero placeholders.
    $this->drupalGet('');
    $this->assertBigPipePlaceholderReplacementCount(0);

    // Node page: Five placeholders.
    $this->drupalGet($node->toUrl());
    $this->assertBigPipePlaceholderReplacementCount(5);

    // Node page second request: Zero placeholders.
    $this->drupalGet($node->toUrl());
    $this->assertBigPipePlaceholderReplacementCount(0);
  }

  /**
   * Asserts the number of BigPipe placeholders that are replaced on the page.
   *
   * @param int $expected_count
   *   The expected number of BigPipe placeholders.
   */
  protected function assertBigPipePlaceholderReplacementCount($expected_count): void {
    $web_assert = $this->assertSession();
    if ($expected_count > 0) {
      $web_assert->waitForElement('css', 'script[data-big-pipe-event="stop"]');
    }
    $page = $this->getSession()->getPage();
    // Settings are removed as soon as they are processed.
    if ($expected_count === 0) {
      $this->assertArrayNotHasKey('bigPipePlaceholderIds', $this->getDrupalSettings());
    }
    else {
      $this->assertCount(0, $this->getDrupalSettings()['bigPipePlaceholderIds']);
    }
    $this->assertCount($expected_count, $page->findAll('css', 'script[data-big-pipe-replacement-for-placeholder-with-id]'));
  }

}
+5 −98
Changes for core/profiles/standard/tests/src/FunctionalJavascript/StandardPerformanceTest.php: 5 added lines, 98 removed lines.
Original line number Diff line number Diff line
@@ -4,11 +4,7 @@

namespace Drupal\Tests\standard\FunctionalJavascript;

use Drupal\Core\Cache\Cache;
use Drupal\FunctionalJavascriptTests\PerformanceTestBase;
use Drupal\Tests\PerformanceData;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
use Drupal\user\UserInterface;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
@@ -41,95 +37,27 @@ class StandardPerformanceTest extends PerformanceTestBase {
   */
  protected ?UserInterface $user = NULL;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    // Create a content type and node to test performance for.
    $this->drupalCreateContentType(['type' => 'test_content', 'name' => 'Test Content']);
    $this->drupalCreateNode(['type' => 'test_content']);
    // Grant the anonymous user the permission to look at user profiles.
    Role::loadOverrideFree(RoleInterface::ANONYMOUS_ID)->grantPermissions([
      'access user profiles',
    ])->save();
  }

  /**
   * Tests performance of the standard profile.
   */
  public function testStandardPerformance(): void {
    $this->testAnonymous();
    $this->testAdmin();
  }

  /**
   * Tests performance for anonymous users.
   */
  protected function testAnonymous(): void {
    // Request the front page, then immediately clear all object caches, so that
    // aggregates and image styles are created on disk but otherwise caches are
    // empty.
    $this->drupalGet('');
    // Give time for big pipe placeholders, asset aggregate requests, and post
    // response tasks to finish processing and write to any caches before
    // clearing caches again.
    sleep(2);
    foreach (Cache::getBins() as $bin) {
      $bin->deleteAll();
    }
    // Now visit a different page to warm some caches.
    $this->drupalGet('user/password');
    // Ensure everything finishes before we collect performance data.
    sleep(2);

    // Test frontpage.
    $performance_data = $this->collectPerformanceData(function () {
      $this->drupalGet('');
    }, 'standardFrontPage');
    $this->assertNoJavaScript($performance_data);
    $this->assertQueriesByName('standardFrontPage', $performance_data->getQueries());
    $this->assertMetricsByName('standardFrontPage', $performance_data);

    // Test node page.
    $performance_data = $this->collectPerformanceData(function () {
      $this->drupalGet('node/1');
    }, 'standardNodePage');

    $this->assertQueriesByName('standardNodePage', $performance_data->getQueries());
    $this->assertMetricsByName('standardNodePage', $performance_data);

    // Test user profile page.
    $this->user = $this->drupalCreateUser();
    $performance_data = $this->collectPerformanceData(function () {
      $this->drupalGet('user/' . $this->user->id());
    }, 'standardUserPage');
    $this->assertNoJavaScript($performance_data);
    $this->assertQueriesByName('standardUserPage', $performance_data->getQueries());
    $this->assertMetricsByName('standardUserPage', $performance_data);
  }

  /**
   * Tests performance of a logged-in admin user with the navigation toolbar.
   */
  protected function testAdmin(): void {
  public function testAdmin(): void {
    $admin_user = $this->drupalCreateUser();
    $admin_user->addRole('administrator');
    $admin_user->save();

    $this->drupalLogin($admin_user);
    // Request the node/1 page twice to ensure all cache collectors are fully
    // Request the front page twice to ensure all cache collectors are fully
    // warmed. The exact contents of cache collectors depends on the order in
    // which requests complete so this ensures that the second request completes
    // after asset aggregates are served.
    $this->drupalGet('node/1');
    $this->drupalGet('');
    sleep(1);
    $this->drupalGet('node/1');
    $this->drupalGet('');
    // Flush the dynamic page cache to simulate visiting a page that is not
    // already fully cached.
    \Drupal::cache('dynamic_page_cache')->deleteAll();
    $performance_data = $this->collectPerformanceData(function () {
      $this->drupalGet('node/1');
      $this->drupalGet('');
    }, 'testAdmin');

    $this->assertQueriesByName('testAdmin', $performance_data->getQueries());
@@ -140,25 +68,4 @@ protected function testAdmin(): void {
    $this->assertIsObject(\Drupal::cache('render')->get('navigation:navigation:[languages:language_interface]=en:[theme]=stark:[user.permissions]=is-admin'));
  }

  /**
   * Passes if no JavaScript is found on the page.
   *
   * @param \Drupal\Tests\PerformanceData $performance_data
   *   A PerformanceData value object.
   *
   * @internal
   */
  protected function assertNoJavaScript(PerformanceData $performance_data): void {
    // Ensure drupalSettings is not set.
    $settings = $this->getDrupalSettings();
    $this->assertEmpty($settings, 'drupalSettings is not set.');
    $this->assertSession()->responseNotMatches('/\.js/');
    $this->assertSame(0, $performance_data->getScriptCount());
  }

  /**
   * Provides an empty implementation to prevent the resetting of caches.
   */
  protected function refreshVariables(): void {}

}
+0 −19
Changes for core/profiles/standard/tests/src/FunctionalJavascript/StandardPerformanceTestAssertions/standardFrontPage.sql: 0 added lines, 19 removed lines.
Original line number Diff line number Diff line
SELECT "base_table"."id" AS "id", "base_table"."path" AS "path", "base_table"."alias" AS "alias", "base_table"."langcode" AS "langcode" FROM "path_alias" "base_table" WHERE ("base_table"."status" = 1) AND ("base_table"."alias" LIKE "/admin/welcome" ESCAPE '\\') AND ("base_table"."langcode" IN ("en", "und")) ORDER BY "base_table"."langcode" ASC, "base_table"."id" DESC
SELECT "name", "route", "fit" FROM "router" WHERE "pattern_outline" IN ( "/admin/welcome", "/admin/%", "/admin" ) AND "number_parts" >= 2
SELECT "name", "value" FROM "key_value" WHERE "name" IN ( "standard.show_welcome" ) AND "collection" = "state"
INSERT INTO "watchdog" ("uid", "type", "message", "variables", "severity", "link", "location", "referer", "hostname", "timestamp") VALUES (0, "access denied", "Path: @uri. %type: @message in %function (line %line of %file).", "WATCHDOG_DATA", 4, "", "LOCATION", "REFERER", "CLIENT_IP", "TIMESTAMP")
SELECT "base_table"."id" AS "id", "base_table"."path" AS "path", "base_table"."alias" AS "alias", "base_table"."langcode" AS "langcode" FROM "path_alias" "base_table" WHERE ("base_table"."status" = 1) AND ("base_table"."alias" LIKE "/system/403" ESCAPE '\\') AND ("base_table"."langcode" IN ("en", "und")) ORDER BY "base_table"."langcode" ASC, "base_table"."id" DESC
SELECT "name", "route", "fit" FROM "router" WHERE "pattern_outline" IN ( "/system/403", "/system/%", "/system" ) AND "number_parts" >= 2
SELECT "name", "route" FROM "router" WHERE "name" IN ( "<current>" )
SELECT 1 AS "expression" FROM "path_alias" "base_table" WHERE ("base_table"."status" = 1) AND ("base_table"."path" LIKE "/admin%" ESCAPE '\\') LIMIT 1 OFFSET 0
SELECT "name", "value" FROM "key_value" WHERE "name" IN ( "theme:stark" ) AND "collection" = "config.entity.key_store.block"
SELECT "name", "route" FROM "router" WHERE "name" IN ( "system.403" )
SELECT 1 AS "expression" FROM "path_alias" "base_table" WHERE ("base_table"."status" = 1) AND ("base_table"."path" LIKE "/system%" ESCAPE '\\') LIMIT 1 OFFSET 0
INSERT INTO "semaphore" ("name", "value", "expire") VALUES ("state:Drupal\Core\Cache\CacheCollector", "LOCK_ID", "EXPIRE")
DELETE FROM "semaphore"  WHERE ("name" = "state:Drupal\Core\Cache\CacheCollector") AND ("value" = "LOCK_ID")
INSERT INTO "semaphore" ("name", "value", "expire") VALUES ("theme_registry:runtime:stark:Drupal\Core\Cache\CacheCollector", "LOCK_ID", "EXPIRE")
DELETE FROM "semaphore"  WHERE ("name" = "theme_registry:runtime:stark:Drupal\Core\Cache\CacheCollector") AND ("value" = "LOCK_ID")
INSERT INTO "semaphore" ("name", "value", "expire") VALUES ("library_info:stark:Drupal\Core\Cache\CacheCollector", "LOCK_ID", "EXPIRE")
DELETE FROM "semaphore"  WHERE ("name" = "library_info:stark:Drupal\Core\Cache\CacheCollector") AND ("value" = "LOCK_ID")
INSERT INTO "semaphore" ("name", "value", "expire") VALUES ("path_alias_prefix_list:Drupal\Core\Cache\CacheCollector", "LOCK_ID", "EXPIRE")
DELETE FROM "semaphore"  WHERE ("name" = "path_alias_prefix_list:Drupal\Core\Cache\CacheCollector") AND ("value" = "LOCK_ID")
+0 −42
Changes for core/profiles/standard/tests/src/FunctionalJavascript/StandardPerformanceTestAssertions/standardFrontPage.yml: 0 added lines, 42 removed lines.
Original line number Diff line number Diff line
QueryCount: 19
CacheGetCount: 49
CacheGetCountByBin:
  page: 1
  config: 10
  data: 4
  bootstrap: 11
  discovery: 11
  routes: 4
  dynamic_page_cache: 1
  render: 4
  default: 2
  file_parsing: 1
CacheSetCount: 22
CacheDeleteCount: 0
CacheTagInvalidationCount: 0
CacheTagLookupQueryCount: 4
CacheTagGroupedLookups:
  -
    - route_match
    - access_policies
    - routes
    - router
    - entity_types
    - entity_field_info
    - entity_bundles
    - local_task
    - library_info
    - http_response
  -
    - 'config:block_list'
    - rendered
  -
    - 'CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form'
    - 'config:system.site'
  -
    - 4xx-response
    - 'config:user.role.anonymous'
ScriptCount: 0
ScriptBytes: 0
StylesheetCount: 2
StylesheetBytes: 1282
+0 −23
Changes for core/profiles/standard/tests/src/FunctionalJavascript/StandardPerformanceTestAssertions/standardNodePage.sql: 0 added lines, 23 removed lines.
Original line number Diff line number Diff line
SELECT "base_table"."id" AS "id", "base_table"."path" AS "path", "base_table"."alias" AS "alias", "base_table"."langcode" AS "langcode" FROM "path_alias" "base_table" WHERE ("base_table"."status" = 1) AND ("base_table"."alias" LIKE "/node/1" ESCAPE '\\') AND ("base_table"."langcode" IN ("en", "und")) ORDER BY "base_table"."langcode" ASC, "base_table"."id" DESC
SELECT "name", "route", "fit" FROM "router" WHERE "pattern_outline" IN ( "/node/1", "/node/%", "/node" ) AND "number_parts" >= 2
SELECT "revision"."vid" AS "vid", "revision"."langcode" AS "langcode", "revision"."revision_uid" AS "revision_uid", "revision"."revision_timestamp" AS "revision_timestamp", "revision"."revision_log" AS "revision_log", "revision"."revision_default" AS "revision_default", "base"."nid" AS "nid", "base"."type" AS "type", "base"."uuid" AS "uuid", CASE "base"."vid" WHEN "revision"."vid" THEN 1 ELSE 0 END AS "isDefaultRevision" FROM "node" "base" INNER JOIN "node_revision" "revision" ON "revision"."vid" = "base"."vid" WHERE "base"."nid" IN (1)
SELECT "node_field_data".*, "node_field_data"."langcode" AS "node_field_data__langcode", "node__body"."body_value" AS "body_value", "node__body"."body_format" AS "body_format" FROM "node_field_data" "node_field_data" LEFT OUTER JOIN "node__body" "node__body" ON "node__body"."entity_id" = "node_field_data"."nid" AND "node__body"."langcode" = "node_field_data"."langcode" AND "node__body"."deleted" = 0 WHERE "node_field_data"."nid" IN (1)
SELECT "name", "route" FROM "router" WHERE "name" IN ( "entity.node.canonical" )
SELECT 1 AS "expression" FROM "path_alias" "base_table" WHERE ("base_table"."status" = 1) AND ("base_table"."path" LIKE "/node%" ESCAPE '\\') LIMIT 1 OFFSET 0
SELECT "name", "data" FROM "config" WHERE "collection" = "" AND "name" IN ( "core.entity_view_display.node.test_content.full" )
SELECT "config"."name" AS "name" FROM "config" "config" WHERE ("collection" = "") AND ("name" LIKE "node.type.%" ESCAPE '\\') ORDER BY "collection" ASC, "name" ASC
SELECT "base"."uid" AS "uid", "base"."uuid" AS "uuid", "base"."langcode" AS "langcode" FROM "users" "base" WHERE "base"."uid" IN (0)
SELECT "users_field_data".*, "users_field_data"."langcode" AS "users_field_data__langcode", "user__user_picture"."user_picture_target_id" AS "user_picture_target_id", "user__user_picture"."user_picture_alt" AS "user_picture_alt", "user__user_picture"."user_picture_title" AS "user_picture_title", "user__user_picture"."user_picture_width" AS "user_picture_width", "user__user_picture"."user_picture_height" AS "user_picture_height" FROM "users_field_data" "users_field_data" LEFT OUTER JOIN "user__user_picture" "user__user_picture" ON "user__user_picture"."entity_id" = "users_field_data"."uid" AND "user__user_picture"."langcode" = "users_field_data"."langcode" AND "user__user_picture"."deleted" = 0 WHERE "users_field_data"."uid" IN (0)
SELECT "user__roles"."entity_id" AS "id", "user__roles"."langcode" AS "langcode", "user__roles"."roles_target_id" AS "roles_target_id", "user__roles"."delta" AS "roles_delta", "base"."default_langcode" AS "base_default_langcode" FROM "user__roles" "user__roles" INNER JOIN "users_field_data" "base" ON "base"."uid" = "user__roles"."entity_id" AND "base"."langcode" = "user__roles"."langcode" WHERE ("user__roles"."entity_id" IN (0)) AND ("user__roles"."deleted" = 0) ORDER BY "user__roles"."delta" ASC
SELECT "name", "data" FROM "config" WHERE "collection" = "" AND "name" IN ( "core.date_format.medium" )
SELECT "name", "data" FROM "config" WHERE "collection" = "" AND "name" IN ( "core.date_format.long" )
SELECT "name", "data" FROM "config" WHERE "collection" = "" AND "name" IN ( "filter.format.restricted_html" )
SELECT "name", "value" FROM "key_value" WHERE "name" IN ( "theme:stark" ) AND "collection" = "config.entity.key_store.block"
SELECT "name", "route" FROM "router" WHERE "name" IN ( "layout_builder.overrides.node.view", "entity.node.edit_form", "entity.node.delete_form", "entity.node.version_history" )
SELECT "base_table"."vid" AS "vid", "base_table"."nid" AS "nid" FROM "node_revision" "base_table" INNER JOIN (SELECT "subquery_base_table"."nid" AS "nid", MAX(subquery_base_table.vid) AS "maximum_revision_id" FROM "node_revision" "subquery_base_table" WHERE "nid" = "1" GROUP BY "subquery_base_table"."nid") "sq_base_table" ON base_table.nid = sq_base_table.nid AND base_table.vid = sq_base_table.maximum_revision_id INNER JOIN "node_field_data" "node_field_data" ON "node_field_data"."nid" = "base_table"."nid" WHERE "node_field_data"."nid" = "1"
SELECT "base_table"."id" AS "id", "base_table"."path" AS "path", "base_table"."alias" AS "alias", "base_table"."langcode" AS "langcode" FROM "path_alias" "base_table" WHERE ("base_table"."status" = 1) AND ("base_table"."alias" LIKE "/node" ESCAPE '\\') AND ("base_table"."langcode" IN ("en", "und")) ORDER BY "base_table"."langcode" ASC, "base_table"."id" DESC
SELECT "name", "route", "fit" FROM "router" WHERE "pattern_outline" IN ( "/node" ) AND "number_parts" >= 1
INSERT INTO "semaphore" ("name", "value", "expire") VALUES ("theme_registry:runtime:stark:Drupal\Core\Cache\CacheCollector", "LOCK_ID", "EXPIRE")
DELETE FROM "semaphore"  WHERE ("name" = "theme_registry:runtime:stark:Drupal\Core\Cache\CacheCollector") AND ("value" = "LOCK_ID")
INSERT INTO "semaphore" ("name", "value", "expire") VALUES ("path_alias_prefix_list:Drupal\Core\Cache\CacheCollector", "LOCK_ID", "EXPIRE")
DELETE FROM "semaphore"  WHERE ("name" = "path_alias_prefix_list:Drupal\Core\Cache\CacheCollector") AND ("value" = "LOCK_ID")
Loading