diff --git a/core/profiles/demo_umami/tests/src/FunctionalJavascript/PerformanceTest.php b/core/profiles/demo_umami/tests/src/FunctionalJavascript/PerformanceTest.php
new file mode 100644
index 0000000000..9995a68824
--- /dev/null
+++ b/core/profiles/demo_umami/tests/src/FunctionalJavascript/PerformanceTest.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\Tests\demo_umami\FunctionalJavascript;
+
+use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+use Drupal\FunctionalJavascriptTests\PerformanceTestTrait;
+
+/**
+ * Tests demo_umami profile performance.
+ *
+ * @group performance
+ */
+class PerformanceTest extends WebDriverTestBase {
+
+  use PerformanceTestTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $profile = 'demo_umami';
+
+  protected function setUp(): void {
+    parent::setUp();
+  }
+
+  /**
+   * Just load the front page.
+   */
+  public function testFrontPage(): void {
+    \Drupal::configFactory()->getEditable('system.performance')
+      ->set('css.preprocess', TRUE)
+      ->set('js.preprocess', TRUE)
+      ->save();
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('Umami');
+    $this->assertSame(2, $this->stylesheetCount);
+    $this->assertSame(1, $this->scriptCount);
+  }
+
+  /**
+   * Load the front page as a user with access to Tours.
+   */
+  public function testFrontPageTour(): void {
+    \Drupal::configFactory()->getEditable('system.performance')
+      ->set('css.preprocess', TRUE)
+      ->set('js.preprocess', TRUE)
+      ->save();
+    $admin_user = $this->drupalCreateUser(['access tour']);
+    $this->drupalLogin($admin_user);
+    $this->drupalGet('<front>');
+    $this->assertSession()->pageTextContains('Umami');
+    $this->assertSame(4, $this->stylesheetCount);
+    $this->assertSame(2, $this->scriptCount);
+  }
+
+}
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/PerformanceTestTrait.php b/core/tests/Drupal/FunctionalJavascriptTests/PerformanceTestTrait.php
new file mode 100644
index 0000000000..b50331a295
--- /dev/null
+++ b/core/tests/Drupal/FunctionalJavascriptTests/PerformanceTestTrait.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace Drupal\FunctionalJavascriptTests;
+
+use Drupal\Core\Url;
+
+/**
+ * Collects performance metrics.
+ *
+ * @ingroup testing
+ */
+trait PerformanceTestTrait {
+
+  /**
+   * The number of stylesheets requested.
+   *
+   * @var int
+   */
+  protected int $stylesheetCount = 0;
+
+  /**
+   * The number of scripts requested.
+   *
+   * @var int
+   */
+  protected int $scriptCount = 0;
+
+  /**
+   * The number of images requested.
+   *
+   * @var int
+   */
+  protected int $imageCount = 0;
+
+  /**
+   * Enable performance data collection.
+   */
+  protected function getMinkDriverArgs() {
+
+    // Add performance logging preferences to the existing driver arguments to
+    // avoid clobbering anything set via environment variables.
+    $parent_driver_args = parent::getMinkDriverArgs();
+    $driver_args = json_decode($parent_driver_args, TRUE);
+
+    $driver_args[1]['goog:loggingPrefs'] = [
+      'browser' => 'ALL',
+      'performance' => 'ALL',
+      'performanceTimeline' => 'ALL',
+    ];
+    $driver_args[1]['chromeOptions']['perfLoggingPrefs'] = [
+      'traceCategories' => 'devtools.timeline',
+      'enableNetwork' => TRUE,
+    ];
+
+    return json_encode($driver_args);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function drupalGet($path, array $options = [], array $headers = []): string {
+    $return = parent::drupalGet($path, $options, $headers);
+    $this->getChromeDriverPerformanceMetrics($path);
+    return $return;
+  }
+
+  /**
+   * Gets the chromedriver performance log and extracts metrics from it.
+   */
+  protected function getChromeDriverPerformanceMetrics($path): void {
+    $session = $this->getSession();
+    $performance_log = $session->getDriver()->getWebDriverSession()->log('performance');
+
+    $messages = [];
+    foreach ($performance_log as $entry) {
+      $decoded = json_decode($entry['message'], 1);
+      $messages[] = $decoded['message'];
+    }
+    $this->collectNetworkData($path, $messages);
+  }
+
+  /**
+   * Prepare data for assertions.
+   *
+   * @param string|\Drupal\Core\Url $path
+   *   The path as passed to static::drupalGet().
+   * @param array $messages
+   *   The chromedriver performance log messages.
+   */
+  protected function collectNetworkData(string|Url $path, array $messages): void {
+    $this->stylesheetCount = 0;
+    $this->scriptCount = 0;
+    $this->imageCount = 0;
+    foreach ($messages as $message) {
+      if ($message['method'] === 'Network.responseReceived') {
+        if ($message['params']['type'] === 'Stylesheet') {
+          $this->stylesheetCount++;
+        }
+        if ($message['params']['type'] === 'Script') {
+          $this->scriptCount++;
+        }
+        if ($message['params']['type'] === 'Image') {
+          $this->imageCount++;
+        }
+      }
+    }
+  }
+
+}
