Initial Drupal 11 with DDEV setup
This commit is contained in:
		@ -0,0 +1,42 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\FunctionalTests\HttpKernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Url;
 | 
			
		||||
use Drupal\Tests\BrowserTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests Content-Length set by Drupal.
 | 
			
		||||
 *
 | 
			
		||||
 * @group Http
 | 
			
		||||
 */
 | 
			
		||||
class ContentLengthTest extends BrowserTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['system', 'http_middleware_test'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  public function testContentLength(): void {
 | 
			
		||||
    // Fire off a request.
 | 
			
		||||
    $this->drupalGet(Url::fromRoute('http_middleware_test.test_response'));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Content-Length', '40');
 | 
			
		||||
 | 
			
		||||
    $this->setContainerParameter('no-alter-content-length', TRUE);
 | 
			
		||||
    $this->rebuildContainer();
 | 
			
		||||
 | 
			
		||||
    // Fire the same exact request but this time length is different.
 | 
			
		||||
    $this->drupalGet(Url::fromRoute('http_middleware_test.test_response'));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Content-Length', '41');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,173 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\FunctionalTests\HttpKernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Url;
 | 
			
		||||
use Drupal\Tests\BrowserTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests CORS provided by Drupal.
 | 
			
		||||
 *
 | 
			
		||||
 * @see sites/default/default.services.yml
 | 
			
		||||
 * @see \Asm89\Stack\Cors
 | 
			
		||||
 * @see \Asm89\Stack\CorsService
 | 
			
		||||
 *
 | 
			
		||||
 * @group Http
 | 
			
		||||
 */
 | 
			
		||||
class CorsIntegrationTest extends BrowserTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['system', 'test_page_test', 'page_cache'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  public function testCrossSiteRequest(): void {
 | 
			
		||||
    // Test default parameters.
 | 
			
		||||
    $cors_config = $this->container->getParameter('cors.config');
 | 
			
		||||
    $this->assertFalse($cors_config['enabled']);
 | 
			
		||||
    $this->assertSame([], $cors_config['allowedHeaders']);
 | 
			
		||||
    $this->assertSame([], $cors_config['allowedMethods']);
 | 
			
		||||
    $this->assertSame(['*'], $cors_config['allowedOrigins']);
 | 
			
		||||
 | 
			
		||||
    $this->assertFalse($cors_config['exposedHeaders']);
 | 
			
		||||
    $this->assertFalse($cors_config['maxAge']);
 | 
			
		||||
    $this->assertFalse($cors_config['supportsCredentials']);
 | 
			
		||||
 | 
			
		||||
    // Enable CORS with the default options.
 | 
			
		||||
    $cors_config['enabled'] = TRUE;
 | 
			
		||||
 | 
			
		||||
    $this->setContainerParameter('cors.config', $cors_config);
 | 
			
		||||
    $this->rebuildContainer();
 | 
			
		||||
 | 
			
		||||
    // Fire off a request.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://example.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'MISS');
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', '*');
 | 
			
		||||
    $this->assertSession()->responseHeaderNotContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Fire the same exact request. This time it should be cached.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://example.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'HIT');
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', '*');
 | 
			
		||||
    $this->assertSession()->responseHeaderNotContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Fire a request for a different origin. Verify the CORS header.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://example.org']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'HIT');
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', '*');
 | 
			
		||||
    $this->assertSession()->responseHeaderNotContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Configure the CORS stack to match allowed origins using regex patterns.
 | 
			
		||||
    $cors_config['allowedOrigins'] = [];
 | 
			
		||||
    $cors_config['allowedOriginsPatterns'] = ['#^http://[a-z-]*\.valid.com$#'];
 | 
			
		||||
 | 
			
		||||
    $this->setContainerParameter('cors.config', $cors_config);
 | 
			
		||||
    $this->rebuildContainer();
 | 
			
		||||
 | 
			
		||||
    // Fire a request from an origin that isn't allowed.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://non-valid.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderDoesNotExist('Access-Control-Allow-Origin');
 | 
			
		||||
    $this->assertSession()->responseHeaderContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Specify a valid origin.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://sub-domain.valid.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://sub-domain.valid.com');
 | 
			
		||||
    $this->assertSession()->responseHeaderContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Test combining allowedOrigins and allowedOriginsPatterns.
 | 
			
		||||
    $cors_config['allowedOrigins'] = ['http://domainA.com'];
 | 
			
		||||
    $cors_config['allowedOriginsPatterns'] = ['#^http://domain[B-Z-]*\.com$#'];
 | 
			
		||||
 | 
			
		||||
    $this->setContainerParameter('cors.config', $cors_config);
 | 
			
		||||
    $this->rebuildContainer();
 | 
			
		||||
 | 
			
		||||
    // Specify an origin that does not match allowedOrigins nor
 | 
			
		||||
    // allowedOriginsPattern.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://non-valid.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderDoesNotExist('Access-Control-Allow-Origin');
 | 
			
		||||
    $this->assertSession()->responseHeaderContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Specify a valid origin that matches allowedOrigins.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://domainA.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://domainA.com');
 | 
			
		||||
    $this->assertSession()->responseHeaderContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Specify a valid origin that matches allowedOriginsPatterns.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://domainX.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://domainX.com');
 | 
			
		||||
    $this->assertSession()->responseHeaderContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Configure the CORS stack to allow a specific origin.
 | 
			
		||||
    $cors_config['allowedOrigins'] = ['http://example.com'];
 | 
			
		||||
    $cors_config['allowedOriginsPatterns'] = [];
 | 
			
		||||
 | 
			
		||||
    $this->setContainerParameter('cors.config', $cors_config);
 | 
			
		||||
    $this->rebuildContainer();
 | 
			
		||||
 | 
			
		||||
    // Fire a request from an origin that isn't allowed.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://non-valid.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
 | 
			
		||||
    $this->assertSession()->responseHeaderNotContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Specify a valid origin.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://example.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
 | 
			
		||||
    $this->assertSession()->responseHeaderNotContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Configure the CORS stack to allow a specific set of origins.
 | 
			
		||||
    $cors_config['allowedOrigins'] = ['http://example.com', 'https://drupal.org'];
 | 
			
		||||
 | 
			
		||||
    $this->setContainerParameter('cors.config', $cors_config);
 | 
			
		||||
    $this->rebuildContainer();
 | 
			
		||||
 | 
			
		||||
    // Fire a request from an origin that isn't allowed.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://non-valid.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', NULL);
 | 
			
		||||
    $this->assertSession()->responseHeaderContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Specify a valid origin.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'http://example.com']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com');
 | 
			
		||||
    $this->assertSession()->responseHeaderContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Specify a valid origin.
 | 
			
		||||
    $this->drupalGet('/test-page', [], ['Origin' => 'https://drupal.org']);
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'https://drupal.org');
 | 
			
		||||
    $this->assertSession()->responseHeaderContains('Vary', 'Origin');
 | 
			
		||||
 | 
			
		||||
    // Verify POST still functions with 'Origin' header set to site's domain.
 | 
			
		||||
    $origin = \Drupal::request()->getSchemeAndHttpHost();
 | 
			
		||||
 | 
			
		||||
    /** @var \GuzzleHttp\ClientInterface $httpClient */
 | 
			
		||||
    $httpClient = $this->getSession()->getDriver()->getClient()->getClient();
 | 
			
		||||
    $url = Url::fromUri('base:/test-page');
 | 
			
		||||
    /** @var \Symfony\Component\HttpFoundation\Response $response */
 | 
			
		||||
    $response = $httpClient->request('POST', $url->setAbsolute()->toString(), [
 | 
			
		||||
      'headers' => [
 | 
			
		||||
        'Origin' => $origin,
 | 
			
		||||
      ],
 | 
			
		||||
    ]);
 | 
			
		||||
    $this->assertEquals(200, $response->getStatusCode());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,45 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\FunctionalTests\HttpKernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\File\FileSystemInterface;
 | 
			
		||||
use Drupal\Core\Url;
 | 
			
		||||
use Drupal\Tests\BrowserTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests invocation of services performing deferred tasks after response flush.
 | 
			
		||||
 *
 | 
			
		||||
 * @see \Drupal\Core\DestructableInterface
 | 
			
		||||
 *
 | 
			
		||||
 * @group Http
 | 
			
		||||
 */
 | 
			
		||||
class DestructableServiceTest extends BrowserTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['system', 'destructable_test'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  public function testDestructableServiceExecutionOrder(): void {
 | 
			
		||||
    $file_system = $this->container->get('file_system');
 | 
			
		||||
    assert($file_system instanceof FileSystemInterface);
 | 
			
		||||
    $semaphore = $file_system
 | 
			
		||||
      ->tempnam($file_system->getTempDirectory(), 'destructable_semaphore');
 | 
			
		||||
    $this->drupalGet(Url::fromRoute('destructable', [], ['query' => ['semaphore' => $semaphore]]));
 | 
			
		||||
    // This should be false as the response should flush before running the
 | 
			
		||||
    // test service.
 | 
			
		||||
    $this->assertEmpty(file_get_contents($semaphore), 'Destructable service did not run when response flushed to client.');
 | 
			
		||||
    // The destructable service will sleep for 3 seconds, then run.
 | 
			
		||||
    // To ensure no race conditions on slow test runners, wait another 3s.
 | 
			
		||||
    sleep(6);
 | 
			
		||||
    $this->assertTrue(file_get_contents($semaphore) === 'ran', 'Destructable service did run.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user