Initial Drupal 11 with DDEV setup
This commit is contained in:
		@ -0,0 +1,338 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\FunctionalTests\Asset;
 | 
			
		||||
 | 
			
		||||
use Drupal\Component\Utility\UrlHelper;
 | 
			
		||||
use Drupal\Tests\BrowserTestBase;
 | 
			
		||||
 | 
			
		||||
// cspell:ignore abcdefghijklmnop
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests asset aggregation.
 | 
			
		||||
 *
 | 
			
		||||
 * @group asset
 | 
			
		||||
 */
 | 
			
		||||
class AssetOptimizationTest extends BrowserTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The file assets path settings value.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $fileAssetsPath;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['system'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests that asset aggregates are rendered and created on disk.
 | 
			
		||||
   */
 | 
			
		||||
  public function testAssetAggregation(): void {
 | 
			
		||||
    // Test aggregation with a custom file_assets_path.
 | 
			
		||||
    $this->fileAssetsPath = $this->publicFilesDirectory . '/test-assets';
 | 
			
		||||
    $settings['settings']['file_assets_path'] = (object) [
 | 
			
		||||
      'value' => $this->fileAssetsPath,
 | 
			
		||||
      'required' => TRUE,
 | 
			
		||||
    ];
 | 
			
		||||
    $this->doTestAggregation($settings);
 | 
			
		||||
 | 
			
		||||
    // Test aggregation with no configured file_assets_path or file_public_path,
 | 
			
		||||
    // since tests run in a multisite, this tests multisite installs where
 | 
			
		||||
    // settings.php is the default.
 | 
			
		||||
    $this->fileAssetsPath = $this->publicFilesDirectory;
 | 
			
		||||
    $settings['settings']['file_public_path'] = (object) [
 | 
			
		||||
      'value' => NULL,
 | 
			
		||||
      'required' => TRUE,
 | 
			
		||||
    ];
 | 
			
		||||
    $settings['settings']['file_assets_path'] = (object) [
 | 
			
		||||
      'value' => NULL,
 | 
			
		||||
      'required' => TRUE,
 | 
			
		||||
    ];
 | 
			
		||||
    $this->doTestAggregation($settings);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a user and requests a page.
 | 
			
		||||
   */
 | 
			
		||||
  protected function requestPage(): void {
 | 
			
		||||
    $user = $this->createUser();
 | 
			
		||||
    $this->drupalLogin($user);
 | 
			
		||||
    $this->drupalGet('');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Helper to test aggregate file URLs.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $settings
 | 
			
		||||
   *   A settings array to pass to ::writeSettings()
 | 
			
		||||
   */
 | 
			
		||||
  protected function doTestAggregation(array $settings): void {
 | 
			
		||||
    $this->writeSettings($settings);
 | 
			
		||||
    $this->rebuildAll();
 | 
			
		||||
    $this->config('system.performance')->set('css', [
 | 
			
		||||
      'preprocess' => TRUE,
 | 
			
		||||
      'gzip' => TRUE,
 | 
			
		||||
    ])->save();
 | 
			
		||||
    $this->config('system.performance')->set('js', [
 | 
			
		||||
      'preprocess' => TRUE,
 | 
			
		||||
      'gzip' => TRUE,
 | 
			
		||||
    ])->save();
 | 
			
		||||
    $this->requestPage();
 | 
			
		||||
    $session = $this->getSession();
 | 
			
		||||
    $page = $session->getPage();
 | 
			
		||||
 | 
			
		||||
    // Collect all the URLs for all the script and styles prior to making any
 | 
			
		||||
    // more requests.
 | 
			
		||||
    $style_elements = $page->findAll('xpath', '//link[@href and @rel="stylesheet"]');
 | 
			
		||||
    $script_elements = $page->findAll('xpath', '//script[@src]');
 | 
			
		||||
    $style_urls = [];
 | 
			
		||||
    foreach ($style_elements as $element) {
 | 
			
		||||
      $style_urls[] = $element->getAttribute('href');
 | 
			
		||||
    }
 | 
			
		||||
    $script_urls = [];
 | 
			
		||||
    foreach ($script_elements as $element) {
 | 
			
		||||
      $script_urls[] = $element->getAttribute('src');
 | 
			
		||||
    }
 | 
			
		||||
    foreach ($style_urls as $url) {
 | 
			
		||||
      $this->assertAggregate($url, TRUE, 'text/css');
 | 
			
		||||
      // Once the file has been requested once, it's on disk. It is possible for
 | 
			
		||||
      // a second request to hit the controller, and then find that another
 | 
			
		||||
      // request has created the file already. Actually simulating this race
 | 
			
		||||
      // condition is not really possible since it relies on timing. However, by
 | 
			
		||||
      // changing the case of the part of the URL that is handled by Drupal
 | 
			
		||||
      // routing, we can force the request to be served by Drupal.
 | 
			
		||||
      $this->assertAggregate(str_replace($this->fileAssetsPath, strtoupper($this->fileAssetsPath), $url), TRUE, 'text/css');
 | 
			
		||||
      $this->assertAggregate($url, FALSE, 'text/css');
 | 
			
		||||
      $this->assertInvalidAggregates($url);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    foreach ($script_urls as $url) {
 | 
			
		||||
      $this->assertAggregate($url);
 | 
			
		||||
      $this->assertAggregate($url, FALSE);
 | 
			
		||||
      $this->assertInvalidAggregates($url);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Asserts the aggregate header.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   * @param bool $from_php
 | 
			
		||||
   *   (optional) Is the result from PHP or disk? Defaults to TRUE (PHP).
 | 
			
		||||
   * @param string|null $content_type
 | 
			
		||||
   *   The expected content type, or NULL to skip checking.
 | 
			
		||||
   */
 | 
			
		||||
  protected function assertAggregate(string $url, bool $from_php = TRUE, ?string $content_type = NULL): void {
 | 
			
		||||
    $url = $this->getAbsoluteUrl($url);
 | 
			
		||||
    if (!stripos($url, $this->fileAssetsPath) !== FALSE) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    $session = $this->getSession();
 | 
			
		||||
    $session->visit($url);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $headers = $session->getResponseHeaders();
 | 
			
		||||
    if (isset($content_type)) {
 | 
			
		||||
      $this->assertStringContainsString($content_type, $headers['Content-Type'][0]);
 | 
			
		||||
    }
 | 
			
		||||
    if ($from_php) {
 | 
			
		||||
      $this->assertStringContainsString('no-store', $headers['Cache-Control'][0]);
 | 
			
		||||
      $this->assertArrayHasKey('X-Generator', $headers);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $this->assertArrayNotHasKey('X-Generator', $headers);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Asserts the aggregate when it is invalid.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Behat\Mink\Exception\ExpectationException
 | 
			
		||||
   */
 | 
			
		||||
  protected function assertInvalidAggregates(string $url): void {
 | 
			
		||||
    $url = $this->getAbsoluteUrl($url);
 | 
			
		||||
    // Not every script or style on a page is aggregated.
 | 
			
		||||
    if (!str_contains($url, $this->fileAssetsPath)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    $session = $this->getSession();
 | 
			
		||||
    $session->visit($this->replaceGroupDelta($url));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
 | 
			
		||||
    $session->visit($this->omitTheme($url));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(400);
 | 
			
		||||
 | 
			
		||||
    $session->visit($this->omitInclude($url));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(400);
 | 
			
		||||
 | 
			
		||||
    $session->visit($this->invalidInclude($url));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(400);
 | 
			
		||||
 | 
			
		||||
    $session->visit($this->invalidExclude($url));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(400);
 | 
			
		||||
 | 
			
		||||
    $session->visit($this->replaceFileNamePrefix($url));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(400);
 | 
			
		||||
 | 
			
		||||
    $session->visit($this->setInvalidLibrary($url));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
 | 
			
		||||
    // When an invalid asset hash name is given.
 | 
			
		||||
    $session->visit($this->replaceGroupHash($url));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $current_url = $session->getCurrentUrl();
 | 
			
		||||
    // Redirect to the correct one.
 | 
			
		||||
    $this->assertEquals($url, $current_url);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Replaces the delta in the given URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The URL with the delta replaced.
 | 
			
		||||
   */
 | 
			
		||||
  protected function replaceGroupDelta(string $url): string {
 | 
			
		||||
    $parts = UrlHelper::parse($url);
 | 
			
		||||
    $parts['query']['delta'] = 100;
 | 
			
		||||
    $query = UrlHelper::buildQuery($parts['query']);
 | 
			
		||||
    return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Replaces the group hash in the given URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The URL with the group hash replaced.
 | 
			
		||||
   */
 | 
			
		||||
  protected function replaceGroupHash(string $url): string {
 | 
			
		||||
    $parts = explode('_', $url, 2);
 | 
			
		||||
    $hash = strtok($parts[1], '.');
 | 
			
		||||
    $parts[1] = str_replace($hash, 'abcdefghijklmnop', $parts[1]);
 | 
			
		||||
    return $this->getAbsoluteUrl(implode('_', $parts));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Replaces the filename prefix in the given URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The URL with the file name prefix replaced.
 | 
			
		||||
   */
 | 
			
		||||
  protected function replaceFileNamePrefix(string $url): string {
 | 
			
		||||
    return str_replace(['/css_', '/js_'], '/xyz_', $url);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Replaces the 'include' entry in the given URL with an invalid value.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The URL with the 'include' query set to an invalid value.
 | 
			
		||||
   */
 | 
			
		||||
  protected function setInvalidLibrary(string $url): string {
 | 
			
		||||
    // First replace the hash, so we don't get served the actual file on disk.
 | 
			
		||||
    $url = $this->replaceGroupHash($url);
 | 
			
		||||
    $parts = UrlHelper::parse($url);
 | 
			
		||||
    $include = explode(',', UrlHelper::uncompressQueryParameter($parts['query']['include']));
 | 
			
		||||
    $include[] = 'system/llama';
 | 
			
		||||
    $parts['query']['include'] = UrlHelper::compressQueryParameter(implode(',', $include));
 | 
			
		||||
 | 
			
		||||
    $query = UrlHelper::buildQuery($parts['query']);
 | 
			
		||||
    return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Removes the 'theme' query parameter from the given URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The URL with the 'theme' omitted.
 | 
			
		||||
   */
 | 
			
		||||
  protected function omitTheme(string $url): string {
 | 
			
		||||
    // First replace the hash, so we don't get served the actual file on disk.
 | 
			
		||||
    $url = $this->replaceGroupHash($url);
 | 
			
		||||
    $parts = UrlHelper::parse($url);
 | 
			
		||||
    unset($parts['query']['theme']);
 | 
			
		||||
    $query = UrlHelper::buildQuery($parts['query']);
 | 
			
		||||
    return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Removes the 'include' query parameter from the given URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The URL with the 'include' parameter omitted.
 | 
			
		||||
   */
 | 
			
		||||
  protected function omitInclude(string $url): string {
 | 
			
		||||
    // First replace the hash, so we don't get served the actual file on disk.
 | 
			
		||||
    $url = $this->replaceGroupHash($url);
 | 
			
		||||
    $parts = UrlHelper::parse($url);
 | 
			
		||||
    unset($parts['query']['include']);
 | 
			
		||||
    $query = UrlHelper::buildQuery($parts['query']);
 | 
			
		||||
    return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Replaces the 'include' query parameter with an invalid value.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The URL with 'include' set to an arbitrary string.
 | 
			
		||||
   */
 | 
			
		||||
  protected function invalidInclude(string $url): string {
 | 
			
		||||
    // First replace the hash, so we don't get served the actual file on disk.
 | 
			
		||||
    $url = $this->replaceGroupHash($url);
 | 
			
		||||
    $parts = UrlHelper::parse($url);
 | 
			
		||||
    $parts['query']['include'] = 'abcdefghijklmnop';
 | 
			
		||||
    $query = UrlHelper::buildQuery($parts['query']);
 | 
			
		||||
    return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Adds an invalid 'exclude' query parameter with an invalid value.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $url
 | 
			
		||||
   *   The source URL.
 | 
			
		||||
   *
 | 
			
		||||
   * @return string
 | 
			
		||||
   *   The URL with 'exclude' set to an arbitrary string.
 | 
			
		||||
   */
 | 
			
		||||
  protected function invalidExclude(string $url): string {
 | 
			
		||||
    // First replace the hash, so we don't get served the actual file on disk.
 | 
			
		||||
    $url = $this->replaceGroupHash($url);
 | 
			
		||||
    $parts = UrlHelper::parse($url);
 | 
			
		||||
    $parts['query']['exclude'] = 'abcdefghijklmnop';
 | 
			
		||||
    $query = UrlHelper::buildQuery($parts['query']);
 | 
			
		||||
    return $this->getAbsoluteUrl($parts['path'] . '?' . $query . '#' . $parts['fragment']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\FunctionalTests\Asset;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests asset aggregation with the Umami install profile.
 | 
			
		||||
 *
 | 
			
		||||
 * Umami includes several core modules as well as the Claro theme, this
 | 
			
		||||
 * results in a more complex asset dependency tree to test than the testing
 | 
			
		||||
 * profile.
 | 
			
		||||
 *
 | 
			
		||||
 * @group asset
 | 
			
		||||
 * @group #slow
 | 
			
		||||
 */
 | 
			
		||||
class AssetOptimizationUmamiTest extends AssetOptimizationTest {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $profile = 'demo_umami';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function requestPage(): void {
 | 
			
		||||
    $user = $this->createUser([], NULL, TRUE);
 | 
			
		||||
    $this->drupalLogin($user);
 | 
			
		||||
    $this->drupalGet('node/add/article');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,102 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\FunctionalTests\Asset;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\BrowserTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests asset aggregation.
 | 
			
		||||
 *
 | 
			
		||||
 * @group asset
 | 
			
		||||
 */
 | 
			
		||||
class UnversionedAssetTest extends BrowserTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The file assets path settings value.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $fileAssetsPath;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['system', 'unversioned_assets_test'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests that unversioned assets cause a new filename when changed.
 | 
			
		||||
   */
 | 
			
		||||
  public function testUnversionedAssets(): void {
 | 
			
		||||
    $this->fileAssetsPath = $this->publicFilesDirectory;
 | 
			
		||||
    file_put_contents('public://test.css', '.original-content{display:none;}');
 | 
			
		||||
    // Test aggregation with a custom file_assets_path.
 | 
			
		||||
    $this->config('system.performance')->set('css', [
 | 
			
		||||
      'preprocess' => TRUE,
 | 
			
		||||
      'gzip' => TRUE,
 | 
			
		||||
    ])->save();
 | 
			
		||||
    $this->config('system.performance')->set('js', [
 | 
			
		||||
      'preprocess' => TRUE,
 | 
			
		||||
      'gzip' => TRUE,
 | 
			
		||||
    ])->save();
 | 
			
		||||
 | 
			
		||||
    // Ensure that the library discovery cache is empty before the page is
 | 
			
		||||
    // requested and that updated asset URLs are rendered.
 | 
			
		||||
    \Drupal::service('cache.data')->deleteAll();
 | 
			
		||||
    \Drupal::service('cache.page')->deleteAll();
 | 
			
		||||
    $this->drupalGet('<front>');
 | 
			
		||||
    $session = $this->getSession();
 | 
			
		||||
    $page = $session->getPage();
 | 
			
		||||
 | 
			
		||||
    $style_elements = $page->findAll('xpath', '//link[@href and @rel="stylesheet"]');
 | 
			
		||||
    $this->assertNotEmpty($style_elements);
 | 
			
		||||
    $href = NULL;
 | 
			
		||||
    foreach ($style_elements as $element) {
 | 
			
		||||
      $href = $element->getAttribute('href');
 | 
			
		||||
      $url = $this->getAbsoluteUrl($href);
 | 
			
		||||
      // Not every script or style on a page is aggregated.
 | 
			
		||||
      if (!str_contains($url, $this->fileAssetsPath)) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      $session = $this->getSession();
 | 
			
		||||
      $session->visit($url);
 | 
			
		||||
      $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
      $aggregate = $session = $session->getPage()->getContent();
 | 
			
		||||
      $this->assertStringContainsString('original-content', $aggregate);
 | 
			
		||||
      $this->assertStringNotContainsString('extra-stuff', $aggregate);
 | 
			
		||||
    }
 | 
			
		||||
    $file = file_get_contents('public://test.css') . '.extra-stuff{display:none;}';
 | 
			
		||||
    file_put_contents('public://test.css', $file);
 | 
			
		||||
    // Clear the library discovery and page caches again so that new URLs are
 | 
			
		||||
    // generated.
 | 
			
		||||
    \Drupal::service('cache.data')->deleteAll();
 | 
			
		||||
    \Drupal::service('cache.page')->deleteAll();
 | 
			
		||||
    $this->drupalGet('<front>');
 | 
			
		||||
    $session = $this->getSession();
 | 
			
		||||
    $page = $session->getPage();
 | 
			
		||||
    $style_elements = $page->findAll('xpath', '//link[@href and @rel="stylesheet"]');
 | 
			
		||||
    $this->assertNotEmpty($style_elements);
 | 
			
		||||
    foreach ($style_elements as $element) {
 | 
			
		||||
      $new_href = $element->getAttribute('href');
 | 
			
		||||
      $this->assertNotSame($new_href, $href);
 | 
			
		||||
      $url = $this->getAbsoluteUrl($new_href);
 | 
			
		||||
      // Not every script or style on a page is aggregated.
 | 
			
		||||
      if (!str_contains($url, $this->fileAssetsPath)) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      $session = $this->getSession();
 | 
			
		||||
      $session->visit($url);
 | 
			
		||||
      $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
      $aggregate = $session = $session->getPage()->getContent();
 | 
			
		||||
      $this->assertStringContainsString('original-content', $aggregate);
 | 
			
		||||
      $this->assertStringContainsString('extra-stuff', $aggregate);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user