From e38fa2898247ae431bc6b878e08341cb39dcaa07 Mon Sep 17 00:00:00 2001
From: catch <6915-catch@users.noreply.drupalcode.org>
Date: Tue, 17 Dec 2024 14:17:50 +0000
Subject: [PATCH] Issue #3491405 by catch, phenaproxima, breidert: Add
 performance testing

---
 .gitlab-ci.yml                                |  19 +++-
 .../FunctionalJavaScript/PerformanceTest.php  | 107 ++++++++++++++++++
 2 files changed, 125 insertions(+), 1 deletion(-)
 create mode 100644 recipes/drupal_cms_starter/tests/src/FunctionalJavaScript/PerformanceTest.php

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 57f75627a..e3a317de2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -122,6 +122,18 @@ build test project:
   - chown -R www-data:www-data $_PROJECT_ROOT/$_WEB_ROOT
   - service apache2 start
 
+.with-chrome: &with-chrome
+  name: selenium/standalone-chrome:latest
+  alias: selenium
+  variables:
+    JAVA_OPTS: '-Dwebdriver.chrome.logfile=/builds/chromedriver.log'
+    SE_NODE_OVERRIDE_MAX_SESSIONS: 'true'
+    SE_NODE_MAX_SESSIONS: '16'
+    SE_SESSION_RETRY_INTERVAL: '1'
+    SE_SESSION_REQUEST_TIMEOUT: '10'
+    SE_START_XVFB: 'false'
+    SE_START_VNC: 'false'
+
 .test-base:
   stage: test
   needs:
@@ -129,9 +141,14 @@ build test project:
   services:
     - name: 'drupalci/mysql-8'
       alias: database
+    - *with-chrome
   variables:
     DDEV_PRIMARY_URL: http://localhost/$_WEB_ROOT
     SIMPLETEST_DB: mysql://drupaltestbot:drupaltestbotpw@database/mysql
+    MINK_DRIVER_ARGS_WEBDRIVER: '["chrome", {"browserName":"chrome", "goog:chromeOptions":{"w3c": true, "args":["--no-sandbox","--ignore-certificate-errors", "--allow-insecure-localhost", "--headless", "--dns-prefetch-disable"]}}, "http://selenium:4444"]'
+  artifacts:
+    reports:
+      junit: junit.xml
 
 run PHP tests:
   extends: .test-base
@@ -141,7 +158,7 @@ run PHP tests:
   script:
     - *start-apache
     - cd $BUILD_DIR
-    - sudo SIMPLETEST_BASE_URL=$DDEV_PRIMARY_URL SIMPLETEST_DB=$SIMPLETEST_DB SYMFONY_DEPRECATIONS_HELPER=disabled -u www-data vendor/bin/phpunit --configuration=$_WEB_ROOT/core $CI_PROJECT_DIR/$DIR
+    - sudo SIMPLETEST_BASE_URL=$DDEV_PRIMARY_URL SIMPLETEST_DB=$SIMPLETEST_DB MINK_DRIVER_ARGS_WEBDRIVER="$MINK_DRIVER_ARGS_WEBDRIVER" SYMFONY_DEPRECATIONS_HELPER=disabled -u www-data vendor/bin/phpunit --display-skipped --log-junit $CI_PROJECT_DIR/junit.xml --configuration=$_WEB_ROOT/core $CI_PROJECT_DIR/$DIR
   artifacts:
     paths:
       - $BUILD_DIR/$_WEB_ROOT/sites/simpletest
diff --git a/recipes/drupal_cms_starter/tests/src/FunctionalJavaScript/PerformanceTest.php b/recipes/drupal_cms_starter/tests/src/FunctionalJavaScript/PerformanceTest.php
new file mode 100644
index 000000000..d6608dd3b
--- /dev/null
+++ b/recipes/drupal_cms_starter/tests/src/FunctionalJavaScript/PerformanceTest.php
@@ -0,0 +1,107 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\drupal_cms_starter\FunctionalJavascript;
+
+use Composer\InstalledVersions;
+use Drupal\FunctionalJavascriptTests\PerformanceTestBase;
+use Drupal\FunctionalTests\Core\Recipe\RecipeTestTrait;
+
+/**
+ * Tests the performance of the drupal_cms_starter recipe.
+ *
+ * Stark is used as the default theme so that this test is not Olivero specific.
+ *
+ * @group OpenTelemetry
+ * @group #slow
+ * @requires extension apcu
+ */
+class PerformanceTest extends PerformanceTestBase {
+
+  use RecipeTestTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * Tests performance of the starter recipe.
+   */
+  public function testPerformance(): void {
+    $dir = InstalledVersions::getInstallPath('drupal/drupal_cms_starter');
+    $this->applyRecipe($dir);
+
+    $this->doTestAnonymousFrontPage();
+    $this->doTestEditorFrontPage();
+  }
+
+  /**
+   * Check the anonymous front page with a hot cache.
+   */
+  protected function doTestAnonymousFrontPage(): void {
+    // Warm various caches. Drupal CMS redirects the front page to /home, so visit that directly.
+    // @todo https://www.drupal.org/project/drupal_cms/issues/3493615
+    $this->drupalGet('/home');
+    $this->drupalGet('/home');
+
+    // Test frontpage.
+    $performance_data = $this->collectPerformanceData(function () {
+      $this->drupalGet('/home');
+    }, 'drupalCMSAnonymousFrontPage');
+    $this->assertSame([], $performance_data->getQueries());
+    $this->assertSame(0, $performance_data->getQueryCount());
+    $this->assertSame(2, $performance_data->getCacheGetCount());
+    $this->assertSame(0, $performance_data->getCacheSetCount());
+    $this->assertSame(0, $performance_data->getCacheDeleteCount());
+    $this->assertSame(0, $performance_data->getCacheTagChecksumCount());
+    $this->assertSame(1, $performance_data->getCacheTagIsValidCount());
+    $this->assertSame(0, $performance_data->getCacheTagInvalidationCount());
+    $this->assertSame(2, $performance_data->getStylesheetCount());
+    $this->assertSame(2, $performance_data->getScriptCount());
+    // @todo dramatically reduce these numbers once Klaro out of the box
+    // performance is improved.
+    // @see https://www.drupal.org/project/drupal_cms/issues/3493438
+    $this->assertLessThan(120000, $performance_data->getStylesheetBytes());
+    $this->assertLessThan(245000, $performance_data->getScriptBytes());
+  }
+
+  /**
+   * Log in with the editor role and visit the front page with a warm cache.
+   */
+  protected function doTestEditorFrontPage(): void {
+    $editor = $this->drupalCreateUser();
+    $editor->addRole('content_editor')->save();
+    $this->drupalLogin($editor);
+    // Warm various caches. Drupal CMS redirects the front page to /home, so visit that directly.
+    // @todo https://www.drupal.org/project/drupal_cms/issues/3493615
+    $this->drupalGet('/home');
+    $this->drupalGet('/home');
+
+    // Test frontpage.
+    $performance_data = $this->collectPerformanceData(function () {
+      $this->drupalGet('/home');
+    }, 'drupalCMSEditorFRontPage');
+    $assert_session = $this->assertSession();
+    $assert_session->elementAttributeContains('named', ['link', 'Dashboard'], 'class', 'toolbar-button--icon--navigation-dashboard');
+    // @todo assert individual queries once Coffee does not result in an
+    // additional AJAX request on every request.
+    // @see https://www.drupal.org/project/coffee/issues/2453585
+    $this->assertSame(59, $performance_data->getQueryCount());
+    $this->assertSame(241, $performance_data->getCacheGetCount());
+    $this->assertSame(0, $performance_data->getCacheSetCount());
+    $this->assertSame(0, $performance_data->getCacheDeleteCount());
+    $this->assertSame(0, $performance_data->getCacheTagChecksumCount());
+    $this->assertSame(102, $performance_data->getCacheTagIsValidCount());
+    $this->assertSame(0, $performance_data->getCacheTagInvalidationCount());
+    $this->assertSame(3, $performance_data->getStylesheetCount());
+    $this->assertSame(5, $performance_data->getScriptCount());
+    // @todo dramatically reduce these numbers once Klaro out of the box
+    // performance is improved.
+    // @see https://www.drupal.org/project/drupal_cms/issues/3493438
+    $this->assertLessThan(370000, $performance_data->getStylesheetBytes());
+    $this->assertLessThan(535000, $performance_data->getScriptBytes());
+  }
+
+}
-- 
GitLab