You are here

public function FrameworkTest::testLazyLoad in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 core/modules/system/src/Tests/Ajax/FrameworkTest.php \Drupal\system\Tests\Ajax\FrameworkTest::testLazyLoad()

Tests that new JavaScript and CSS files are lazy-loaded on an AJAX request.

File

core/modules/system/src/Tests/Ajax/FrameworkTest.php, line 97
Contains \Drupal\system\Tests\Ajax\FrameworkTest.

Class

FrameworkTest
Performs tests on AJAX framework functions.

Namespace

Drupal\system\Tests\Ajax

Code

public function testLazyLoad() {
  $asset_resolver = \Drupal::service('asset.resolver');
  $css_collection_renderer = \Drupal::service('asset.css.collection_renderer');
  $js_collection_renderer = \Drupal::service('asset.js.collection_renderer');
  $renderer = \Drupal::service('renderer');
  $expected = array(
    'setting_name' => 'ajax_forms_test_lazy_load_form_submit',
    'setting_value' => 'executed',
    'library_1' => 'system/admin',
    'library_2' => 'system/drupal.system',
  );

  // Get the base page.
  $this
    ->drupalGet('ajax_forms_test_lazy_load_form');
  $original_settings = $this
    ->getDrupalSettings();
  $original_libraries = explode(',', $original_settings['ajaxPageState']['libraries']);

  // Verify that the base page doesn't have the settings and files that are to
  // be lazy loaded as part of the next requests.
  $this
    ->assertTrue(!isset($original_settings[$expected['setting_name']]), format_string('Page originally lacks the %setting, as expected.', array(
    '%setting' => $expected['setting_name'],
  )));
  $this
    ->assertTrue(!in_array($expected['library_1'], $original_libraries), format_string('Page originally lacks the %library library, as expected.', array(
    '%library' => $expected['library_1'],
  )));
  $this
    ->assertTrue(!in_array($expected['library_2'], $original_libraries), format_string('Page originally lacks the %library library, as expected.', array(
    '%library' => $expected['library_2'],
  )));

  // Calculate the expected CSS and JS.
  $assets = new AttachedAssets();
  $assets
    ->setLibraries([
    $expected['library_1'],
  ])
    ->setAlreadyLoadedLibraries($original_libraries);
  $css_render_array = $css_collection_renderer
    ->render($asset_resolver
    ->getCssAssets($assets, FALSE));
  $expected_css_html = $renderer
    ->renderRoot($css_render_array);
  $assets
    ->setLibraries([
    $expected['library_2'],
  ])
    ->setAlreadyLoadedLibraries($original_libraries);
  $js_assets = $asset_resolver
    ->getJsAssets($assets, FALSE)[1];
  unset($js_assets['drupalSettings']);
  $js_render_array = $js_collection_renderer
    ->render($js_assets);
  $expected_js_html = $renderer
    ->renderRoot($js_render_array);

  // Submit the AJAX request without triggering files getting added.
  $commands = $this
    ->drupalPostAjaxForm(NULL, array(
    'add_files' => FALSE,
  ), array(
    'op' => t('Submit'),
  ));
  $new_settings = $this
    ->getDrupalSettings();
  $new_libraries = explode(',', $new_settings['ajaxPageState']['libraries']);

  // Verify the setting was not added when not expected.
  $this
    ->assertTrue(!isset($new_settings[$expected['setting_name']]), format_string('Page still lacks the %setting, as expected.', array(
    '%setting' => $expected['setting_name'],
  )));
  $this
    ->assertTrue(!in_array($expected['library_1'], $new_libraries), format_string('Page still lacks the %library library, as expected.', array(
    '%library' => $expected['library_1'],
  )));
  $this
    ->assertTrue(!in_array($expected['library_2'], $new_libraries), format_string('Page still lacks the %library library, as expected.', array(
    '%library' => $expected['library_2'],
  )));

  // Verify a settings command does not add CSS or scripts to drupalSettings
  // and no command inserts the corresponding tags on the page.
  $found_settings_command = FALSE;
  $found_markup_command = FALSE;
  foreach ($commands as $command) {
    if ($command['command'] == 'settings' && (array_key_exists('css', $command['settings']['ajaxPageState']) || array_key_exists('js', $command['settings']['ajaxPageState']))) {
      $found_settings_command = TRUE;
    }
    if (isset($command['data']) && ($command['data'] == $expected_js_html || $command['data'] == $expected_css_html)) {
      $found_markup_command = TRUE;
    }
  }
  $this
    ->assertFalse($found_settings_command, format_string('Page state still lacks the %library_1 and %library_2 libraries, as expected.', array(
    '%library_1' => $expected['library_1'],
    '%library_2' => $expected['library_2'],
  )));
  $this
    ->assertFalse($found_markup_command, format_string('Page still lacks the %library_1 and %library_2 libraries, as expected.', array(
    '%library_1' => $expected['library_1'],
    '%library_2' => $expected['library_2'],
  )));

  // Submit the AJAX request and trigger adding files.
  $commands = $this
    ->drupalPostAjaxForm(NULL, array(
    'add_files' => TRUE,
  ), array(
    'op' => t('Submit'),
  ));
  $new_settings = $this
    ->getDrupalSettings();
  $new_libraries = explode(',', $new_settings['ajaxPageState']['libraries']);

  // Verify the expected setting was added, both to drupalSettings, and as
  // the first AJAX command.
  $this
    ->assertIdentical($new_settings[$expected['setting_name']], $expected['setting_value'], format_string('Page now has the %setting.', array(
    '%setting' => $expected['setting_name'],
  )));
  $expected_command = new SettingsCommand(array(
    $expected['setting_name'] => $expected['setting_value'],
  ), TRUE);
  $this
    ->assertCommand(array_slice($commands, 0, 1), $expected_command
    ->render(), 'The settings command was first.');

  // Verify the expected CSS file was added, both to drupalSettings, and as
  // the second AJAX command for inclusion into the HTML.
  $this
    ->assertTrue(in_array($expected['library_1'], $new_libraries), format_string('Page state now has the %library library.', array(
    '%library' => $expected['library_1'],
  )));
  $this
    ->assertCommand(array_slice($commands, 1, 1), array(
    'data' => $expected_css_html,
  ), format_string('Page now has the %library library.', array(
    '%library' => $expected['library_1'],
  )));

  // Verify the expected JS file was added, both to drupalSettings, and as
  // the third AJAX command for inclusion into the HTML. By testing for an
  // exact HTML string containing the SCRIPT tag, we also ensure that
  // unexpected JavaScript code, such as a jQuery.extend() that would
  // potentially clobber rather than properly merge settings, didn't
  // accidentally get added.
  $this
    ->assertTrue(in_array($expected['library_2'], $new_libraries), format_string('Page state now has the %library library.', array(
    '%library' => $expected['library_2'],
  )));
  $this
    ->assertCommand(array_slice($commands, 2, 1), array(
    'data' => $expected_js_html,
  ), format_string('Page now has the %library library.', array(
    '%library' => $expected['library_2'],
  )));
}