You are here

public function BubbleableMetadataTest::testMergeAttachmentsLibraryMerging in Drupal 9

Same name and namespace in other branches
  1. 8 core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php \Drupal\Tests\Core\Render\BubbleableMetadataTest::testMergeAttachmentsLibraryMerging()

Tests library asset merging.

@covers ::mergeAttachments

File

core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php, line 242

Class

BubbleableMetadataTest
@coversDefaultClass \Drupal\Core\Render\BubbleableMetadata @group Render

Namespace

Drupal\Tests\Core\Render

Code

public function testMergeAttachmentsLibraryMerging() {
  $a['#attached'] = [
    'library' => [
      'core/drupal',
      'core/drupalSettings',
    ],
    'drupalSettings' => [
      'foo' => [
        'd',
      ],
    ],
  ];
  $b['#attached'] = [
    'library' => [
      'core/jquery',
    ],
    'drupalSettings' => [
      'bar' => [
        'a',
        'b',
        'c',
      ],
    ],
  ];
  $expected['#attached'] = [
    'library' => [
      'core/drupal',
      'core/drupalSettings',
      'core/jquery',
    ],
    'drupalSettings' => [
      'foo' => [
        'd',
      ],
      'bar' => [
        'a',
        'b',
        'c',
      ],
    ],
  ];
  $this
    ->assertSame($expected['#attached'], BubbleableMetadata::mergeAttachments($a['#attached'], $b['#attached']), 'Attachments merged correctly.');

  // Merging in the opposite direction yields the opposite library order.
  $expected['#attached'] = [
    'library' => [
      'core/jquery',
      'core/drupal',
      'core/drupalSettings',
    ],
    'drupalSettings' => [
      'bar' => [
        'a',
        'b',
        'c',
      ],
      'foo' => [
        'd',
      ],
    ],
  ];
  $this
    ->assertSame($expected['#attached'], BubbleableMetadata::mergeAttachments($b['#attached'], $a['#attached']), 'Attachments merged correctly; opposite merging yields opposite order.');

  // Merging with duplicates: duplicates are simply retained, it's up to the
  // rest of the system to handle duplicates.
  $b['#attached']['library'][] = 'core/drupalSettings';
  $expected['#attached'] = [
    'library' => [
      'core/drupal',
      'core/drupalSettings',
      'core/jquery',
      'core/drupalSettings',
    ],
    'drupalSettings' => [
      'foo' => [
        'd',
      ],
      'bar' => [
        'a',
        'b',
        'c',
      ],
    ],
  ];
  $this
    ->assertSame($expected['#attached'], BubbleableMetadata::mergeAttachments($a['#attached'], $b['#attached']), 'Attachments merged correctly; duplicates are retained.');

  // Merging with duplicates (simple case).
  $b['#attached']['drupalSettings']['foo'] = [
    'a',
    'b',
    'c',
  ];
  $expected['#attached'] = [
    'library' => [
      'core/drupal',
      'core/drupalSettings',
      'core/jquery',
      'core/drupalSettings',
    ],
    'drupalSettings' => [
      'foo' => [
        'a',
        'b',
        'c',
      ],
      'bar' => [
        'a',
        'b',
        'c',
      ],
    ],
  ];
  $this
    ->assertSame($expected['#attached'], BubbleableMetadata::mergeAttachments($a['#attached'], $b['#attached']));

  // Merging with duplicates (simple case) in the opposite direction yields
  // the opposite JS setting asset order, but also opposite overriding order.
  $expected['#attached'] = [
    'library' => [
      'core/jquery',
      'core/drupalSettings',
      'core/drupal',
      'core/drupalSettings',
    ],
    'drupalSettings' => [
      'bar' => [
        'a',
        'b',
        'c',
      ],
      'foo' => [
        'd',
        'b',
        'c',
      ],
    ],
  ];
  $this
    ->assertSame($expected['#attached'], BubbleableMetadata::mergeAttachments($b['#attached'], $a['#attached']));

  // Merging with duplicates: complex case.
  // Only the second of these two entries should appear in drupalSettings.
  $build = [];
  $build['a']['#attached']['drupalSettings']['commonTest'] = 'firstValue';
  $build['b']['#attached']['drupalSettings']['commonTest'] = 'secondValue';

  // Only the second of these entries should appear in drupalSettings.
  $build['a']['#attached']['drupalSettings']['commonTestJsArrayLiteral'] = [
    'firstValue',
  ];
  $build['b']['#attached']['drupalSettings']['commonTestJsArrayLiteral'] = [
    'secondValue',
  ];

  // Only the second of these two entries should appear in drupalSettings.
  $build['a']['#attached']['drupalSettings']['commonTestJsObjectLiteral'] = [
    'key' => 'firstValue',
  ];
  $build['b']['#attached']['drupalSettings']['commonTestJsObjectLiteral'] = [
    'key' => 'secondValue',
  ];

  // Real world test case: multiple elements in a render array are adding the
  // same (or nearly the same) JavaScript settings. When merged, they should
  // contain all settings and not duplicate some settings.
  $settings_one = [
    'moduleName' => [
      'ui' => [
        'button A',
        'button B',
      ],
      'magical flag' => 3.14159265359,
    ],
  ];
  $build['a']['#attached']['drupalSettings']['commonTestRealWorldIdentical'] = $settings_one;
  $build['b']['#attached']['drupalSettings']['commonTestRealWorldIdentical'] = $settings_one;
  $settings_two_a = [
    'moduleName' => [
      'ui' => [
        'button A',
        'button B',
        'button C',
      ],
      'magical flag' => 3.14159265359,
      'thingiesOnPage' => [
        'id1' => [],
      ],
    ],
  ];
  $build['a']['#attached']['drupalSettings']['commonTestRealWorldAlmostIdentical'] = $settings_two_a;
  $settings_two_b = [
    'moduleName' => [
      'ui' => [
        'button D',
        'button E',
      ],
      'magical flag' => 3.14,
      'thingiesOnPage' => [
        'id2' => [],
      ],
    ],
  ];
  $build['b']['#attached']['drupalSettings']['commonTestRealWorldAlmostIdentical'] = $settings_two_b;
  $merged = BubbleableMetadata::mergeAttachments($build['a']['#attached'], $build['b']['#attached']);

  // Test whether #attached can be used to override a previous setting.
  $this
    ->assertSame('secondValue', $merged['drupalSettings']['commonTest']);

  // Test whether #attached can be used to add and override a JavaScript
  // array literal (an indexed PHP array) values.
  $this
    ->assertSame('secondValue', $merged['drupalSettings']['commonTestJsArrayLiteral'][0]);

  // Test whether #attached can be used to add and override a JavaScript
  // object literal (an associate PHP array) values.
  $this
    ->assertSame('secondValue', $merged['drupalSettings']['commonTestJsObjectLiteral']['key']);

  // Test whether the two real world cases are handled correctly: the first
  // adds the exact same settings twice and hence tests idempotency, the
  // second adds *almost* the same settings twice: the second time, some
  // values are altered, and some key-value pairs are added.
  $this
    ->assertSame($settings_one, $merged['drupalSettings']['commonTestRealWorldIdentical']);
  $expected_settings_two = $settings_two_a;
  $expected_settings_two['moduleName']['thingiesOnPage']['id1'] = [];
  $expected_settings_two['moduleName']['ui'][0] = 'button D';
  $expected_settings_two['moduleName']['ui'][1] = 'button E';
  $expected_settings_two['moduleName']['ui'][2] = 'button C';
  $expected_settings_two['moduleName']['magical flag'] = 3.14;
  $expected_settings_two['moduleName']['thingiesOnPage']['id2'] = [];
  $this
    ->assertSame($expected_settings_two, $merged['drupalSettings']['commonTestRealWorldAlmostIdentical']);
}