5 * Contains \Drupal\Tests\big_pipe\Unit\Render\Placeholder\BigPipePlaceholderTestCases.
8 namespace Drupal\big_pipe\Tests;
10 use Drupal\big_pipe\Render\BigPipeMarkup;
11 use Drupal\Core\Session\AccountInterface;
12 use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
14 use Symfony\Component\DependencyInjection\ContainerInterface;
17 * BigPipe placeholder test cases for use in both unit and integration tests.
20 * \Drupal\Tests\big_pipe\Unit\Render\Placeholder\BigPipeStrategyTest
21 * - Integration test for BigPipe with JS on:
22 * \Drupal\big_pipe\Tests\BigPipeTest::testBigPipe()
23 * - Integration test for BigPipe with JS off:
24 * \Drupal\big_pipe\Tests\BigPipeTest::testBigPipeNoJs()
26 class BigPipePlaceholderTestCases {
29 * Gets all BigPipe placeholder test cases.
31 * @param \Symfony\Component\DependencyInjection\ContainerInterface|null $container
32 * Optional. Necessary to get the embedded AJAX/HTML responses.
33 * @param \Drupal\Core\Session\AccountInterface|null $user
34 * Optional. Necessary to get the embedded AJAX/HTML responses.
36 * @return \Drupal\big_pipe\Tests\BigPipePlaceholderTestCase[]
38 public static function cases(ContainerInterface $container = NULL, AccountInterface $user = NULL) {
39 // Define the two types of cacheability that we expect to see. These will be
40 // used in the expectations.
41 $cacheability_depends_on_session_only = [
43 'contexts' => ['session.exists'],
45 $cacheability_depends_on_session_and_nojs_cookie = [
47 'contexts' => ['session.exists', 'cookies:big_pipe_nojs'],
51 // 1. Real-world example of HTML placeholder.
52 $status_messages = new BigPipePlaceholderTestCase(
53 ['#type' => 'status_messages'],
54 '<drupal-render-placeholder callback="Drupal\Core\Render\Element\StatusMessages::renderMessages" arguments="0" token="_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></drupal-render-placeholder>',
57 'Drupal\Core\Render\Element\StatusMessages::renderMessages',
62 $status_messages->bigPipePlaceholderId = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA';
63 $status_messages->bigPipePlaceholderRenderArray = [
64 '#markup' => '<span data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>',
65 '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
67 'library' => ['big_pipe/big_pipe'],
69 'bigPipePlaceholderIds' => [
70 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA' => TRUE,
73 'big_pipe_placeholders' => [
74 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA' => $status_messages->placeholderRenderArray,
78 $status_messages->bigPipeNoJsPlaceholder = '<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>';
79 $status_messages->bigPipeNoJsPlaceholderRenderArray = [
80 '#markup' => '<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>',
81 '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
83 'big_pipe_nojs_placeholders' => [
84 '<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>' => $status_messages->placeholderRenderArray,
88 if ($container && $user) {
89 $status_messages->embeddedAjaxResponseCommands = [
91 'command' => 'settings',
95 'libraries' => 'big_pipe/big_pipe,classy/base,classy/messages,core/drupal.active-link,core/html5shiv,core/normalize,system/base',
97 'pluralDelimiter' => PluralTranslatableMarkup::DELIMITER,
100 'permissionsHash' => $container->get('user_permissions_hash_generator')->generate($user),
106 'command' => 'add_css',
107 'data' => '<link rel="stylesheet" href="' . base_path() . 'core/themes/classy/css/components/messages.css?' . $container->get('state')->get('system.css_js_query_string') . '" media="all" />' . "\n"
110 'command' => 'insert',
111 'method' => 'replaceWith',
112 'selector' => '[data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"]',
113 'data' => "\n" . ' <div role="contentinfo" aria-label="Status message" class="messages messages--status">' . "\n" . ' <h2 class="visually-hidden">Status message</h2>' . "\n" . ' Hello from BigPipe!' . "\n" . ' </div>' . "\n ",
117 $status_messages->embeddedHtmlResponse = '<link rel="stylesheet" href="' . base_path() . 'core/themes/classy/css/components/messages.css?' . $container->get('state')->get('system.css_js_query_string') . '" media="all" />' . "\n" . "\n" . ' <div role="contentinfo" aria-label="Status message" class="messages messages--status">' . "\n" . ' <h2 class="visually-hidden">Status message</h2>' . "\n" . ' Hello from BigPipe!' . "\n" . ' </div>' . "\n \n";
121 // 2. Real-world example of HTML attribute value placeholder: form action.
122 $form_action = new BigPipePlaceholderTestCase(
123 $container ? $container->get('form_builder')->getForm('Drupal\big_pipe_test\Form\BigPipeTestForm') : [],
124 'form_action_cc611e1d',
126 '#lazy_builder' => ['form_builder:renderPlaceholderFormAction', []],
129 $form_action->bigPipeNoJsPlaceholder = 'big_pipe_nojs_placeholder_attribute_safe:form_action_cc611e1d';
130 $form_action->bigPipeNoJsPlaceholderRenderArray = [
131 '#markup' => 'big_pipe_nojs_placeholder_attribute_safe:form_action_cc611e1d',
132 '#cache' => $cacheability_depends_on_session_only,
134 'big_pipe_nojs_placeholders' => [
135 'big_pipe_nojs_placeholder_attribute_safe:form_action_cc611e1d' => $form_action->placeholderRenderArray,
140 $form_action->embeddedHtmlResponse = '<form class="big-pipe-test-form" data-drupal-selector="big-pipe-test-form" action="' . base_path() . 'big_pipe_test"';
144 // 3. Real-world example of HTML attribute value subset placeholder: CSRF
146 $csrf_token = new BigPipePlaceholderTestCase(
148 '#title' => 'Link with CSRF token',
150 '#url' => Url::fromRoute('system.theme_set_default'),
152 'e88b559cce72c80b687d56b0e2a3a5ae4b66bc0e',
155 'route_processor_csrf:renderPlaceholderCsrfToken',
156 ['admin/config/user-interface/shortcut/manage/default/add-link-inline']
160 $csrf_token->bigPipeNoJsPlaceholder = 'big_pipe_nojs_placeholder_attribute_safe:e88b559cce72c80b687d56b0e2a3a5ae4b66bc0e';
161 $csrf_token->bigPipeNoJsPlaceholderRenderArray = [
162 '#markup' => 'big_pipe_nojs_placeholder_attribute_safe:e88b559cce72c80b687d56b0e2a3a5ae4b66bc0e',
163 '#cache' => $cacheability_depends_on_session_only,
165 'big_pipe_nojs_placeholders' => [
166 'big_pipe_nojs_placeholder_attribute_safe:e88b559cce72c80b687d56b0e2a3a5ae4b66bc0e' => $csrf_token->placeholderRenderArray,
171 $csrf_token->embeddedHtmlResponse = $container->get('csrf_token')->get('admin/appearance/default');
175 // 4. Edge case: custom string to be considered as a placeholder that
176 // happens to not be valid HTML.
177 $hello = new BigPipePlaceholderTestCase(
179 '#markup' => BigPipeMarkup::create('<hello'),
182 '<hello' => ['#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::helloOrYarhar', []]],
194 $hello->bigPipeNoJsPlaceholder = 'big_pipe_nojs_placeholder_attribute_safe:<hello';
195 $hello->bigPipeNoJsPlaceholderRenderArray = [
196 '#markup' => 'big_pipe_nojs_placeholder_attribute_safe:<hello',
197 '#cache' => $cacheability_depends_on_session_only,
199 'big_pipe_nojs_placeholders' => [
200 'big_pipe_nojs_placeholder_attribute_safe:<hello' => $hello->placeholderRenderArray,
204 $hello->embeddedHtmlResponse = '<marquee>Yarhar llamas forever!</marquee>';
207 // 5. Edge case: non-#lazy_builder placeholder.
208 $current_time = new BigPipePlaceholderTestCase(
210 '#markup' => BigPipeMarkup::create('<time>CURRENT TIME</time>'),
213 '<time>CURRENT TIME</time>' => [
215 '\Drupal\big_pipe_test\BigPipeTestController::currentTime',
221 '<time>CURRENT TIME</time>',
223 '#pre_render' => ['current_time'],
226 $current_time->bigPipePlaceholderId = 'timecurrent-timetime';
227 $current_time->bigPipePlaceholderRenderArray = [
228 '#markup' => '<span data-big-pipe-placeholder-id="timecurrent-timetime"></span>',
229 '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
231 'library' => ['big_pipe/big_pipe'],
232 'drupalSettings' => [
233 'bigPipePlaceholderIds' => [
234 'timecurrent-timetime' => TRUE,
237 'big_pipe_placeholders' => [
238 'timecurrent-timetime' => $current_time->placeholderRenderArray,
242 $current_time->embeddedAjaxResponseCommands = [
244 'command' => 'insert',
245 'method' => 'replaceWith',
246 'selector' => '[data-big-pipe-placeholder-id="timecurrent-timetime"]',
247 'data' => '<time datetime="1991-03-14"></time>',
251 $current_time->bigPipeNoJsPlaceholder = '<span data-big-pipe-nojs-placeholder-id="timecurrent-timetime"></span>';
252 $current_time->bigPipeNoJsPlaceholderRenderArray = [
253 '#markup' => '<span data-big-pipe-nojs-placeholder-id="timecurrent-timetime"></span>',
254 '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
256 'big_pipe_nojs_placeholders' => [
257 '<span data-big-pipe-nojs-placeholder-id="timecurrent-timetime"></span>' => $current_time->placeholderRenderArray,
261 $current_time->embeddedHtmlResponse = '<time datetime="1991-03-14"></time>';
264 // 6. Edge case: #lazy_builder that throws an exception.
265 $exception = new BigPipePlaceholderTestCase(
267 '#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::exception', ['llamas', 'suck']],
268 '#create_placeholder' => TRUE,
270 '<drupal-render-placeholder callback="\Drupal\big_pipe_test\BigPipeTestController::exception" arguments="0=llamas&1=suck" token="uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></drupal-render-placeholder>',
272 '#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::exception', ['llamas', 'suck']],
275 $exception->bigPipePlaceholderId = 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU';
276 $exception->bigPipePlaceholderRenderArray = [
277 '#markup' => '<span data-big-pipe-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></span>',
278 '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
280 'library' => ['big_pipe/big_pipe'],
281 'drupalSettings' => [
282 'bigPipePlaceholderIds' => [
283 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU' => TRUE,
286 'big_pipe_placeholders' => [
287 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU' => $exception->placeholderRenderArray,
291 $exception->embeddedAjaxResponseCommands = NULL;
292 $exception->bigPipeNoJsPlaceholder = '<span data-big-pipe-nojs-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></span>';
293 $exception->bigPipeNoJsPlaceholderRenderArray = [
294 '#markup' => $exception->bigPipeNoJsPlaceholder,
295 '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
297 'big_pipe_nojs_placeholders' => [
298 $exception->bigPipeNoJsPlaceholder => $exception->placeholderRenderArray,
302 $exception->embeddedHtmlResponse = NULL;
304 // 7. Edge case: response filter throwing an exception for this placeholder.
305 $embedded_response_exception = new BigPipePlaceholderTestCase(
307 '#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::responseException', []],
308 '#create_placeholder' => TRUE,
310 '<drupal-render-placeholder callback="\Drupal\big_pipe_test\BigPipeTestController::responseException" arguments="" token="PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU"></drupal-render-placeholder>',
312 '#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::responseException', []],
315 $embedded_response_exception->bigPipePlaceholderId = 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&&token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU';
316 $embedded_response_exception->bigPipePlaceholderRenderArray = [
317 '#markup' => '<span data-big-pipe-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&&token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU"></span>',
318 '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
320 'library' => ['big_pipe/big_pipe'],
321 'drupalSettings' => [
322 'bigPipePlaceholderIds' => [
323 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&&token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU' => TRUE,
326 'big_pipe_placeholders' => [
327 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&&token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU' => $embedded_response_exception->placeholderRenderArray,
331 $embedded_response_exception->embeddedAjaxResponseCommands = NULL;
332 $embedded_response_exception->bigPipeNoJsPlaceholder = '<span data-big-pipe-nojs-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3AresponseException&&token=PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU"></span>';
333 $embedded_response_exception->bigPipeNoJsPlaceholderRenderArray = [
334 '#markup' => $embedded_response_exception->bigPipeNoJsPlaceholder,
335 '#cache' => $cacheability_depends_on_session_and_nojs_cookie,
337 'big_pipe_nojs_placeholders' => [
338 $embedded_response_exception->bigPipeNoJsPlaceholder => $embedded_response_exception->placeholderRenderArray,
342 $exception->embeddedHtmlResponse = NULL;
345 'html' => $status_messages,
346 'html_attribute_value' => $form_action,
347 'html_attribute_value_subset' => $csrf_token,
348 'edge_case__invalid_html' => $hello,
349 'edge_case__html_non_lazy_builder' => $current_time,
350 'exception__lazy_builder' => $exception,
351 'exception__embedded_response' => $embedded_response_exception,
357 class BigPipePlaceholderTestCase {
360 * The original render array.
367 * The expected corresponding placeholder string.
374 * The expected corresponding placeholder render array.
378 public $placeholderRenderArray;
381 * The expected BigPipe placeholder ID.
383 * (Only possible for HTML placeholders.)
387 public $bigPipePlaceholderId = NULL;
390 * The corresponding expected BigPipe placeholder render array.
394 public $bigPipePlaceholderRenderArray = NULL;
397 * The corresponding expected embedded AJAX response.
401 public $embeddedAjaxResponseCommands = NULL;
405 * The expected BigPipe no-JS placeholder.
407 * (Possible for all placeholders, HTML or non-HTML.)
411 public $bigPipeNoJsPlaceholder;
414 * The corresponding expected BigPipe no-JS placeholder render array.
418 public $bigPipeNoJsPlaceholderRenderArray;
421 * The corresponding expected embedded HTML response.
425 public $embeddedHtmlResponse;
427 public function __construct(array $render_array, $placeholder, array $placeholder_render_array) {
428 $this->renderArray = $render_array;
429 $this->placeholder = $placeholder;
430 $this->placeholderRenderArray = $placeholder_render_array;