Version 1
[yaffs-website] / web / core / modules / big_pipe / tests / src / Unit / Render / BigPipeResponseAttachmentsProcessorTest.php
diff --git a/web/core/modules/big_pipe/tests/src/Unit/Render/BigPipeResponseAttachmentsProcessorTest.php b/web/core/modules/big_pipe/tests/src/Unit/Render/BigPipeResponseAttachmentsProcessorTest.php
new file mode 100644 (file)
index 0000000..a4cbacd
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+
+namespace Drupal\Tests\big_pipe\Unit\Render;
+
+use Drupal\big_pipe\Render\BigPipeResponse;
+use Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor;
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Asset\AssetCollectionRendererInterface;
+use Drupal\Core\Asset\AssetResolverInterface;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Render\AttachmentsInterface;
+use Drupal\Core\Render\AttachmentsResponseProcessorInterface;
+use Drupal\Core\Render\HtmlResponse;
+use Drupal\Core\Render\RendererInterface;
+use Drupal\Tests\UnitTestCase;
+use Prophecy\Argument;
+use Prophecy\Prophecy\ObjectProphecy;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * @coversDefaultClass \Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor
+ * @group big_pipe
+ */
+class BigPipeResponseAttachmentsProcessorTest extends UnitTestCase {
+
+  /**
+   * @covers ::processAttachments
+   *
+   * @dataProvider nonHtmlResponseProvider
+   */
+  public function testNonHtmlResponse($response_class) {
+    $big_pipe_response_attachments_processor = $this->createBigPipeResponseAttachmentsProcessor($this->prophesize(AttachmentsResponseProcessorInterface::class));
+
+    $non_html_response = new $response_class();
+    $this->setExpectedException(\AssertionError::class);
+    $big_pipe_response_attachments_processor->processAttachments($non_html_response);
+  }
+
+  public function nonHtmlResponseProvider() {
+    return [
+      'AjaxResponse, which implements AttachmentsInterface' => [AjaxResponse::class],
+      'A dummy that implements AttachmentsInterface' => [get_class($this->prophesize(AttachmentsInterface::class)->reveal())],
+    ];
+  }
+
+  /**
+   * @covers ::processAttachments
+   *
+   * @dataProvider attachmentsProvider
+   */
+  public function testHtmlResponse(array $attachments) {
+    $big_pipe_response = new BigPipeResponse(new HtmlResponse('original'));
+    $big_pipe_response->setAttachments($attachments);
+
+    // This mock is the main expectation of this test: verify that the decorated
+    // service (that is this mock) never receives BigPipe placeholder
+    // attachments, because it doesn't know (nor should it) how to handle them.
+    $html_response_attachments_processor = $this->prophesize(AttachmentsResponseProcessorInterface::class);
+    $html_response_attachments_processor->processAttachments(Argument::that(function ($response) {
+      return $response instanceof HtmlResponse && empty(array_intersect(['big_pipe_placeholders', 'big_pipe_nojs_placeholders'], array_keys($response->getAttachments())));
+    }))
+      ->will(function ($args) {
+        /** @var \Symfony\Component\HttpFoundation\Response|\Drupal\Core\Render\AttachmentsInterface $response */
+        $response = $args[0];
+        // Simulate its actual behavior.
+        $attachments = array_diff_key($response->getAttachments(), ['html_response_attachment_placeholders' => TRUE]);
+        $response->setContent('processed');
+        $response->setAttachments($attachments);
+        return $response;
+      })
+      ->shouldBeCalled();
+
+    $big_pipe_response_attachments_processor = $this->createBigPipeResponseAttachmentsProcessor($html_response_attachments_processor);
+    $processed_big_pipe_response = $big_pipe_response_attachments_processor->processAttachments($big_pipe_response);
+
+    // The secondary expectation of this test: the original (passed in) response
+    // object remains unchanged, the processed (returned) response object has
+    // the expected values.
+    $this->assertSame($attachments, $big_pipe_response->getAttachments(), 'Attachments of original response object MUST NOT be changed.');
+    $this->assertEquals('original', $big_pipe_response->getContent(), 'Content of original response object MUST NOT be changed.');
+    $this->assertEquals(array_diff_key($attachments, ['html_response_attachment_placeholders' => TRUE]), $processed_big_pipe_response->getAttachments(), 'Attachments of returned (processed) response object MUST be changed.');
+    $this->assertEquals('processed', $processed_big_pipe_response->getContent(), 'Content of returned (processed) response object MUST be changed.');
+  }
+
+  public function attachmentsProvider() {
+    $typical_cases = [
+      'no attachments' => [[]],
+      'libraries' => [['library' => ['core/drupal']]],
+      'libraries + drupalSettings' => [['library' => ['core/drupal'], 'drupalSettings' => ['foo' => 'bar']]],
+    ];
+
+    $official_attachment_types = ['html_head', 'feed', 'html_head_link', 'http_header', 'library', 'placeholders', 'drupalSettings', 'html_response_attachment_placeholders'];
+    $official_attachments_with_random_values = [];
+    foreach ($official_attachment_types as $type) {
+      $official_attachments_with_random_values[$type] = $this->randomMachineName();
+    }
+    $random_attachments = ['random' . $this->randomMachineName() => $this->randomMachineName()];
+    $edge_cases = [
+      'all official attachment types, with random assigned values, even if technically not valid, to prove BigPipeResponseAttachmentsProcessor is a perfect decorator' => [$official_attachments_with_random_values],
+      'random attachment type (unofficial), with random assigned value, to prove BigPipeResponseAttachmentsProcessor is a perfect decorator' => [$random_attachments],
+    ];
+
+    $big_pipe_placeholder_attachments = ['big_pipe_placeholders' => $this->randomMachineName()];
+    $big_pipe_nojs_placeholder_attachments = ['big_pipe_nojs_placeholders' => $this->randomMachineName()];
+    $big_pipe_cases = [
+      'only big_pipe_placeholders' => [$big_pipe_placeholder_attachments],
+      'only big_pipe_nojs_placeholders' => [$big_pipe_nojs_placeholder_attachments],
+      'big_pipe_placeholders + big_pipe_nojs_placeholders' => [$big_pipe_placeholder_attachments + $big_pipe_nojs_placeholder_attachments],
+    ];
+
+    $combined_cases = [
+      'all official attachment types + big_pipe_placeholders + big_pipe_nojs_placeholders' => [$official_attachments_with_random_values + $big_pipe_placeholder_attachments + $big_pipe_nojs_placeholder_attachments],
+      'random attachment types + big_pipe_placeholders + big_pipe_nojs_placeholders' => [$random_attachments + $big_pipe_placeholder_attachments + $big_pipe_nojs_placeholder_attachments],
+    ];
+
+    return $typical_cases + $edge_cases + $big_pipe_cases + $combined_cases;
+  }
+
+  /**
+   * Creates a BigPipeResponseAttachmentsProcessor with mostly dummies.
+   *
+   * @param \Prophecy\Prophecy\ObjectProphecy $decorated_html_response_attachments_processor
+   *   An object prophecy implementing AttachmentsResponseProcessorInterface.
+   *
+   * @return \Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor
+   *   The BigPipeResponseAttachmentsProcessor to test.
+   */
+  protected function createBigPipeResponseAttachmentsProcessor(ObjectProphecy $decorated_html_response_attachments_processor) {
+    return new BigPipeResponseAttachmentsProcessor(
+      $decorated_html_response_attachments_processor->reveal(),
+      $this->prophesize(AssetResolverInterface::class)->reveal(),
+      $this->prophesize(ConfigFactoryInterface::class)->reveal(),
+      $this->prophesize(AssetCollectionRendererInterface::class)->reveal(),
+      $this->prophesize(AssetCollectionRendererInterface::class)->reveal(),
+      $this->prophesize(RequestStack::class)->reveal(),
+      $this->prophesize(RendererInterface::class)->reveal(),
+      $this->prophesize(ModuleHandlerInterface::class)->reveal()
+    );
+  }
+
+}