summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2014-12-09 11:55:57 (GMT)
committerNathaniel Catchpole2014-12-09 11:55:57 (GMT)
commit77c613e36fb852fab1b3f5365ed54f206f44416b (patch)
tree4aa28df226ff9ec8f8c0870362dcb8ab79ea35dd
parentcd0cb0d7c962b95213124da84b656f97a36756f2 (diff)
Issue #2382533 by Wim Leers: Attach assets only via the asset library system
-rw-r--r--core/includes/common.inc147
-rw-r--r--core/lib/Drupal/Core/Asset/CssCollectionRenderer.php15
-rw-r--r--core/lib/Drupal/Core/Asset/JsCollectionRenderer.php8
-rw-r--r--core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php6
-rw-r--r--core/modules/comment/comment.libraries.yml4
-rw-r--r--core/modules/history/history.libraries.yml9
-rw-r--r--core/modules/history/history.module7
-rw-r--r--core/modules/history/js/mark-as-read.js19
-rw-r--r--core/modules/history/src/Tests/HistoryTest.php5
-rw-r--r--core/modules/quickedit/quickedit.module3
-rw-r--r--core/modules/system/src/Tests/Ajax/FrameworkTest.php34
-rw-r--r--core/modules/system/src/Tests/Common/AttachedAssetsTest.php408
-rw-r--r--core/modules/system/src/Tests/Common/CascadingStylesheetsTest.php185
-rw-r--r--core/modules/system/src/Tests/Common/JavaScriptTest.php660
-rw-r--r--core/modules/system/src/Tests/Common/MergeAttachmentsTest.php94
-rw-r--r--core/modules/system/src/Tests/Common/RenderTest.php23
-rw-r--r--core/modules/system/tests/modules/ajax_test/ajax_test.libraries.yml20
-rw-r--r--core/modules/system/tests/modules/ajax_test/ajax_test.module23
-rw-r--r--core/modules/system/tests/modules/common_test/common_test.libraries.yml103
-rw-r--r--core/modules/system/theme.api.php28
-rw-r--r--core/modules/views/src/Tests/Plugin/CacheTest.php5
-rw-r--r--core/modules/views/src/ViewExecutable.php18
-rw-r--r--core/modules/views/tests/modules/views_test_data/views_test_data.views_execution.inc3
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php58
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php46
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php81
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php35
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/css_test_files/charset.css1
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/css_test_files/charset.css.optimized.css1
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_newline.css2
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_sameline.css1
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_sameline.css.optimized.css1
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/library_test_files/external.libraries.yml4
-rw-r--r--core/tests/Drupal/Tests/Core/Asset/library_test_files/versions.libraries.yml22
34 files changed, 756 insertions, 1323 deletions
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 0d9c094..3ec9576 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -871,9 +871,7 @@ function _drupal_add_html_head_link($attributes, $header = FALSE) {
* If CSS aggregation/compression is enabled, all cascading style sheets added
* with $options['preprocess'] set to TRUE will be merged into one aggregate
* file and compressed by removing all extraneous white space.
- * Preprocessed inline stylesheets will not be aggregated into this single file;
- * instead, they are just compressed upon output on the page. Externally hosted
- * stylesheets are never aggregated or compressed.
+ * Externally hosted stylesheets are never aggregated or compressed.
*
* The reason for aggregating the files is outlined quite thoroughly here:
* http://www.die.net/musings/page_load_time/ "Load fewer external objects. Due
@@ -899,18 +897,15 @@ function _drupal_add_html_head_link($attributes, $header = FALSE) {
* override module-supplied CSS files based on their filenames, and this
* prefixing helps prevent confusing name collisions for theme developers.
* See drupal_get_css() where the overrides are performed.
- * - 'inline': A string of CSS that should be placed in the given scope. Note
- * that it is better practice to use 'file' stylesheets, rather than
- * 'inline', as the CSS would then be aggregated and cached.
* - 'external': The absolute path to an external CSS file that is not hosted
* on the local server. These files will not be aggregated if CSS
* aggregation is enabled.
* @param $options
* (optional) A string defining the 'type' of CSS that is being added in the
- * $data parameter ('file', 'inline', or 'external'), or an array which can
- * have any or all of the following keys:
- * - 'type': The type of stylesheet being added. Available options are 'file',
- * 'inline' or 'external'. Defaults to 'file'.
+ * $data parameter ('file' or 'external'), or an array which can have any or
+ * all of the following keys:
+ * - 'type': The type of stylesheet being added. Available options are 'file'
+ * or 'external'. Defaults to 'file'.
* - 'basename': Force a basename for the file being added. Modules are
* expected to use stylesheets with unique filenames, but integration of
* external libraries may make this impossible. The basename of
@@ -1027,12 +1022,6 @@ function _drupal_add_css($data = NULL, $options = NULL) {
// Add the data to the CSS array depending on the type.
switch ($options['type']) {
- case 'inline':
- // For inline stylesheets, we don't want to use the $data as the array
- // key as $data could be a very long string of CSS.
- $css[] = $options;
- break;
-
case 'file':
// Local CSS files are keyed by basename; if a file with the same
// basename is added more than once, it gets overridden.
@@ -1278,21 +1267,12 @@ function drupal_clean_id_identifier($id) {
}
/**
- * Adds a JavaScript file, setting, or inline code to the page.
+ * Adds a JavaScript file or setting to the page.
*
* The behavior of this function depends on the parameters it is called with.
- * Generally, it handles the addition of JavaScript to the page, either as
- * reference to an existing file or as inline code. The following actions can be
- * performed using this function:
+ * Generally, it handles the addition of JavaScript to the page. The following
+ * actions can be performed using this function:
* - Add a file ('file'): Adds a reference to a JavaScript file to the page.
- * - Add inline JavaScript code ('inline'): Executes a piece of JavaScript code
- * on the current page by placing the code directly in the page (for example,
- * to tell the user that a new message arrived, by opening a pop up, alert
- * box, etc.). This should only be used for JavaScript that cannot be executed
- * from a file. When adding inline code, make sure that you are not relying on
- * $() being the jQuery function. Wrap your code in
- * @code (function ($) {... })(jQuery); @endcode
- * or use jQuery() instead of $().
* - Add external JavaScript ('external'): Allows the inclusion of external
* JavaScript files that are not hosted on the local server. Note that these
* external JavaScript references do not get aggregated when preprocessing is
@@ -1305,10 +1285,6 @@ function drupal_clean_id_identifier($id) {
* @code
* _drupal_add_js('core/misc/collapse.js');
* _drupal_add_js('core/misc/collapse.js', 'file');
- * _drupal_add_js('jQuery(document).ready(function () { alert("Hello!"); });', 'inline');
- * _drupal_add_js('jQuery(document).ready(function () { alert("Hello!"); });',
- * array('type' => 'inline', 'scope' => 'footer', 'weight' => 5)
- * );
* _drupal_add_js('http://example.com/example.js', 'external');
* _drupal_add_js(array('myModule' => array('key' => 'value')), 'setting');
* @endcode
@@ -1318,7 +1294,6 @@ function drupal_clean_id_identifier($id) {
*
* If JavaScript aggregation is enabled, all JavaScript files added with
* $options['preprocess'] set to TRUE will be merged into one aggregate file.
- * Preprocessed inline JavaScript will not be aggregated into this single file.
* Externally hosted JavaScripts are never aggregated.
*
* The reason for aggregating the files is outlined quite thoroughly here:
@@ -1338,7 +1313,6 @@ function drupal_clean_id_identifier($id) {
* (optional) If given, the value depends on the $options parameter, or
* $options['type'] if $options is passed as an associative array:
* - 'file': Path to the file relative to base_path().
- * - 'inline': The JavaScript code that should be placed in the given scope.
* - 'external': The absolute path to an external JavaScript file that is not
* hosted on the local server. These files will not be aggregated if
* JavaScript aggregation is enabled.
@@ -1350,11 +1324,11 @@ function drupal_clean_id_identifier($id) {
* added to the existing settings array.
* @param $options
* (optional) A string defining the type of JavaScript that is being added in
- * the $data parameter ('file'/'setting'/'inline'/'external'), or an
- * associative array. JavaScript settings should always pass the string
- * 'setting' only. Other types can have the following elements in the array:
+ * the $data parameter ('file'/'setting'/'external'), or an associative array.
+ * JavaScript settings should always pass the string 'setting' only. Other
+ * types can have the following elements in the array:
* - type: The type of JavaScript that is to be added to the page. Allowed
- * values are 'file', 'inline', 'external' or 'setting'. Defaults
+ * values are 'file', 'external' or 'setting'. Defaults
* to 'file'.
* - scope: The location in which you want to place the script. Possible
* values are 'header' or 'footer'. If your theme implements different
@@ -1467,15 +1441,9 @@ function _drupal_add_js($data = NULL, $options = NULL) {
'data' => array(),
);
}
- // All JavaScript settings are placed in the header of the page with
- // the library weight so that inline scripts appear afterwards.
$javascript['drupalSettings']['data'] = NestedArray::mergeDeepArray([$javascript['drupalSettings']['data'], $data], TRUE);
break;
- case 'inline':
- $javascript[] = $options;
- break;
-
default: // 'file' and 'external'
// Local and external files must keep their name as the associative key
// so the same JavaScript file is not added twice.
@@ -1515,8 +1483,8 @@ function drupal_js_defaults($data = NULL) {
*
* References to JavaScript files are placed in a certain order: first, all
* 'core' files, then all 'module' and finally all 'theme' JavaScript files
- * are added to the page. Then, all settings are output, followed by 'inline'
- * JavaScript code. If running update.php, all preprocessing is disabled.
+ * are added to the page. Then, all settings are output. If running update.php,
+ * all preprocessing is disabled.
*
* Note that hook_js_alter(&$javascript) is called during this function call
* to allow alterations of the JavaScript during its presentation. Calls to
@@ -1694,44 +1662,40 @@ function drupal_merge_attached(array $a, array $b) {
/**
* Adds attachments to a render() structure.
*
- * Libraries, JavaScript, CSS and other types of custom structures are attached
- * to elements using the #attached property. The #attached property is an
- * associative array, where the keys are the the attachment types and the values
- * are the attached data. For example:
+ * Libraries, JavaScript settings, feeds, HTML <head> tags and HTML <head> links
+ * are attached to elements using the #attached property. The #attached property
+ * is an associative array, where the keys are the attachment types and the
+ * values are the attached data. For example:
*
* @code
- * $build['#attached'] = array(
- * 'library' => array(array('taxonomy', 'taxonomy')),
- * 'css' => array(drupal_get_path('module', 'taxonomy') . '/css/taxonomy.module.css'),
- * );
+ * $build['#attached'] = [
+ * 'library' => ['core/jquery']
+ * ];
* @endcode
*
- * 'js', 'css', and 'library' are types that get special handling. For any
- * other kind of attached data, the array key must be the full name of the
- * callback function and each value an array of arguments. For example:
+ * The available keys are:
+ * - 'library' (asset libraries)
+ * - 'drupalSettings' (JavaScript settings)
+ * - 'feed' (RSS feeds)
+ * - 'html_head' (tags in HTML <head>)
+ * - 'html_head_link' (<link> tags in HTML <head>)
+ * - 'http_header' (HTTP headers)
+ *
+ * For example:
* @code
* $build['#attached']['http_header'] = array(
* array('Content-Type', 'application/rss+xml; charset=utf-8'),
* );
* @endcode
*
- * External 'js' and 'css' files can also be loaded. For example:
- * @code
- * $build['#attached']['js'] = array(
- * 'http://code.jquery.com/jquery-1.4.2.min.js' => array(
- * 'type' => 'external',
- * ),
- * );
- * @endcode
- *
- * @param $elements
+ * @param array $elements
* The structured array describing the data being rendered.
- * @param $dependency_check
+ * @param bool $dependency_check
* When TRUE, will exit if a given library's dependencies are missing. When
* set to FALSE, will continue to add the libraries, even though one or more
* dependencies are missing. Defaults to FALSE.
*
- * @return
+ * @return bool
* FALSE if there were any missing library dependencies; TRUE if all library
* dependencies were met.
*
@@ -1740,12 +1704,10 @@ function drupal_merge_attached(array $a, array $b) {
* @see _drupal_add_css()
* @see drupal_render()
*/
-function drupal_process_attached($elements, $dependency_check = FALSE) {
+function drupal_process_attached(array $elements, $dependency_check = FALSE) {
// Add defaults to the special attached structures that should be processed differently.
$elements['#attached'] += array(
'library' => array(),
- 'js' => array(),
- 'css' => array(),
);
// Add the libraries first.
@@ -1761,30 +1723,8 @@ function drupal_process_attached($elements, $dependency_check = FALSE) {
}
unset($elements['#attached']['library']);
- // Add both the JavaScript and the CSS.
- // The parameters for _drupal_add_js() and _drupal_add_css() require special
- // handling.
- foreach (array('js', 'css') as $type) {
- foreach ($elements['#attached'][$type] as $data => $options) {
- // If the value is not an array, it's a filename and passed as first
- // (and only) argument.
- if (!is_array($options)) {
- $data = $options;
- $options = NULL;
- }
- // In some cases, the first parameter ($data) is an array. Arrays can't be
- // passed as keys in PHP, so we have to get $data from the value array.
- if (is_numeric($data)) {
- $data = $options['data'];
- unset($options['data']);
- }
- call_user_func('_drupal_add_' . $type, $data, $options);
- }
- unset($elements['#attached'][$type]);
- }
-
// Convert every JavaScript settings asset into a regular JavaScript asset.
- // @todo Clean this up in https://www.drupal.org/node/2382533
+ // @todo Clean this up in https://www.drupal.org/node/2368797
if (!empty($elements['#attached']['drupalSettings'])) {
_drupal_add_js($elements['#attached']['drupalSettings'], ['type' => 'setting']);
unset($elements['#attached']['drupalSettings']);
@@ -1994,22 +1934,21 @@ function _drupal_add_library($library_name, $every_page = NULL) {
// Add all components within the library.
$elements['#attached'] = array(
'library' => $library['dependencies'],
- 'js' => $library['js'],
- 'css' => $library['css'],
);
if (isset($library['drupalSettings'])) {
$elements['#attached']['drupalSettings'] = $library['drupalSettings'];
}
+ $added[$extension][$name] = drupal_process_attached($elements, TRUE);
+
+ // Add both the JavaScript and the CSS.
+ // The parameters for _drupal_add_js() and _drupal_add_css() require special
+ // handling.
foreach (array('js', 'css') as $type) {
- foreach ($elements['#attached'][$type] as $data => $options) {
- // Set the every_page flag if one was passed.
- if (isset($every_page)) {
- $elements['#attached'][$type][$data]['every_page'] = $every_page;
- }
+ foreach ($library[$type] as $options) {
+ call_user_func('_drupal_add_' . $type, $options['data'], $options);
}
+ unset($elements['#attached'][$type]);
}
-
- $added[$extension][$name] = drupal_process_attached($elements, TRUE);
}
else {
// Requested library does not exist.
diff --git a/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php b/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
index ab07555..d00fcb4 100644
--- a/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
+++ b/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
@@ -158,21 +158,6 @@ class CssCollectionRenderer implements AssetCollectionRendererInterface {
}
break;
- // Output a STYLE tag for an inline CSS asset. The asset's 'data'
- // property contains the CSS content.
- case 'inline':
- $element = $style_element_defaults;
- $element['#value'] = $css_asset['data'];
- $element['#attributes']['media'] = $css_asset['media'];
- $element['#browsers'] = $css_asset['browsers'];
- // For inline CSS to validate as XHTML, all CSS containing XHTML needs
- // to be wrapped in CDATA. To make that backwards compatible with HTML
- // 4, we need to comment out the CDATA-tag.
- $element['#value_prefix'] = "\n/* <![CDATA[ */\n";
- $element['#value_suffix'] = "\n/* ]]> */\n";
- $elements[] = $element;
- break;
-
// Output a LINK tag for an external CSS asset. The asset's 'data'
// property contains the full URL.
case 'external':
diff --git a/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php b/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
index 36f012b..52e6fe1 100644
--- a/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
+++ b/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
@@ -72,14 +72,8 @@ class JsCollectionRenderer implements AssetCollectionRendererInterface {
$element['#value_suffix'] = $embed_suffix;
break;
- case 'inline':
- $element['#value_prefix'] = $embed_prefix;
- $element['#value'] = $js_asset['data'];
- $element['#value_suffix'] = $embed_suffix;
- break;
-
case 'file':
- $query_string = empty($js_asset['version']) ? $default_query_string : 'v=' . $js_asset['version'];
+ $query_string = $js_asset['version'] == -1 ? $default_query_string : 'v=' . $js_asset['version'];
$query_string_separator = (strpos($js_asset['data'], '?') !== FALSE) ? '&' : '?';
$element['#attributes']['src'] = file_create_url($js_asset['data']);
// Only add the cache-busting query string if this isn't an aggregate
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
index ec5f457..5ff88b2 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
@@ -197,12 +197,6 @@ class LibraryDiscoveryParser {
$library[$type][] = $options;
}
}
-
- // @todo Convert all uses of #attached[library][]=array('provider','name')
- // into #attached[library][]='provider/name' and remove this.
- foreach ($library['dependencies'] as $i => $dependency) {
- $library['dependencies'][$i] = $dependency;
- }
}
return $libraries;
diff --git a/core/modules/comment/comment.libraries.yml b/core/modules/comment/comment.libraries.yml
index 46c98e7..d19ff93 100644
--- a/core/modules/comment/comment.libraries.yml
+++ b/core/modules/comment/comment.libraries.yml
@@ -30,7 +30,7 @@ drupal.comment-new-indicator:
- core/jquery
- core/jquery.once
- core/drupal
- - history/drupal.history
+ - history/api
- core/drupal.displace
drupal.node-new-comments-link:
@@ -41,4 +41,4 @@ drupal.node-new-comments-link:
- core/jquery
- core/jquery.once
- core/drupal
- - history/drupal.history
+ - history/api
diff --git a/core/modules/history/history.libraries.yml b/core/modules/history/history.libraries.yml
index 4920096..457b1f4 100644
--- a/core/modules/history/history.libraries.yml
+++ b/core/modules/history/history.libraries.yml
@@ -1,4 +1,4 @@
-drupal.history:
+api:
version: VERSION
js:
js/history.js: {}
@@ -7,3 +7,10 @@ drupal.history:
- core/drupalSettings
- core/drupal
- core/drupal.ajax
+
+mark-as-read:
+ version: VERSION
+ js:
+ js/mark-as-read.js: { scope: footer }
+ dependencies:
+ - history/api
diff --git a/core/modules/history/history.module b/core/modules/history/history.module
index bd8ca71..61395de 100644
--- a/core/modules/history/history.module
+++ b/core/modules/history/history.module
@@ -138,11 +138,8 @@ function history_node_view_alter(array &$build, EntityInterface $node, EntityVie
// When the window's "load" event is triggered, mark the node as read.
// This still allows for Drupal behaviors (which are triggered on the
// "DOMContentReady" event) to add "new" and "updated" indicators.
- $build['#attached']['js'][] = array(
- 'data' => 'window.addEventListener("load",function(){Drupal.history.markAsRead(' . $node->id() . ');},false);',
- 'type' => 'inline',
- );
- $build['#attached']['library'][] = 'history/drupal.history';
+ $build['#attached']['library'][] = 'history/mark-as-read';
+ $build['#attached']['drupalSettings']['history']['nodesToMarkAsRead'][$node->id()] = TRUE;
}
}
diff --git a/core/modules/history/js/mark-as-read.js b/core/modules/history/js/mark-as-read.js
new file mode 100644
index 0000000..d5b62ec
--- /dev/null
+++ b/core/modules/history/js/mark-as-read.js
@@ -0,0 +1,19 @@
+/**
+ * Marks the nodes listed in drupalSettings.history.nodesToMarkAsRead as read.
+ *
+ * Uses the History module JavaScript API.
+ */
+(function (window, Drupal, drupalSettings) {
+
+ "use strict";
+
+ // When the window's "load" event is triggered, mark all enumerated nodes as
+ // read. This still allows for Drupal behaviors (which are triggered on the
+ // "DOMContentReady" event) to add "new" and "updated" indicators.
+ window.addEventListener('load', function() {
+ if (drupalSettings.history && drupalSettings.history.nodesToMarkAsRead) {
+ Object.keys(drupalSettings.history.nodesToMarkAsRead).forEach(Drupal.history.markAsRead);
+ }
+ });
+
+})(window, Drupal, drupalSettings);
diff --git a/core/modules/history/src/Tests/HistoryTest.php b/core/modules/history/src/Tests/HistoryTest.php
index 3acd3c4..cdbfd68 100644
--- a/core/modules/history/src/Tests/HistoryTest.php
+++ b/core/modules/history/src/Tests/HistoryTest.php
@@ -119,8 +119,9 @@ class HistoryTest extends WebTestBase {
$this->drupalGet('node/' . $nid);
// JavaScript present to record the node read.
$settings = $this->getDrupalSettings();
- $this->assertTrue(isset($settings['ajaxPageState']['js']['core/modules/history/js/history.js']), 'drupal.history library is present.');
- $this->assertRaw('Drupal.history.markAsRead(' . $nid . ')', 'History module JavaScript API call to mark node as read present on page.');
+ $this->assertTrue(isset($settings['ajaxPageState']['js']['core/modules/history/js/history.js']), 'history/api library is present.');
+ $this->assertTrue(isset($settings['ajaxPageState']['js']['core/modules/history/js/mark-as-read.js']), 'history/mark-as-read library is present.');
+ $this->assertEqual([$nid => TRUE], $settings['history']['nodesToMarkAsRead'], 'drupalSettings to mark node as read are present.');
// Simulate JavaScript: perform HTTP request to mark node as read.
$response = $this->markNodeAsRead($nid);
diff --git a/core/modules/quickedit/quickedit.module b/core/modules/quickedit/quickedit.module
index 7ed6f92..5066c14 100644
--- a/core/modules/quickedit/quickedit.module
+++ b/core/modules/quickedit/quickedit.module
@@ -99,7 +99,8 @@ function quickedit_library_alter(array &$library, $name, $theme = NULL) {
}
if (isset($info['quickedit_stylesheets']) && is_array($info['quickedit_stylesheets'])) {
foreach ($info['quickedit_stylesheets'] as $path) {
- $library['css'][$theme_path . '/' . $path] = array(
+ $library['css'][] = array(
+ 'data' => $theme_path . '/' . $path,
'group' => CSS_AGGREGATE_THEME,
'weight' => CSS_THEME,
);
diff --git a/core/modules/system/src/Tests/Ajax/FrameworkTest.php b/core/modules/system/src/Tests/Ajax/FrameworkTest.php
index d998f01..cded8cb 100644
--- a/core/modules/system/src/Tests/Ajax/FrameworkTest.php
+++ b/core/modules/system/src/Tests/Ajax/FrameworkTest.php
@@ -35,44 +35,18 @@ class FrameworkTest extends AjaxTestBase {
* Tests AjaxResponse::prepare() AJAX commands ordering.
*/
public function testOrder() {
- $path = drupal_get_path('module', 'system');
$expected_commands = array();
// Expected commands, in a very specific order.
$expected_commands[0] = new SettingsCommand(array('ajax' => 'test'), TRUE);
drupal_static_reset('_drupal_add_css');
- $attached = array(
- '#attached' => array(
- 'css' => array(
- $path . '/css/system.admin.css' => array(),
- $path . '/css/system.maintenance.css' => array()
- ),
- ),
- );
- drupal_render($attached);
- drupal_process_attached($attached);
+ $build['#attached']['library'][] = 'ajax_test/order-css-command';
+ drupal_process_attached($build);
$expected_commands[1] = new AddCssCommand(drupal_get_css(_drupal_add_css(), TRUE));
drupal_static_reset('_drupal_add_js');
- $attached = array(
- '#attached' => array(
- 'js' => array(
- $path . '/system.js' => array(),
- ),
- ),
- );
- drupal_render($attached);
- drupal_process_attached($attached);
+ $build['#attached']['library'][] = 'ajax_test/order-js-command';
+ drupal_process_attached($build);
$expected_commands[2] = new PrependCommand('head', drupal_get_js('header', _drupal_add_js(), TRUE));
- drupal_static_reset('_drupal_add_js');
- $attached = array(
- '#attached' => array(
- 'js' => array(
- $path . '/system.modules.js' => array('scope' => 'footer'),
- ),
- ),
- );
- drupal_render($attached);
- drupal_process_attached($attached);
$expected_commands[3] = new AppendCommand('body', drupal_get_js('footer', _drupal_add_js(), TRUE));
$expected_commands[4] = new HtmlCommand('body', 'Hello, world!');
diff --git a/core/modules/system/src/Tests/Common/AttachedAssetsTest.php b/core/modules/system/src/Tests/Common/AttachedAssetsTest.php
new file mode 100644
index 0000000..fd44155
--- /dev/null
+++ b/core/modules/system/src/Tests/Common/AttachedAssetsTest.php
@@ -0,0 +1,408 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Common\JavaScriptTest.
+ */
+
+namespace Drupal\system\Tests\Common;
+
+use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\Unicode;
+use Drupal\Component\Utility\Crypt;
+use Drupal\simpletest\KernelTestBase;
+
+/**
+ * Tests #attached assets: attached asset libraries and JavaScript settings.
+ *
+ * i.e. tests:
+ *
+ * @code
+ * $build['#attached']['library'] = …
+ * $build['#attached']['drupalSettings'] = …
+ * @endcode
+ *
+ * @group Common
+ * @group Asset
+ */
+class AttachedAssetsTest extends KernelTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public static $modules = array('language', 'simpletest', 'common_test', 'system');
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ // Disable preprocessing.
+ \Drupal::config('system.performance')
+ ->set('css.preprocess', FALSE)
+ ->set('js.preprocess', FALSE)
+ ->save();
+
+ // Reset _drupal_add_css() and _drupal_add_js() statics before each test.
+ drupal_static_reset('_drupal_add_css');
+ drupal_static_reset('_drupal_add_js');
+
+ $this->installSchema('system', 'router');
+ \Drupal::service('router.builder')->rebuild();
+ }
+
+ /**
+ * Tests that default CSS and JavaScript is empty.
+ */
+ function testDefault() {
+ $build['#attached'] = [];
+ drupal_process_attached($build);
+
+ $this->assertEqual(array(), _drupal_add_css(), 'Default CSS is empty.');
+ $this->assertEqual(array(), _drupal_add_js(), 'Default JavaScript is empty.');
+ }
+
+ /**
+ * Tests non-existing libraries.
+ */
+ function testLibraryUnknown() {
+ $build['#attached']['library'][] = 'unknown/unknown';
+ drupal_process_attached($build);
+
+ $scripts = drupal_get_js();
+ $this->assertTrue(strpos($scripts, 'unknown') === FALSE, 'Unknown library was not added to the page.');
+ }
+
+ /**
+ * Tests adding a CSS and a JavaScript file.
+ */
+ function testAddFiles() {
+ $build['#attached']['library'][] = 'common_test/files';
+ drupal_process_attached($build);
+
+ $css = _drupal_add_css();
+ $js = _drupal_add_js();
+ $this->assertTrue(array_key_exists('bar.css', $css), 'CSS files are correctly added.');
+ $this->assertTrue(array_key_exists('core/modules/system/tests/modules/common_test/foo.js', $js), 'JavaScript files are correctly added.');
+
+ $rendered_css = drupal_get_css();
+ $rendered_js = drupal_get_js();
+ $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
+ $this->assertNotIdentical(strpos($rendered_css, '<link rel="stylesheet" href="' . file_create_url('core/modules/system/tests/modules/common_test/bar.css') . '?' . $query_string . '" media="all" />'), FALSE, 'Rendering an external CSS file.');
+ $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/foo.js') . '?' . $query_string . '"></script>'), FALSE, 'Rendering an external JavaScript file.');
+ }
+
+ /**
+ * Tests adding JavaScript settings.
+ */
+ function testAddJsSettings() {
+ // Add a file in order to test default settings.
+ $build['#attached']['library'][] = 'core/drupalSettings';
+ drupal_process_attached($build);
+
+ $javascript = _drupal_add_js();
+ $this->assertTrue(array_key_exists('currentPath', $javascript['drupalSettings']['data']['path']), 'The current path JavaScript setting is set correctly.');
+
+ $javascript = _drupal_add_js(array('drupal' => 'rocks', 'dries' => 280342800), 'setting');
+ $this->assertEqual(280342800, $javascript['drupalSettings']['data']['dries'], 'JavaScript setting is set correctly.');
+ $this->assertEqual('rocks', $javascript['drupalSettings']['data']['drupal'], 'The other JavaScript setting is set correctly.');
+ }
+
+ /**
+ * Tests adding external CSS and JavaScript files.
+ */
+ function testAddExternalFiles() {
+ $build['#attached']['library'][] = 'common_test/external';
+ drupal_process_attached($build);
+
+ $css = _drupal_add_css();
+ $js = _drupal_add_js();
+ $this->assertTrue(array_key_exists('http://example.com/stylesheet.css', $css), 'External CSS files are correctly added.');
+ $this->assertTrue(array_key_exists('http://example.com/script.js', $js), 'External JavaScript files are correctly added.');
+
+ $rendered_css = drupal_get_css();
+ $rendered_js = drupal_get_js();
+ $this->assertNotIdentical(strpos($rendered_css, '<link rel="stylesheet" href="http://example.com/stylesheet.css" media="all" />'), FALSE, 'Rendering an external CSS file.');
+ $this->assertNotIdentical(strpos($rendered_js, '<script src="http://example.com/script.js"></script>'), FALSE, 'Rendering an external JavaScript file.');
+ }
+
+ /**
+ * Tests adding JavaScript files with additional attributes.
+ */
+ function testAttributes() {
+ $build['#attached']['library'][] = 'common_test/js-attributes';
+ drupal_process_attached($build);
+
+ $rendered_js = drupal_get_js();
+ $expected_1 = '<script src="http://example.com/deferred-external.js" foo="bar" defer></script>';
+ $expected_2 = '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/deferred-internal.js') . '?v=1" defer bar="foo"></script>';
+ $this->assertNotIdentical(strpos($rendered_js, $expected_1), FALSE, 'Rendered external JavaScript with correct defer and random attributes.');
+ $this->assertNotIdentical(strpos($rendered_js, $expected_2), FALSE, 'Rendered internal JavaScript with correct defer and random attributes.');
+ }
+
+ /**
+ * Tests that attributes are maintained when JS aggregation is enabled.
+ */
+ function testAggregatedAttributes() {
+ // Enable aggregation.
+ \Drupal::config('system.performance')->set('js.preprocess', 1)->save();
+
+ $build['#attached']['library'][] = 'common_test/js-attributes';
+ drupal_process_attached($build);
+
+ $rendered_js = drupal_get_js();
+ $expected_1 = '<script src="http://example.com/deferred-external.js" foo="bar" defer></script>';
+ $expected_2 = '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/deferred-internal.js') . '?v=1" defer bar="foo"></script>';
+ $this->assertNotIdentical(strpos($rendered_js, $expected_1), FALSE, 'Rendered external JavaScript with correct defer and random attributes.');
+ $this->assertNotIdentical(strpos($rendered_js, $expected_2), FALSE, 'Rendered internal JavaScript with correct defer and random attributes.');
+ }
+
+ /**
+ * Tests drupal_get_js() for JavaScript settings.
+ */
+ function testHeaderSetting() {
+ $build = array();
+ $build['#attached']['library'][] = 'core/drupalSettings';
+ // Nonsensical value to verify if it's possible to override path settings.
+ $build['#attached']['drupalSettings']['path']['pathPrefix'] = 'yarhar';
+ drupal_process_attached($build);
+
+ $rendered_js = drupal_get_js('header');
+
+ // Parse the generated drupalSettings <script> back to a PHP representation.
+ $startToken = 'drupalSettings = ';
+ $endToken = '}';
+ $start = strpos($rendered_js, $startToken) + strlen($startToken);
+ $end = strrpos($rendered_js, $endToken);
+ $json = Unicode::substr($rendered_js, $start, $end - $start + 1);
+ $parsed_settings = Json::decode($json);
+
+ // Test whether the settings for core/drupalSettings are available.
+ $this->assertTrue(isset($parsed_settings['path']['baseUrl']), 'drupalSettings.path.baseUrl is present.');
+ $this->assertTrue(isset($parsed_settings['path']['scriptPath']), 'drupalSettings.path.scriptPath is present.');
+ $this->assertIdentical($parsed_settings['path']['pathPrefix'], 'yarhar', 'drupalSettings.path.pathPrefix is present and has the correct (overridden) value.');
+ $this->assertIdentical($parsed_settings['path']['currentPath'], '', 'drupalSettings.path.currentPath is present and has the correct value.');
+ $this->assertIdentical($parsed_settings['path']['currentPathIsAdmin'], FALSE, 'drupalSettings.path.currentPathIsAdmin is present and has the correct value.');
+ $this->assertIdentical($parsed_settings['path']['isFront'], FALSE, 'drupalSettings.path.isFront is present and has the correct value.');
+ $this->assertIdentical($parsed_settings['path']['currentLanguage'], 'en', 'drupalSettings.path.currentLanguage is present and has the correct value.');
+
+ // Tests whether altering JavaScript settings via hook_js_settings_alter()
+ // is working as expected.
+ // @see common_test_js_settings_alter()
+ $this->assertIdentical($parsed_settings['locale']['pluralDelimiter'], '☃');
+ $this->assertIdentical($parsed_settings['foo'], 'bar');
+ }
+
+ /**
+ * Tests JS assets assigned to the 'footer' scope.
+ */
+ function testFooterHTML() {
+ $build['#attached']['library'][] = 'common_test/js-footer';
+ drupal_process_attached($build);
+
+ $rendered_js = drupal_get_js('footer');
+ $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
+ $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/footer.js') . '?' . $query_string . '"></script>'), FALSE, 'Rendering an external JavaScript file.');
+ }
+
+ /**
+ * Tests _drupal_add_js() sets preprocess to FALSE when cache is also FALSE.
+ */
+ function testNoCache() {
+ $build['#attached']['library'][] = 'common_test/no-cache';
+ drupal_process_attached($build);
+
+ $js = _drupal_add_js();
+ $this->assertFalse($js['core/modules/system/tests/modules/common_test/nocache.js']['preprocess'], 'Setting cache to FALSE sets preprocess to FALSE when adding JavaScript.');
+ }
+
+ /**
+ * Tests adding JavaScript within conditional comments.
+ *
+ * @see \Drupal\Core\Render\Element\HtmlTag::preRenderConditionalComments()
+ */
+ function testBrowserConditionalComments() {
+ $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
+
+ $build['#attached']['library'][] = 'common_test/browsers';
+ drupal_process_attached($build);
+
+ $js = drupal_get_js();
+ $expected_1 = "<!--[if lte IE 8]>\n" . '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/old-ie.js') . '?' . $default_query_string . '"></script>' . "\n<![endif]-->";
+ $expected_2 = "<!--[if !IE]><!-->\n" . '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/no-ie.js') . '?' . $default_query_string . '"></script>' . "\n<!--<![endif]-->";
+
+ $this->assertNotIdentical(strpos($js, $expected_1), FALSE, 'Rendered JavaScript within downlevel-hidden conditional comments.');
+ $this->assertNotIdentical(strpos($js, $expected_2), FALSE, 'Rendered JavaScript within downlevel-revealed conditional comments.');
+ }
+
+ /**
+ * Tests JavaScript versioning.
+ */
+ function testVersionQueryString() {
+ $build['#attached']['library'][] = 'core/backbone';
+ $build['#attached']['library'][] = 'core/domready';
+ drupal_process_attached($build);
+
+ $js = drupal_get_js();
+ $this->assertTrue(strpos($js, 'core/assets/vendor/backbone/backbone.js?v=1.1.0') > 0 && strpos($js, 'core/assets/vendor/domready/ready.min.js?v=1.0.6') > 0 , 'JavaScript version identifiers correctly appended to URLs');
+ }
+
+ /**
+ * Tests JavaScript and CSS asset ordering.
+ */
+ function testRenderOrder() {
+ $build['#attached']['library'][] = 'common_test/order';
+ drupal_process_attached($build);
+
+ // Construct the expected result from the regex.
+ $expected_order_js = [
+ "-8_1",
+ "-8_2",
+ "-8_3",
+ "-8_4",
+ "-5_1", // The external script.
+ "-3_1",
+ "-3_2",
+ "0_1",
+ "0_2",
+ "0_3",
+ ];
+
+ // Retrieve the rendered JavaScript and test against the regex.
+ $rendered_js = drupal_get_js();
+ $matches = array();
+ if (preg_match_all('/weight_([-0-9]+_[0-9]+)/', $rendered_js, $matches)) {
+ $result = $matches[1];
+ }
+ else {
+ $result = array();
+ }
+ $this->assertIdentical($result, $expected_order_js, 'JavaScript is added in the expected weight order.');
+
+ // Construct the expected result from the regex.
+ $expected_order_css = [
+ // Base.
+ 'base_weight_-101_1',
+ 'base_weight_-8_1',
+ 'layout_weight_-101_1',
+ 'base_weight_0_1',
+ 'base_weight_0_2',
+ // Layout.
+ 'layout_weight_-8_1',
+ 'component_weight_-101_1',
+ 'layout_weight_0_1',
+ 'layout_weight_0_2',
+ // Component.
+ 'component_weight_-8_1',
+ 'state_weight_-101_1',
+ 'component_weight_0_1',
+ 'component_weight_0_2',
+ // State.
+ 'state_weight_-8_1',
+ 'theme_weight_-101_1',
+ 'state_weight_0_1',
+ 'state_weight_0_2',
+ // Theme.
+ 'theme_weight_-8_1',
+ 'theme_weight_0_1',
+ 'theme_weight_0_2',
+ ];
+
+ // Retrieve the rendered JavaScript and test against the regex.
+ $rendered_css = drupal_get_css();
+ $matches = array();
+ if (preg_match_all('/([a-z]+)_weight_([-0-9]+_[0-9]+)/', $rendered_css, $matches)) {
+ $result = $matches[0];
+ }
+ else {
+ $result = array();
+ }
+ $this->assertIdentical($result, $expected_order_css, 'CSS is added in the expected weight order.');
+ }
+
+ /**
+ * Tests rendering the JavaScript with a file's weight above jQuery's.
+ */
+ function testRenderDifferentWeight() {
+ // If a library contains assets A and B, and A is listed first, then B can
+ // still make itself appear first by defining a lower weight.
+ $build['#attached']['library'][] = 'core/jquery';
+ $build['#attached']['library'][] = 'common_test/weight';
+ drupal_process_attached($build);
+
+ $js = drupal_get_js();
+ $this->assertTrue(strpos($js, 'lighter.css') < strpos($js, 'first.js'), 'Lighter CSS assets are rendered first.');
+ $this->assertTrue(strpos($js, 'lighter.js') < strpos($js, 'first.js'), 'Lighter JavaScript assets are rendered first.');
+ $this->assertTrue(strpos($js, 'before-jquery.js') < strpos($js, 'core/assets/vendor/jquery/jquery.js'), 'Rendering a JavaScript file above jQuery.');
+ }
+
+ /**
+ * Tests altering a JavaScript's weight via hook_js_alter().
+ *
+ * @see simpletest_js_alter()
+ */
+ function testAlter() {
+ // Add both tableselect.js and simpletest.js.
+ $build['#attached']['library'][] = 'core/drupal.tableselect';
+ $build['#attached']['library'][] = 'simpletest/drupal.simpletest';
+ drupal_process_attached($build);
+
+ // Render the JavaScript, testing if simpletest.js was altered to be before
+ // tableselect.js. See simpletest_js_alter() to see where this alteration
+ // takes place.
+ $js = drupal_get_js();
+ $this->assertTrue(strpos($js, 'simpletest.js') < strpos($js, 'core/misc/tableselect.js'), 'Altering JavaScript weight through the alter hook.');
+ }
+
+ /**
+ * Adds a JavaScript library to the page and alters it.
+ *
+ * @see common_test_library_info_alter()
+ */
+ function testLibraryAlter() {
+ // Verify that common_test altered the title of Farbtastic.
+ /** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery */
+ $library_discovery = \Drupal::service('library.discovery');
+ $library = $library_discovery->getLibraryByName('core', 'jquery.farbtastic');
+ $this->assertEqual($library['version'], '0.0', 'Registered libraries were altered.');
+
+ // common_test_library_info_alter() also added a dependency on jQuery Form.
+ $build['#attached']['library'][] = 'core/jquery.farbtastic';
+ drupal_process_attached($build);
+ $scripts = drupal_get_js();
+ $this->assertTrue(strpos($scripts, 'core/assets/vendor/jquery-form/jquery.form.js'), 'Altered library dependencies are added to the page.');
+ }
+
+ /**
+ * Tests that multiple modules can implement libraries with the same name.
+ *
+ * @see common_test.library.yml
+ */
+ function testLibraryNameConflicts() {
+ /** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery */
+ $library_discovery = \Drupal::service('library.discovery');
+ $farbtastic = $library_discovery->getLibraryByName('common_test', 'jquery.farbtastic');
+ $this->assertEqual($farbtastic['version'], '0.1', 'Alternative libraries can be added to the page.');
+ }
+
+ /**
+ * Tests JavaScript files that have querystrings attached get added right.
+ */
+ function testAddJsFileWithQueryString() {
+ $build['#attached']['library'][] = 'common_test/querystring';
+ drupal_process_attached($build);
+
+ $css = _drupal_add_css();
+ $js = _drupal_add_js();
+ $this->assertTrue(array_key_exists('querystring.css?arg1=value1&arg2=value2', $css), 'CSS file with query string is correctly added.');
+ $this->assertTrue(array_key_exists('core/modules/system/tests/modules/common_test/querystring.js?arg1=value1&arg2=value2', $js), 'JavaScript file with query string is correctly added.');
+
+ $rendered_css = drupal_get_css();
+ $rendered_js = drupal_get_js();
+ $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
+ $this->assertNotIdentical(strpos($rendered_css, '<link rel="stylesheet" href="' . str_replace('&', '&amp;', file_create_url('core/modules/system/tests/modules/common_test/querystring.css?arg1=value1&arg2=value2')) . '&amp;' . $query_string . '" media="all" />'), FALSE, 'CSS file with query string gets version query string correctly appended..');
+ $this->assertNotIdentical(strpos($rendered_js, '<script src="' . str_replace('&', '&amp;', file_create_url('core/modules/system/tests/modules/common_test/querystring.js?arg1=value1&arg2=value2')) . '&amp;' . $query_string . '"></script>'), FALSE, 'JavaScript file with query string gets version query string correctly appended.');
+ }
+
+}
diff --git a/core/modules/system/src/Tests/Common/CascadingStylesheetsTest.php b/core/modules/system/src/Tests/Common/CascadingStylesheetsTest.php
deleted file mode 100644
index 658cc29..0000000
--- a/core/modules/system/src/Tests/Common/CascadingStylesheetsTest.php
+++ /dev/null
@@ -1,185 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Common\CascadingStylesheetsTest.
- */
-
-namespace Drupal\system\Tests\Common;
-
-use Drupal\Component\Utility\String;
-use Drupal\simpletest\KernelTestBase;
-
-/**
- * Tests adding various cascading stylesheets to the page.
- *
- * @group Common
- */
-class CascadingStylesheetsTest extends KernelTestBase {
-
- /**
- * Modules to enable.
- *
- * @var array
- */
- public static $modules = array('language', 'system');
-
- protected function setUp() {
- parent::setUp();
- // Reset _drupal_add_css() before each test.
- drupal_static_reset('_drupal_add_css');
- }
-
- /**
- * Checks that default stylesheets are empty.
- */
- function testDefault() {
- $this->assertEqual(array(), _drupal_add_css(), 'Default CSS is empty.');
- }
-
- /**
- * Tests adding a file stylesheet.
- */
- function testAddFile() {
- $path = drupal_get_path('module', 'simpletest') . '/css/simpletest.module.css';
- $css = _drupal_add_css($path);
- $this->assertEqual($css['simpletest.module.css']['data'], $path);
- }
-
- /**
- * Tests adding an external stylesheet.
- */
- function testAddExternal() {
- $path = 'http://example.com/style.css';
- $css = _drupal_add_css($path, 'external');
- $this->assertEqual($css[$path]['type'], 'external', 'Adding an external CSS file caches it properly.');
- }
-
- /**
- * Makes sure that resetting the CSS empties the cache.
- */
- function testReset() {
- drupal_static_reset('_drupal_add_css');
- $this->assertEqual(array(), _drupal_add_css(), 'Resetting the CSS empties the cache.');
- }
-
- /**
- * Tests rendering the stylesheets.
- */
- function testRenderFile() {
- $css = drupal_get_path('module', 'simpletest') . '/css/simpletest.module.css';
- _drupal_add_css($css);
- $styles = drupal_get_css(NULL, FALSE, FALSE);
- $this->assertTrue(strpos($styles, $css) > 0, 'Rendered CSS includes the added stylesheet.');
- // Verify that newlines are properly added inside style tags.
- $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
- $css_processed = '<link rel="stylesheet" href="' . String::checkPlain(file_create_url($css)) . "?" . $query_string . '" media="all" />';
- $this->assertEqual(trim($styles), $css_processed, 'Rendered CSS includes newlines inside style tags for JavaScript use.');
- }
-
- /**
- * Tests rendering an external stylesheet.
- */
- function testRenderExternal() {
- $css = 'http://example.com/style.css';
- _drupal_add_css($css, 'external');
- $styles = drupal_get_css();
- // Stylesheet URL may be the href of a LINK tag or in an @import statement
- // of a STYLE tag.
- $this->assertTrue(strpos($styles, 'href="' . $css) > 0 || strpos($styles, '@import url("' . $css . '")') > 0, 'Rendering an external CSS file.');
- }
-
- /**
- * Tests rendering inline stylesheets with preprocessing on.
- */
- function testRenderInlinePreprocess() {
- // Turn on CSS aggregation to allow for preprocessing.
- $config = $this->container->get('config.factory')->get('system.performance');
- $config->set('css.preprocess', 1);
-
- $css = 'body { padding: 0px; }';
- $css_preprocessed = '<style media="all">' . "\n/* <![CDATA[ */\n" . "body{padding:0px;}\n" . "\n/* ]]> */\n" . '</style>';
- _drupal_add_css($css, array('type' => 'inline'));
- $styles = drupal_get_css(NULL, NULL, FALSE);
- $this->assertEqual(trim($styles), $css_preprocessed, 'Rendering preprocessed inline CSS adds it to the page.');
- }
-
- /**
- * Tests rendering inline stylesheets with preprocessing off.
- */
- function testRenderInlineNoPreprocess() {
- $css = 'body { padding: 0px; }';
- _drupal_add_css($css, array('type' => 'inline', 'preprocess' => FALSE));
- $styles = drupal_get_css();
- $this->assertTrue(strpos($styles, $css) > 0, 'Rendering non-preprocessed inline CSS adds it to the page.');
- }
-
- /**
- * Tests CSS ordering.
- */
- function testRenderOrder() {
- // Load a module CSS file.
- _drupal_add_css(drupal_get_path('module', 'simpletest') . '/css/simpletest.module.css');
- // Load a few system CSS files in a custom, early-loading aggregate group.
- $test_aggregate_group = -100;
- $system_path = drupal_get_path('module', 'system');
- _drupal_add_css($system_path . '/css/system.module.css', array('group' => $test_aggregate_group, 'weight' => -10));
- _drupal_add_css($system_path . '/css/system.theme.css', array('group' => $test_aggregate_group));
-
- $expected = array(
- $system_path . '/css/system.module.css',
- $system_path . '/css/system.theme.css',
- drupal_get_path('module', 'simpletest') . '/css/simpletest.module.css',
- );
-
- $styles = drupal_get_css(NULL, NULL, FALSE);
- // Stylesheet URL may be the href of a LINK tag or in an @import statement
- // of a STYLE tag.
- if (preg_match_all('/(href="|url\(")' . preg_quote($GLOBALS['base_url'] . '/', '/') . '([^?]+)\?/', $styles, $matches)) {
- $result = $matches[2];
- }
- else {
- $result = array();
- }
-
- $this->assertIdentical($result, $expected, 'The CSS files are in the expected order.');
- }
-
- /**
- * Tests CSS override.
- */
- function testRenderOverride() {
- $system = drupal_get_path('module', 'system');
-
- _drupal_add_css($system . '/css/system.module.css');
- _drupal_add_css($system . '/tests/css/system.module.css');
-
- // The dummy stylesheet should be the only one included.
- $styles = drupal_get_css();
- $this->assert(strpos($styles, $system . '/tests/css/system.module.css') !== FALSE, 'The overriding CSS file is output.');
- $this->assert(strpos($styles, $system . '/css/system.module.css') === FALSE, 'The overridden CSS file is not output.');
-
- _drupal_add_css($system . '/tests/css/system.module.css');
- _drupal_add_css($system . '/css/system.module.css');
-
- // The standard stylesheet should be the only one included.
- $styles = drupal_get_css();
- $this->assert(strpos($styles, $system . '/css/system.module.css') !== FALSE, 'The overriding CSS file is output.');
- $this->assert(strpos($styles, $system . '/tests/css/system.module.css') === FALSE, 'The overridden CSS file is not output.');
- }
-
- /**
- * Tests that CSS query string remains intact when added to file.
- */
- function testAddCssFileWithQueryString() {
- $css_without_query_string = drupal_get_path('module', 'node') . '/css/node.admin.css';
- $css_with_query_string = '/' . drupal_get_path('module', 'node') . '/node-fake.css?arg1=value1&arg2=value2';
- _drupal_add_css($css_without_query_string);
- _drupal_add_css($css_with_query_string);
-
- $styles = drupal_get_css();
- $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
- $this->assertTrue(strpos($styles, $css_without_query_string . '?' . $query_string), 'Query string was appended correctly to css.');
- $this->assertTrue(strpos($styles, str_replace('&', '&amp;', $css_with_query_string)), 'Query string not escaped on a URI.');
- }
-}
diff --git a/core/modules/system/src/Tests/Common/JavaScriptTest.php b/core/modules/system/src/Tests/Common/JavaScriptTest.php
deleted file mode 100644
index 9c924fd..0000000
--- a/core/modules/system/src/Tests/Common/JavaScriptTest.php
+++ /dev/null
@@ -1,660 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Common\JavaScriptTest.
- */
-
-namespace Drupal\system\Tests\Common;
-
-use Drupal\Component\Serialization\Json;
-use Drupal\Component\Utility\Unicode;
-use Drupal\simpletest\KernelTestBase;
-use Drupal\Component\Utility\Crypt;
-
-/**
- * Tests the JavaScript system.
- *
- * @group Common
- */
-class JavaScriptTest extends KernelTestBase {
-
- /**
- * Enable Language and SimpleTest in the test environment.
- *
- * @var array
- */
- public static $modules = array('language', 'simpletest', 'common_test', 'system');
-
- /**
- * Stores configured value for JavaScript preprocessing.
- */
- protected $preprocess_js = NULL;
-
- protected function setUp() {
- parent::setUp();
-
- // Disable preprocessing
- $config = \Drupal::config('system.performance');
- $this->preprocess_js = $config->get('js.preprocess');
- $config->set('js.preprocess', 0);
- $config->save();
-
- // Reset _drupal_add_js() statics before each test.
- drupal_static_reset('_drupal_add_js');
-
- $this->installSchema('system', 'router');
- \Drupal::service('router.builder')->rebuild();
- }
-
- protected function tearDown() {
- // Restore configured value for JavaScript preprocessing.
- $config = \Drupal::config('system.performance');
- $config->set('js.preprocess', $this->preprocess_js);
- $config->save();
- parent::tearDown();
- }
-
- /**
- * Tests that default JavaScript is empty.
- */
- function testDefault() {
- $this->assertEqual(array(), _drupal_add_js(), 'Default JavaScript is empty.');
- }
-
- /**
- * Tests adding a JavaScript file.
- */
- function testAddFile() {
- $attached['#attached']['js']['core/misc/collapse.js'] = array();
- $this->render($attached);
- $javascript = _drupal_add_js();
- $this->assertTrue(array_key_exists('core/misc/collapse.js', $javascript), 'JavaScript files are correctly added.');
- }
-
- /**
- * Tests adding settings.
- */
- function testAddSetting() {
- // Add a file in order to test default settings.
- $build['#attached']['library'][] = 'core/drupalSettings';
- drupal_process_attached($build);
- $javascript = _drupal_add_js();
- $this->assertTrue(array_key_exists('currentPath', $javascript['drupalSettings']['data']['path']), 'The current path JavaScript setting is set correctly.');
-
- $javascript = _drupal_add_js(array('drupal' => 'rocks', 'dries' => 280342800), 'setting');
- $this->assertEqual(280342800, $javascript['drupalSettings']['data']['dries'], 'JavaScript setting is set correctly.');
- $this->assertEqual('rocks', $javascript['drupalSettings']['data']['drupal'], 'The other JavaScript setting is set correctly.');
- }
-
- /**
- * Tests adding an external JavaScript File.
- */
- function testAddExternal() {
- $attached['#attached']['js']['http://example.com/script.js'] = array('type' => 'external');
- $this->render($attached);
- $javascript = _drupal_add_js();
- $this->assertTrue(array_key_exists('http://example.com/script.js', $javascript), 'Added an external JavaScript file.');
- }
-
- /**
- * Tests adding JavaScript files with additional attributes.
- */
- function testAttributes() {
- $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
-
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['http://example.com/script.js'] = array(
- 'type' => 'external',
- 'attributes' => array('defer' => 'defer'),
- );
- $attached['#attached']['js']['core/misc/collapse.js'] = array(
- 'attributes' => array('defer' => 'defer'),
- );
- $this->render($attached);
- $javascript = drupal_get_js();
-
- $expected_1 = '<script src="http://example.com/script.js" defer="defer"></script>';
- $expected_2 = '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '" defer="defer"></script>';
-
- $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute.');
- $this->assertTrue(strpos($javascript, $expected_2) > 0, 'Rendered internal JavaScript with correct defer attribute.');
- }
-
- /**
- * Tests that attributes are maintained when JS aggregation is enabled.
- */
- function testAggregatedAttributes() {
- // Enable aggregation.
- \Drupal::config('system.performance')->set('js.preprocess', 1)->save();
-
- $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
-
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['http://example.com/script.js'] = array(
- 'type' => 'external',
- 'attributes' => array('defer' => 'defer'),
- );
- $attached['#attached']['js']['core/misc/collapse.js'] = array(
- 'attributes' => array('defer' => 'defer'),
- );
- $this->render($attached);
- $javascript = drupal_get_js();
-
- $expected_1 = '<script src="http://example.com/script.js" defer="defer"></script>';
- $expected_2 = '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '" defer="defer"></script>';
-
- $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute with aggregation enabled.');
- $this->assertTrue(strpos($javascript, $expected_2) > 0, 'Rendered internal JavaScript with correct defer attribute with aggregation enabled.');
- }
-
- /**
- * Tests drupal_get_js() for JavaScript settings.
- */
- function testHeaderSetting() {
- $attached = array();
- $attached['#attached']['library'][] = 'core/drupalSettings';
- // Nonsensical value to verify if it's possible to override path settings.
- $attached['#attached']['drupalSettings']['path']['pathPrefix'] = 'yarhar';
- $this->render($attached);
-
- $javascript = drupal_get_js('header');
-
- // Parse the generated drupalSettings <script> back to a PHP representation.
- $startToken = 'drupalSettings = ';
- $endToken = '}';
- $start = strpos($javascript, $startToken) + strlen($startToken);
- $end = strrpos($javascript, $endToken);
- $json = Unicode::substr($javascript, $start, $end - $start + 1);
- $parsed_settings = Json::decode($json);
-
- // Test whether the settings for core/drupalSettings are available.
- $this->assertTrue(isset($parsed_settings['path']['baseUrl']), 'drupalSettings.path.baseUrl is present.');
- $this->assertTrue(isset($parsed_settings['path']['scriptPath']), 'drupalSettings.path.scriptPath is present.');
- $this->assertIdentical($parsed_settings['path']['pathPrefix'], 'yarhar', 'drupalSettings.path.pathPrefix is present and has the correct (overridden) value.');
- $this->assertIdentical($parsed_settings['path']['currentPath'], '', 'drupalSettings.path.currentPath is present and has the correct value.');
- $this->assertIdentical($parsed_settings['path']['currentPathIsAdmin'], FALSE, 'drupalSettings.path.currentPathIsAdmin is present and has the correct value.');
- $this->assertIdentical($parsed_settings['path']['isFront'], FALSE, 'drupalSettings.path.isFront is present and has the correct value.');
- $this->assertIdentical($parsed_settings['path']['currentLanguage'], 'en', 'drupalSettings.path.currentLanguage is present and has the correct value.');
-
- // Tests whether altering JavaScript settings via hook_js_settings_alter()
- // is working as expected.
- // @see common_test_js_settings_alter()
- $this->assertIdentical($parsed_settings['locale']['pluralDelimiter'], '☃');
- $this->assertIdentical($parsed_settings['foo'], 'bar');
- }
-
- /**
- * Tests to see if resetting the JavaScript empties the cache.
- */
- function testReset() {
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['core/misc/collapse.js'] = array();
- $this->render($attached);
- drupal_static_reset('_drupal_add_js');
- $this->assertEqual(array(), _drupal_add_js(), 'Resetting the JavaScript correctly empties the cache.');
- }
-
- /**
- * Tests adding inline scripts.
- */
- function testAddInline() {
- $inline = 'jQuery(function () { });';
- $attached['#attached']['library'][] = 'core/jquery';
- $attached['#attached']['js'][] = array(
- 'type' => 'inline',
- 'data' => $inline,
- 'attributes' => array('defer' => 'defer'),
- );
- $this->render($attached);
- $javascript = _drupal_add_js();
- $this->assertTrue(array_key_exists('core/assets/vendor/jquery/jquery.js', $javascript), 'jQuery is added when inline scripts are added.');
- $data = end($javascript);
- $this->assertEqual($inline, $data['data'], 'Inline JavaScript is correctly added to the footer.');
- }
-
- /**
- * Tests rendering an external JavaScript file.
- */
- function testRenderExternal() {
- $external = 'http://example.com/example.js';
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js'][] = array(
- 'type' => 'external',
- 'data' => $external,
- );
- $this->render($attached);
-
- $javascript = drupal_get_js();
- // Local files have a base_path() prefix, external files should not.
- $this->assertTrue(strpos($javascript, 'src="' . $external) > 0, 'Rendering an external JavaScript file.');
- }
-
- /**
- * Tests drupal_get_js() with a footer scope.
- */
- function testFooterHTML() {
- $inline = 'jQuery(function () { });';
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js'][] = array(
- 'type' => 'inline',
- 'data' => $inline,
- 'scope' => 'footer',
- 'attributes' => array('defer' => 'defer'),
- );
- $this->render($attached);
-
- $javascript = drupal_get_js('footer');
- $this->assertTrue(strpos($javascript, $inline) > 0, 'Rendered JavaScript footer returns the inline code.');
- }
-
- /**
- * Tests _drupal_add_js() sets preproccess to FALSE when cache is also FALSE.
- */
- function testNoCache() {
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['core/misc/collapse.js'] = array('cache' => FALSE);
- $this->render($attached);
- $javascript = _drupal_add_js();
- $this->assertFalse($javascript['core/misc/collapse.js']['preprocess'], 'Setting cache to FALSE sets proprocess to FALSE when adding JavaScript.');
- }
-
- /**
- * Tests adding a JavaScript file with a different group.
- */
- function testDifferentGroup() {
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['core/misc/collapse.js'] = array('group' => JS_THEME);
- $this->render($attached);
- $javascript = _drupal_add_js();
- $this->assertEqual($javascript['core/misc/collapse.js']['group'], JS_THEME, 'Adding a JavaScript file with a different group caches the given group.');
- }
-
- /**
- * Tests adding a JavaScript file with a different weight.
- */
- function testDifferentWeight() {
- $attached['#attached']['js']['core/misc/collapse.js'] = array('weight' => 2);
- $this->render($attached);
- $javascript = _drupal_add_js();
- $this->assertEqual($javascript['core/misc/collapse.js']['weight'], 2, 'Adding a JavaScript file with a different weight caches the given weight.');
- }
-
- /**
- * Tests adding JavaScript within conditional comments.
- *
- * @see \Drupal\Core\Render\Element\HtmlTag::preRenderConditionalComments()
- */
- function testBrowserConditionalComments() {
- $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
-
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['core/misc/collapse.js'] = array(
- 'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE),
- );
- $attached['#attached']['js'][] = array(
- 'type' => 'inline',
- 'data' => 'jQuery(function () { });',
- 'browsers' => array('IE' => FALSE),
- );
- $this->render($attached);
- $javascript = drupal_get_js();
-
- $expected_1 = "<!--[if lte IE 8]>\n" . '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '"></script>' . "\n<![endif]-->";
- $expected_2 = "<!--[if !IE]><!-->\n" . '<script>' . "\n<!--//--><![CDATA[//><!--\n" . 'jQuery(function () { });' . "\n//--><!]]>\n" . '</script>' . "\n<!--<![endif]-->";
-
- $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered JavaScript within downlevel-hidden conditional comments.');
- $this->assertTrue(strpos($javascript, $expected_2) > 0, 'Rendered JavaScript within downlevel-revealed conditional comments.');
- }
-
- /**
- * Tests JavaScript versioning.
- */
- function testVersionQueryString() {
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['core/misc/collapse.js'] = array('version' => 'foo');
- $attached['#attached']['js']['core/misc/ajax.js'] = array('version' => 'bar');
- $this->render($attached);
- $javascript = drupal_get_js();
- $this->assertTrue(strpos($javascript, 'core/misc/collapse.js?v=foo') > 0 && strpos($javascript, 'core/misc/ajax.js?v=bar') > 0 , 'JavaScript version identifiers correctly appended to URLs');
- }
-
- /**
- * Tests JavaScript grouping and aggregation.
- */
- function testAggregation() {
- $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
-
- // To optimize aggregation, items with the 'every_page' option are ordered
- // ahead of ones without. The order of JavaScript execution must be the
- // same regardless of whether aggregation is enabled, so ensure this
- // expected order, first with aggregation off.
- $attached = array();
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['core/misc/ajax.js'] = array();
- $attached['#attached']['js']['core/misc/collapse.js'] = array('every_page' => TRUE);
- $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
- $attached['#attached']['js']['core/misc/batch.js'] = array('every_page' => TRUE);
- $this->render($attached);
- $javascript = drupal_get_js();
- $expected = implode("\n", array(
- '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '"></script>',
- '<script src="' . file_create_url('core/misc/batch.js') . '?' . $default_query_string . '"></script>',
- '<script src="' . file_create_url('core/misc/ajax.js') . '?' . $default_query_string . '"></script>',
- '<script src="' . file_create_url('core/misc/autocomplete.js') . '?' . $default_query_string . '"></script>',
- ));
- $this->assertTrue(strpos($javascript, $expected) > 0, 'Unaggregated JavaScript is added in the expected group order.');
-
- // Now ensure that with aggregation on, one file is made for the
- // 'every_page' files, and one file is made for the others.
- drupal_static_reset('_drupal_add_js');
- $config = \Drupal::config('system.performance');
- $config->set('js.preprocess', 1);
- $config->save();
- $attached = array();
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['core/misc/ajax.js'] = array();
- $attached['#attached']['js']['core/misc/collapse.js'] = array('every_page' => TRUE);
- $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
- $attached['#attached']['js']['core/misc/batch.js'] = array('every_page' => TRUE);
- $this->render($attached);
- $js_items = _drupal_add_js();
- $javascript = drupal_get_js();
- $expected = implode("\n", array(
- '<script src="' . $this->calculateAggregateFilename(array('core/misc/collapse.js' => $js_items['core/misc/collapse.js'], 'core/misc/batch.js' => $js_items['core/misc/batch.js'])) . '"></script>',
- '<script src="' . $this->calculateAggregateFilename(array('core/misc/ajax.js' => $js_items['core/misc/ajax.js'], 'core/misc/autocomplete.js' => $js_items['core/misc/autocomplete.js'])) . '"></script>',
- ));
- $this->assertTrue(strpos($javascript, $expected) !== FALSE, 'JavaScript is aggregated in the expected groups and order.');
- }
-
- /**
- * Tests JavaScript aggregation when files are added to a different scope.
- */
- function testAggregationOrder() {
- // Enable JavaScript aggregation.
- \Drupal::config('system.performance')->set('js.preprocess', 1)->save();
- drupal_static_reset('_drupal_add_js');
-
- // Add two JavaScript files to the current request and build the cache.
- $attached = array();
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['core/misc/ajax.js'] = array();
- $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
- $this->render($attached);
-
- $js_items = _drupal_add_js();
- $scripts_html = array(
- '#type' => 'scripts',
- '#items' => array(
- 'core/misc/ajax.js' => $js_items['core/misc/ajax.js'],
- 'core/misc/autocomplete.js' => $js_items['core/misc/autocomplete.js']
- )
- );
- $this->render($scripts_html);
-
- // Store the expected key for the first item in the cache.
- $cache = array_keys(\Drupal::state()->get('system.js_cache_files') ?: array());
- $expected_key = $cache[0];
-
- // Reset variables and add a file in a different scope first.
- \Drupal::state()->delete('system.js_cache_files');
- drupal_static_reset('_drupal_add_js');
- $attached = array();
- $attached['#attached']['library'][] = 'core/drupal';
- $attached['#attached']['js']['some/custom/javascript_file.js'] = array('scope' => 'footer');
- $attached['#attached']['js']['core/misc/ajax.js'] = array();
- $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
- $this->render($attached);
-
- // Rebuild the cache.
- $js_items = _drupal_add_js();
- $scripts_html = array(
- '#type' => 'scripts',
- '#items' => array(
- 'core/misc/ajax.js' => $js_items['core/misc/ajax.js'],
- 'core/misc/autocomplete.js' => $js_items['core/misc/autocomplete.js']
- )
- );
- $this->render($scripts_html);
-
- // Compare the expected key for the first file to the current one.
- $cache = array_keys(\Drupal::state()->get('system.js_cache_files') ?: array());
- $key = $cache[0];
- $this->assertEqual($key, $expected_key, 'JavaScript aggregation is not affected by ordering in different scopes.');
- }
-
- /**
- * Tests JavaScript ordering.
- */
- function testRenderOrder() {
- $shared_options = array(
- 'type' => 'inline',
- 'scope' => 'footer',
- );
- // Add a bunch of JavaScript in strange ordering.
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight 5 #1");})(jQuery);',
- 'weight' => 5,
- );
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight 0 #1");})(jQuery);',
- );
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight 0 #2");})(jQuery);',
- );
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight -8 #1");})(jQuery);',
- 'weight' => -8,
- );
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight -8 #2");})(jQuery);',
- 'weight' => -8,
- );
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight -8 #3");})(jQuery);',
- 'weight' => -8,
- );
- $attached['#attached']['js']['http://example.com/example.js?Weight -5 #1'] = array(
- 'type' => 'external',
- 'scope' => 'footer',
- 'weight' => -5,
- );
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight -8 #4");})(jQuery);',
- 'weight' => -8,
- );
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight 5 #2");})(jQuery);',
- 'weight' => 5,
- );
- $attached['#attached']['js'][] = $shared_options + array(
- 'data' => '(function($){alert("Weight 0 #3");})(jQuery);',
- );
- $this->render($attached);
-
- // Construct the expected result from the regex.
- $expected = array(
- "-8 #1",
- "-8 #2",
- "-8 #3",
- "-8 #4",
- "-5 #1", // The external script.
- "0 #1",
- "0 #2",
- "0 #3",
- "5 #1",
- "5 #2",
- );
-
- // Retrieve the rendered JavaScript and test against the regex.
- $js = drupal_get_js('footer');
- $matches = array();
- if (preg_match_all('/Weight\s([-0-9]+\s[#0-9]+)/', $js, $matches)) {
- $result = $matches[1];
- }
- else {
- $result = array();
- }
- $this->assertIdentical($result, $expected, 'JavaScript is added in the expected weight order.');
- }
-
- /**
- * Tests rendering the JavaScript with a file's weight above jQuery's.
- */
- function testRenderDifferentWeight() {
- // JavaScript files are sorted first by group, then by the 'every_page'
- // flag, then by weight (see drupal_sort_css_js()), so to test the effect of
- // weight, we need the other two options to be the same.
- $attached['#attached']['library'][] = 'core/jquery';
- $attached['#attached']['js']['core/misc/collapse.js'] = array(
- 'group' => JS_LIBRARY,
- 'every_page' => TRUE,
- 'weight' => -21,
- );
- $this->render($attached);
- $javascript = drupal_get_js();
- $this->assertTrue(strpos($javascript, 'core/misc/collapse.js') < strpos($javascript, 'core/assets/vendor/jquery/jquery.js'), 'Rendering a JavaScript file above jQuery.');
- }
-
- /**
- * Tests altering a JavaScript's weight via hook_js_alter().
- *
- * @see simpletest_js_alter()
- */
- function testAlter() {
- // Add both tableselect.js and simpletest.js, with a larger weight on SimpleTest.
- $attached['#attached']['js']['core/misc/tableselect.js'] = array();
- $attached['#attached']['js'][drupal_get_path('module', 'simpletest') . '/simpletest.js'] = array('weight' => 9999);
- $this->render($attached);
-
- // Render the JavaScript, testing if simpletest.js was altered to be before
- // tableselect.js. See simpletest_js_alter() to see where this alteration
- // takes place.
- $javascript = drupal_get_js();
- $this->assertTrue(strpos($javascript, 'simpletest.js') < strpos($javascript, 'core/misc/tableselect.js'), 'Altering JavaScript weight through the alter hook.');
- }
-
- /**
- * Adds a library to the page and tests for both its JavaScript and its CSS.
- */
- function testLibraryRender() {
- $attached = array();
- $attached['#attached']['library'][] = 'core/jquery.farbtastic';
- $this->render($attached);
- $scripts = drupal_get_js();
- $styles = drupal_get_css();
- $this->assertTrue(strpos($scripts, 'core/assets/vendor/farbtastic/farbtastic.js'), 'JavaScript of library was added to the page.');
- $this->assertTrue(strpos($styles, 'core/assets/vendor/farbtastic/farbtastic.css'), 'Stylesheet of library was added to the page.');
- }
-
- /**
- * Adds a JavaScript library to the page and alters it.
- *
- * @see common_test_library_info_alter()
- */
- function testLibraryAlter() {
- // Verify that common_test altered the title of Farbtastic.
- /** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery */
- $library_discovery = \Drupal::service('library.discovery');
- $library = $library_discovery->getLibraryByName('core', 'jquery.farbtastic');
- $this->assertEqual($library['version'], '0.0', 'Registered libraries were altered.');
-
- // common_test_library_info_alter() also added a dependency on jQuery Form.
- $attached['#attached']['library'][] = 'core/jquery.farbtastic';
- $this->render($attached);
- $scripts = drupal_get_js();
- $this->assertTrue(strpos($scripts, 'core/assets/vendor/jquery-form/jquery.form.js'), 'Altered library dependencies are added to the page.');
- }
-
- /**
- * Tests that multiple modules can implement the same library.
- *
- * @see common_test.library.yml
- */
- function testLibraryNameConflicts() {
- /** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery */
- $library_discovery = \Drupal::service('library.discovery');
- $farbtastic = $library_discovery->getLibraryByName('common_test', 'jquery.farbtastic');
- $this->assertEqual($farbtastic['version'], '0.1', 'Alternative libraries can be added to the page.');
- }
-
- /**
- * Tests non-existing libraries.
- */
- function testLibraryUnknown() {
- /** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery */
- $library_discovery = \Drupal::service('library.discovery');
- $result = $library_discovery->getLibraryByName('unknown', 'unknown');
- $this->assertFalse($result, 'Unknown library returned FALSE.');
- drupal_static_reset('drupal_get_library');
-
- $attached['#attached']['library'][] = 'unknown/unknown';
- $this->render($attached);
- $scripts = drupal_get_js();
- $this->assertTrue(strpos($scripts, 'unknown') === FALSE, 'Unknown library was not added to the page.');
- }
-
- /**
- * Tests the addition of libraries through the #attached['library'] property.
- */
- function testAttachedLibrary() {
- $element['#attached']['library'][] = 'core/jquery.farbtastic';
- $this->render($element);
- $scripts = drupal_get_js();
- $this->assertTrue(strpos($scripts, 'core/assets/vendor/farbtastic/farbtastic.js'), 'The attached_library property adds the additional libraries.');
- }
-
- /**
- * Tests retrieval of libraries via drupal_get_library().
- */
- function testGetLibrary() {
- /** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery */
- $library_discovery = \Drupal::service('library.discovery');
- // Retrieve all libraries registered by a module.
- $libraries = $library_discovery->getLibrariesByExtension('common_test');
- $this->assertTrue(isset($libraries['jquery.farbtastic']), 'Retrieved all module libraries.');
- // Retrieve all libraries for a module not declaring any libraries.
- // Note: This test installs language module.
- $libraries = $library_discovery->getLibrariesByExtension('dblog');
- $this->assertEqual($libraries, array(), 'Retrieving libraries from a module not declaring any libraries returns an emtpy array.');
-
- // Retrieve a specific library by module and name.
- $farbtastic = $library_discovery->getLibraryByName('common_test', 'jquery.farbtastic');
- $this->assertEqual($farbtastic['version'], '0.1', 'Retrieved a single library.');
- // Retrieve a non-existing library by module and name.
- $farbtastic = $library_discovery->getLibraryByName('common_test', 'foo');
- $this->assertIdentical($farbtastic, FALSE, 'Retrieving a non-existing library returns FALSE.');
- }
-
- /**
- * Tests JavaScript files that have querystrings attached get added right.
- */
- function testAddJsFileWithQueryString() {
- $js = drupal_get_path('module', 'node') . '/node.js';
- _drupal_add_js($js);
-
- $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
- $scripts = drupal_get_js();
- $this->assertTrue(strpos($scripts, $js . '?' . $query_string), 'Query string was appended correctly to JS.');
- }
-
- /**
- * Calculates the aggregated file URI of a group of JavaScript assets.
- *
- * @param array $js_assets
- * A group of JavaScript assets.
- * @return string
- * A file URI.
- *
- * @see testAggregation()
- * @see testAggregationOrder()
- */
- protected function calculateAggregateFilename($js_assets) {
- $data = '';
- foreach ($js_assets as $js_asset) {
- $data .= file_get_contents($js_asset['data']) . ";\n";
- }
- return file_create_url('public://js/js_' . Crypt::hashBase64($data) . '.js');
- }
-
-}
diff --git a/core/modules/system/src/Tests/Common/MergeAttachmentsTest.php b/core/modules/system/src/Tests/Common/MergeAttachmentsTest.php
index 20a4401..f59e395 100644
--- a/core/modules/system/src/Tests/Common/MergeAttachmentsTest.php
+++ b/core/modules/system/src/Tests/Common/MergeAttachmentsTest.php
@@ -67,100 +67,6 @@ class MergeAttachmentsTest extends KernelTestBase {
}
/**
- * Tests justs CSS asset merging.
- */
- function testCssMerging() {
- $a['#attached'] = array(
- 'css' => array(
- 'foo.css' => array(),
- 'bar.css' => array(),
- ),
- );
- $b['#attached'] = array(
- 'css' => array(
- 'baz.css' => array(),
- ),
- );
- $expected['#attached'] = array(
- 'css' => array(
- 'foo.css' => array(),
- 'bar.css' => array(),
- 'baz.css' => array(),
- ),
- );
- $this->assertIdentical($expected['#attached'], drupal_merge_attached($a['#attached'], $b['#attached']), 'Attachments merged correctly.');
-
- // Merging in the opposite direction yields the opposite CSS asset order.
- $expected['#attached'] = array(
- 'css' => array(
- 'baz.css' => array(),
- 'foo.css' => array(),
- 'bar.css' => array(),
- ),
- );
- $this->assertIdentical($expected['#attached'], drupal_merge_attached($b['#attached'], $a['#attached']), 'Attachments merged correctly; opposite merging yields opposite order.');
-
- // Merging with duplicates: duplicates are automatically removed because the
- // values have unique keys.
- $b['#attached']['css']['bar.css'] = array();
- $expected['#attached'] = array(
- 'css' => array(
- 'foo.css' => array(),
- 'bar.css' => array(),
- 'baz.css' => array(),
- ),
- );
- $this->assertIdentical($expected['#attached'], drupal_merge_attached($a['#attached'], $b['#attached']), 'Attachments merged correctly; CSS asset duplicates removed.');
- }
-
- /**
- * Tests justs JavaScript asset merging.
- */
- function testJsMerging() {
- $a['#attached'] = array(
- 'js' => array(
- 'foo.js' => array(),
- 'bar.js' => array(),
- ),
- );
- $b['#attached'] = array(
- 'js' => array(
- 'baz.js' => array(),
- ),
- );
- $expected['#attached'] = array(
- 'js' => array(
- 'foo.js' => array(),
- 'bar.js' => array(),
- 'baz.js' => array(),
- ),
- );
- $this->assertIdentical($expected['#attached'], drupal_merge_attached($a['#attached'], $b['#attached']), 'Attachments merged correctly.');
-
- // Merging in the opposite direction yields the opposite JS asset order.
- $expected['#attached'] = array(
- 'js' => array(
- 'baz.js' => array(),
- 'foo.js' => array(),
- 'bar.js' => array(),
- ),
- );
- $this->assertIdentical($expected['#attached'], drupal_merge_attached($b['#attached'], $a['#attached']), 'Attachments merged correctly; opposite merging yields opposite order.');
-
- // Merging with duplicates: duplicates are automatically removed because the
- // values have unique keys.
- $b['#attached']['js']['bar.js'] = array();
- $expected['#attached'] = array(
- 'js' => array(
- 'foo.js' => array(),
- 'bar.js' => array(),
- 'baz.js' => array(),
- ),
- );
- $this->assertIdentical($expected['#attached'], drupal_merge_attached($a['#attached'], $b['#attached']), 'Attachments merged correctly; JS asset duplicates removed.');
- }
-
- /**
* Tests justs JavaScript and JavaScript setting asset merging.
*/
function testJsSettingMerging() {
diff --git a/core/modules/system/src/Tests/Common/RenderTest.php b/core/modules/system/src/Tests/Common/RenderTest.php
index a1d7523..6848dc9 100644
--- a/core/modules/system/src/Tests/Common/RenderTest.php
+++ b/core/modules/system/src/Tests/Common/RenderTest.php
@@ -354,40 +354,35 @@ class RenderTest extends KernelTestBase {
\Drupal::request()->setMethod('GET');
// Create an element with a child and subchild. Each element loads a
- // different JavaScript file using #attached.
- $parent_js = drupal_get_path('module', 'user') . '/user.js';
- $child_js = drupal_get_path('module', 'forum') . '/forum.js';
- $subchild_js = drupal_get_path('module', 'book') . '/book.js';
+ // different library using #attached.
$element = array(
- '#type' => 'details',
- '#open' => TRUE,
+ '#type' => 'container',
'#cache' => array(
'keys' => array('simpletest', 'drupal_render', 'children_attached'),
),
- '#attached' => array('js' => array($parent_js)),
+ '#attached' => ['library' => ['test/parent']],
'#title' => 'Parent',
);
$element['child'] = array(
- '#type' => 'details',
- '#open' => TRUE,
- '#attached' => array('js' => array($child_js)),
+ '#type' => 'container',
+ '#attached' => ['library' => ['test/child']],
'#title' => 'Child',
);
$element['child']['subchild'] = array(
- '#attached' => array('js' => array($subchild_js)),
+ '#attached' => ['library' => ['test/subchild']],
'#markup' => 'Subchild',
);
// Render the element and verify the presence of #attached JavaScript.
drupal_render($element);
- $expected_js = [$parent_js, $child_js, $subchild_js];
- $this->assertEqual($element['#attached']['js'], $expected_js, 'The element, child and subchild #attached JavaScript are included.');
+ $expected_libraries = ['test/parent', 'test/child', 'test/subchild'];
+ $this->assertEqual($element['#attached']['library'], $expected_libraries, 'The element, child and subchild #attached libraries are included.');
// Load the element from cache and verify the presence of the #attached
// JavaScript.
$element = array('#cache' => array('keys' => array('simpletest', 'drupal_render', 'children_attached')));
$this->assertTrue(strlen(drupal_render($element)) > 0, 'The element was retrieved from cache.');
- $this->assertEqual($element['#attached']['js'], $expected_js, 'The element, child and subchild #attached JavaScript are included.');
+ $this->assertEqual($element['#attached']['library'], $expected_libraries, 'The element, child and subchild #attached libraries are included.');
// Restore the previous request method.
\Drupal::request()->setMethod($request_method);
diff --git a/core/modules/system/tests/modules/ajax_test/ajax_test.libraries.yml b/core/modules/system/tests/modules/ajax_test/ajax_test.libraries.yml
new file mode 100644
index 0000000..5f94748
--- /dev/null
+++ b/core/modules/system/tests/modules/ajax_test/ajax_test.libraries.yml
@@ -0,0 +1,20 @@
+order:
+ drupalSettings:
+ ajax: test
+ dependencies:
+ - ajax_test/order-css-command
+ - ajax_test/order-js-command
+
+order-css-command:
+ css:
+ theme:
+ # Two CSS files (order should remain the same).
+ a.css: {}
+ b.css: {}
+
+order-js-command:
+ js:
+ # Two JavaScript files (first to the footer, should appear last).
+ footer.js: { scope: footer }
+ header.js: {}
+
diff --git a/core/modules/system/tests/modules/ajax_test/ajax_test.module b/core/modules/system/tests/modules/ajax_test/ajax_test.module
index 1f19aac..d81da66 100644
--- a/core/modules/system/tests/modules/ajax_test/ajax_test.module
+++ b/core/modules/system/tests/modules/ajax_test/ajax_test.module
@@ -47,29 +47,10 @@ function ajax_test_render() {
*/
function ajax_test_order() {
$response = new AjaxResponse();
- $path = drupal_get_path('module', 'system');
// HTML insertion command.
$response->addCommand(new HtmlCommand('body', 'Hello, world!'));
- $attached = array(
- '#attached' => array(
- 'css' => array(
- // Add two CSS files (order should remain the same).
- $path . '/css/system.admin.css' => array(),
- $path . '/css/system.maintenance.css' => array(),
- ),
- 'js' => array(
- // Add two JavaScript files (first to the footer, should appear last).
- $path . '/system.modules.js' => array('scope' => 'footer'),
- $path . '/system.js' => array(),
- ),
- // Finally, add a JavaScript setting.
- 'drupalSettings' => array(
- 'ajax' => 'test',
- ),
- ),
- );
-
- drupal_process_attached($attached);
+ $build['#attached']['library'][] = 'ajax_test/order';
+ drupal_process_attached($build);
return $response;
}
diff --git a/core/modules/system/tests/modules/common_test/common_test.libraries.yml b/core/modules/system/tests/modules/common_test/common_test.libraries.yml
index 47d2b37..69b9c11 100644
--- a/core/modules/system/tests/modules/common_test/common_test.libraries.yml
+++ b/core/modules/system/tests/modules/common_test/common_test.libraries.yml
@@ -7,3 +7,106 @@ jquery.farbtastic:
assets/vendor/farbtastic/farbtastic.css: {}
dependencies:
- core/jquery
+
+# Library to test CSS and JS file assets.
+files:
+ js:
+ foo.js: {}
+ css:
+ theme:
+ bar.css: {}
+
+# Library to test external CSS and JS file assets.
+external:
+ version: 1
+ js:
+ http://example.com/script.js: { type: external }
+ css:
+ theme:
+ http://example.com/stylesheet.css: { type: external }
+
+# Library to test JS file asset attributes (both internal and external).
+js-attributes:
+ version: 1
+ js:
+ deferred-internal.js: { attributes: { defer: true, bar: foo } }
+ http://example.com/deferred-external.js:
+ type: external
+ attributes:
+ foo: bar
+ defer: true
+
+js-footer:
+ js:
+ footer.js: { scope: footer }
+
+# Library to test setting cache = FALSE, to prevent aggregation.
+no-cache:
+ js:
+ nocache.js: { cache: false }
+
+order:
+ js:
+ weight_-3_1.js: { weight: -3 }
+ weight_0_1.js: {}
+ weight_0_2.js: {}
+ weight_-8_1.js: { weight: -8 }
+ weight_-8_2.js: { weight: -8 }
+ weight_-8_3.js: { weight: -8 }
+ http://example.com/weight_-5_1.js: { type: external, weight: -5 }
+ weight_-8_4.js: { weight: -8 }
+ weight_-3_2.js: { weight: -3 }
+ weight_0_3.js: {}
+ css:
+ base:
+ base_weight_0_1.js: {}
+ base_weight_0_2.js: {}
+ base_weight_-8_1.js: { weight: -8 }
+ base_weight_-101_1.js: { weight: -101 }
+ layout:
+ layout_weight_0_1.js: {}
+ layout_weight_0_2.js: {}
+ layout_weight_-8_1.js: { weight: -8 }
+ layout_weight_-101_1.js: { weight: -101 }
+ component:
+ component_weight_0_1.js: {}
+ component_weight_0_2.js: {}
+ component_weight_-8_1.js: { weight: -8}
+ component_weight_-101_1.js: { weight: -101}
+ state:
+ state_weight_0_1.js: {}
+ state_weight_0_2.js: {}
+ state_weight_-8_1.js: { weight: -8}
+ state_weight_-101_1.js: { weight: -101}
+ theme:
+ theme_weight_0_1.js: {}
+ theme_weight_0_2.js: {}
+ theme_weight_-8_1.js: { weight: -8}
+ theme_weight_-101_1.js: { weight: -101}
+
+weight:
+ css:
+ theme:
+ first.css: {}
+ lighter.js: { weight: -1 }
+ js:
+ first.js: {}
+ lighter.js: { weight: -1 }
+ before-jquery.js: { weight: -21 }
+
+browsers:
+ js:
+ old-ie.js:
+ browsers:
+ 'IE': 'lte IE 8'
+ '!IE': false
+ no-ie.js:
+ browsers:
+ IE: false
+
+querystring:
+ js:
+ querystring.js?arg1=value1&arg2=value2: {}
+ css:
+ theme:
+ querystring.css?arg1=value1&arg2=value2: {}
diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php
index a335e38..408c753 100644
--- a/core/modules/system/theme.api.php
+++ b/core/modules/system/theme.api.php
@@ -258,7 +258,7 @@
* normally preferable to use #theme or #type instead, so that the theme can
* customize the markup.
*
- * JavaScript and CSS attributes are specified in the render array using the
+ * JavaScript and CSS assets are specified in the render array using the
* #attached property (see @ref sec_attached).
*
* @section elements Render elements
@@ -286,18 +286,22 @@
*
* @section sec_attached Attaching libraries in render arrays
*
- * The #attached property allows loading of CSS, JavaScript, libraries or custom
- * types. Specify an array of type => value pairs, where the type (most often
- * 'css', 'js', or 'library') determines the loading technique and the value
- * provides the options specified to the loader function. Example:
- * @code
- * $form['#attached']['css'] = array(
- * drupal_get_path('module', 'ajax_example') . '/ajax_example.css',
- * );
*
- * $form['#attached']['js'] = array(
- * drupal_get_path('module', 'ajax_example') . '/ajax_example.js',
- * );
+ * Libraries, JavaScript settings, feeds, HTML <head> tags and HTML <head> links
+ * are attached to elements using the #attached property. The #attached property
+ * is an associative array, where the keys are the attachment types and the
+ * values are the attached data. For example:
+ *
+ * The #attached property allows loading of asset libraries (which may contain
+ * CSS assets, JavaScript assets, and JavaScript setting assets), JavaScript
+ * settings, feeds, HTML <head> tags and HTML <head> links. Specify an array of
+ * type => value pairs, where the type (most often 'library' — for libraries, or
+ * 'drupalSettings' — for JavaScript settings) to attach these response-level
+ * values. Example:
+ * @code
+ * $build['#attached']['library'][] = 'core/jquery';
+ * $build['#attached']['drupalSettings']['foo] = 'bar';
+ * $build['#attached']['feed'][] = ['aggregator/rss', $this->t('Feed title')];
* @endcode
*
* See drupal_process_attached() for additional information.
diff --git a/core/modules/views/src/Tests/Plugin/CacheTest.php b/core/modules/views/src/Tests/Plugin/CacheTest.php
index 6f669d2..7f9e460 100644
--- a/core/modules/views/src/Tests/Plugin/CacheTest.php
+++ b/core/modules/views/src/Tests/Plugin/CacheTest.php
@@ -148,10 +148,7 @@ class CacheTest extends PluginTestBase {
$output = $view->preview();
drupal_render($output);
$this->assertTrue(in_array('views_test_data/test', $output['#attached']['library']), 'Make sure libraries are added for cached views.');
- $css_path = drupal_get_path('module', 'views_test_data') . '/views_cache.test.css';
- $js_path = drupal_get_path('module', 'views_test_data') . '/views_cache.test.js';
- $this->assertTrue(in_array($css_path, $output['#attached']['css']), 'Make sure the css is added for cached views.');
- $this->assertTrue(in_array($js_path, $output['#attached']['js']), 'Make sure the js is added for cached views.');
+ $this->assertEqual(['foo' => 'bar'], $output['#attached']['drupalSettings'], 'Make sure drupalSettings are added for cached views.');
$this->assertTrue(['views_test_data:1'], $output['#cache']['tags']);
$this->assertTrue(['views_test_data_post_render_cache' => [['foo' => 'bar']]], $output['#post_render_cache']);
$this->assertFalse(!empty($view->build_info['pre_render_called']), 'Make sure hook_views_pre_render is not called for the cached view.');
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index 9214808..8c61f35 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -388,20 +388,20 @@ class ViewExecutable {
/**
* A render array container to store render related information.
*
- * For example you can alter the array and attach some css/js via the
- * #attached key. This is the required way to add custom css/js.
+ * For example you can alter the array and attach some asset library or JS
+ * settings via the #attached key. This is the required way to add custom
+ * CSS or JS.
*
* @var array
*
* @see drupal_process_attached
*/
- public $element = array(
- '#attached' => array(
- 'css' => array(),
- 'js' => array(),
- 'library' => array(),
- ),
- );
+ public $element = [
+ '#attached' => [
+ 'library' => [],
+ 'drupalSettings' => [],
+ ]
+ ];
/**
* The current user.
diff --git a/core/modules/views/tests/modules/views_test_data/views_test_data.views_execution.inc b/core/modules/views/tests/modules/views_test_data/views_test_data.views_execution.inc
index 8f0df18..d3ceb3b 100644
--- a/core/modules/views/tests/modules/views_test_data/views_test_data.views_execution.inc
+++ b/core/modules/views/tests/modules/views_test_data/views_test_data.views_execution.inc
@@ -47,11 +47,8 @@ function views_test_data_views_pre_render(ViewExecutable $view) {
\Drupal::state()->set('views_hook_test_views_pre_render', TRUE);
if (isset($view) && ($view->storage->id() == 'test_cache_header_storage')) {
- $path = drupal_get_path('module', 'views_test_data');
$view->element['#attached']['library'][] = 'views_test_data/test';
$view->element['#attached']['drupalSettings']['foo'] = 'bar';
- $view->element['#attached']['js'][] = "$path/views_cache.test.js";
- $view->element['#attached']['css'][] = "$path/views_cache.test.css";
$view->element['#cache']['tags'][] = 'views_test_data:1';
$view->element['#post_render_cache']['views_test_data_post_render_cache'][] = ['foo' => 'bar'];
$view->build_info['pre_render_called'] = TRUE;
diff --git a/core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php
index 8ca43ae..688ba54 100644
--- a/core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/CssCollectionGrouperUnitTest.php
@@ -69,26 +69,6 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
'basename' => 'jquery.ui.core.css',
),
- 0 => array(
- 'type' => 'inline',
- 'group' => 0,
- 'weight' => 0.007,
- 'every_page' => FALSE,
- 'media' => 'all',
- 'preprocess' => TRUE,
- 'data' => 'body { padding: 0px; }',
- 'browsers' => array('IE' => TRUE, '!IE' => TRUE),
- ),
- 1 => array(
- 'type' => 'inline',
- 'group' => 0,
- 'weight' => 0.007,
- 'every_page' => FALSE,
- 'media' => 'all',
- 'preprocess' => FALSE,
- 'data' => 'body { margin: 0px; }',
- 'browsers' => array('IE' => TRUE, '!IE' => TRUE),
- ),
'field.css' => array(
'every_page' => TRUE,
'group' => 0,
@@ -137,7 +117,7 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
$groups = $this->grouper->group($css_assets);
- $this->assertSame(count($groups), 7, "7 groups created.");
+ $this->assertSame(count($groups), 6, "6 groups created.");
// Check group 1.
$this->assertSame($groups[0]['group'], -100);
@@ -160,49 +140,39 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
// Check group 3.
$this->assertSame($groups[2]['group'], 0);
- $this->assertSame($groups[2]['every_page'], FALSE);
- $this->assertSame($groups[2]['type'], 'inline');
+ $this->assertSame($groups[2]['every_page'], TRUE);
+ $this->assertSame($groups[2]['type'], 'file');
$this->assertSame($groups[2]['media'], 'all');
$this->assertSame($groups[2]['preprocess'], TRUE);
- $this->assertSame(count($groups[2]['items']), 2);
- $this->assertContains($css_assets[0], $groups[2]['items']);
- $this->assertContains($css_assets[1], $groups[2]['items']);
+ $this->assertSame(count($groups[2]['items']), 1);
+ $this->assertContains($css_assets['field.css'], $groups[2]['items']);
// Check group 4.
$this->assertSame($groups[3]['group'], 0);
- $this->assertSame($groups[3]['every_page'], TRUE);
- $this->assertSame($groups[3]['type'], 'file');
+ $this->assertSame($groups[3]['every_page'], FALSE);
+ $this->assertSame($groups[3]['type'], 'external');
$this->assertSame($groups[3]['media'], 'all');
$this->assertSame($groups[3]['preprocess'], TRUE);
$this->assertSame(count($groups[3]['items']), 1);
- $this->assertContains($css_assets['field.css'], $groups[3]['items']);
+ $this->assertContains($css_assets['external.css'], $groups[3]['items']);
// Check group 5.
- $this->assertSame($groups[4]['group'], 0);
- $this->assertSame($groups[4]['every_page'], FALSE);
- $this->assertSame($groups[4]['type'], 'external');
+ $this->assertSame($groups[4]['group'], 100);
+ $this->assertSame($groups[4]['every_page'], TRUE);
+ $this->assertSame($groups[4]['type'], 'file');
$this->assertSame($groups[4]['media'], 'all');
$this->assertSame($groups[4]['preprocess'], TRUE);
$this->assertSame(count($groups[4]['items']), 1);
- $this->assertContains($css_assets['external.css'], $groups[4]['items']);
+ $this->assertContains($css_assets['style.css'], $groups[4]['items']);
// Check group 6.
$this->assertSame($groups[5]['group'], 100);
$this->assertSame($groups[5]['every_page'], TRUE);
$this->assertSame($groups[5]['type'], 'file');
- $this->assertSame($groups[5]['media'], 'all');
+ $this->assertSame($groups[5]['media'], 'print');
$this->assertSame($groups[5]['preprocess'], TRUE);
$this->assertSame(count($groups[5]['items']), 1);
- $this->assertContains($css_assets['style.css'], $groups[5]['items']);
-
- // Check group 7.
- $this->assertSame($groups[6]['group'], 100);
- $this->assertSame($groups[6]['every_page'], TRUE);
- $this->assertSame($groups[6]['type'], 'file');
- $this->assertSame($groups[6]['media'], 'print');
- $this->assertSame($groups[6]['preprocess'], TRUE);
- $this->assertSame(count($groups[6]['items']), 1);
- $this->assertContains($css_assets['print.css'], $groups[6]['items']);
+ $this->assertContains($css_assets['print.css'], $groups[5]['items']);
}
}
diff --git a/core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php
index 5028f45..64a3833 100644
--- a/core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php
@@ -57,13 +57,6 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
protected $file_css_group;
/**
- * A valid inline CSS asset group.
- *
- * @var array
- */
- protected $inline_css_group;
-
- /**
* The state mock class.
*
* @var \Drupal\Core\State\StateInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -108,36 +101,6 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
),
),
);
- $this->inline_css_group = array(
- 'group' => 0,
- 'every_page' => FALSE,
- 'type' => 'inline',
- 'media' => 'all',
- 'preprocess' => TRUE,
- 'browsers' => array('IE' => TRUE, '!IE' => TRUE),
- 'items' => array(
- 0 => array(
- 'group' => 0,
- 'every_page' => FALSE,
- 'type' => 'inline',
- 'weight' => 0.012,
- 'media' => 'all',
- 'preprocess' => TRUE,
- 'data' => '.girlfriend { display: none; }',
- 'browsers' => array('IE' => TRUE, '!IE' => TRUE),
- ),
- 1 => array(
- 'group' => 0,
- 'every_page' => FALSE,
- 'type' => 'file',
- 'weight' => 0.013,
- 'media' => 'all',
- 'preprocess' => FALSE,
- 'data' => '#home body { position: fixed; }',
- 'browsers' => array('IE' => TRUE, '!IE' => TRUE),
- ),
- ),
- );
}
/**
@@ -191,15 +154,6 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
0 => $create_link_element('http://example.com/popular.js', 'all'),
),
),
- // Single inline CSS asset.
- 1 => array(
- array(
- 0 => array('group' => 0, 'every_page' => FALSE, 'type' => 'inline', 'media' => 'all', 'preprocess' => FALSE, 'data' => '.girlfriend { display: none; }', 'browsers' => array()),
- ),
- array(
- 0 => $create_style_element('.girlfriend { display: none; }', 'all', array(), TRUE),
- ),
- ),
// Single file CSS asset.
2 => array(
array(
diff --git a/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php
index df90beb..54cdebc 100644
--- a/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php
@@ -136,38 +136,41 @@ class CssOptimizerUnitTest extends UnitTestCase {
),
file_get_contents($path . 'comment_hacks.css.optimized.css'),
),
- // Inline. Preprocessing enabled.
- 3 => array(
+ // File in subfolder. Tests:
+ // - CSS import path is properly interpreted. (https://drupal.org/node/1198904)
+ // - Don't adjust data URIs (https://drupal.org/node/2142441)
+ 5 => array(
array(
- 'group' => 0,
- 'every_page' => FALSE,
- 'type' => 'inline',
- 'weight' => 0.012,
+ 'group' => -100,
+ 'every_page' => TRUE,
+ 'type' => 'file',
+ 'weight' => 0.013,
'media' => 'all',
'preprocess' => TRUE,
- 'data' => '.girlfriend { display: none; }',
+ 'data' => $path . 'css_subfolder/css_input_with_import.css',
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
+ 'basename' => 'css_input_with_import.css',
),
- ".girlfriend{display:none;}\n",
+ str_replace('url(../images/icon.png)', 'url(' . file_create_url($path . 'images/icon.png') . ')', file_get_contents($path . 'css_subfolder/css_input_with_import.css.optimized.css')),
),
- // Inline. Preprocessing disabled.
- 4 => array(
+ // File. Tests:
+ // - Any @charaset declaration at the beginning of a file should be
+ // removed without breaking subsequent CSS.
+ 6 => array(
array(
- 'group' => 0,
- 'every_page' => FALSE,
- 'type' => 'inline',
+ 'group' => -100,
+ 'every_page' => TRUE,
+ 'type' => 'file',
'weight' => 0.013,
'media' => 'all',
- 'preprocess' => FALSE,
- 'data' => '#home body { position: fixed; }',
+ 'preprocess' => TRUE,
+ 'data' => $path . 'charset_sameline.css',
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
+ 'basename' => 'charset_sameline.css',
),
- '#home body { position: fixed; }',
+ file_get_contents($path . 'charset.css.optimized.css'),
),
- // File in subfolder. Tests:
- // - CSS import path is properly interpreted. (https://drupal.org/node/1198904)
- // - Don't adjust data URIs (https://drupal.org/node/2142441)
- 5 => array(
+ 7 => array(
array(
'group' => -100,
'every_page' => TRUE,
@@ -175,11 +178,11 @@ class CssOptimizerUnitTest extends UnitTestCase {
'weight' => 0.013,
'media' => 'all',
'preprocess' => TRUE,
- 'data' => $path . 'css_subfolder/css_input_with_import.css',
+ 'data' => $path . 'charset_newline.css',
'browsers' => array('IE' => TRUE, '!IE' => TRUE),
- 'basename' => 'css_input_with_import.css',
+ 'basename' => 'charset_newline.css',
),
- str_replace('url(../images/icon.png)', 'url(' . file_create_url($path . 'images/icon.png') . ')', file_get_contents($path . 'css_subfolder/css_input_with_import.css.optimized.css')),
+ file_get_contents($path . 'charset.css.optimized.css'),
),
);
}
@@ -194,38 +197,6 @@ class CssOptimizerUnitTest extends UnitTestCase {
}
/**
- * Tests optimizing a CSS asset containing charset declaration.
- */
- function testOptimizeRemoveCharset() {
- $cases = array(
- array(
- 'asset' => array(
- 'type' => 'inline',
- 'data' => '@charset "UTF-8";html{font-family:"sans-serif";}',
- 'preprocess' => FALSE,
- ),
- 'expected' => 'html{font-family:"sans-serif";}',
- ),
- array(
- // This asset contains extra \n character.
- 'asset' => array(
- 'type' => 'inline',
- 'data' => "@charset 'UTF-8';\nhtml{font-family:'sans-serif';}",
- 'preprocess' => FALSE,
- ),
- 'expected' => "\nhtml{font-family:'sans-serif';}",
- ),
- );
- foreach ($cases as $case) {
- $this->assertEquals(
- $case['expected'],
- $this->optimizer->optimize($case['asset']),
- 'CSS optimizing correctly removes the charset declaration.'
- );
- }
- }
-
- /**
* Tests a file CSS asset with preprocessing disabled.
*/
function testTypeFilePreprocessingDisabled() {
diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
index 141d432..18e8bbc 100644
--- a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
@@ -179,6 +179,36 @@ class LibraryDiscoveryParserTest extends UnitTestCase {
}
/**
+ * Tests the version property, and how it propagates to the contained assets.
+ *
+ * @covers ::buildByExtension
+ */
+ public function testVersion() {
+ $this->moduleHandler->expects($this->atLeastOnce())
+ ->method('moduleExists')
+ ->with('versions')
+ ->will($this->returnValue(TRUE));
+
+ $path = __DIR__ . '/library_test_files';
+ $path = substr($path, strlen($this->root) + 1);
+ $this->libraryDiscoveryParser->setPaths('module', 'versions', $path);
+
+ $libraries = $this->libraryDiscoveryParser->buildByExtension('versions');
+
+ $this->assertFalse(array_key_exists('version', $libraries['versionless']));
+ $this->assertEquals(-1, $libraries['versionless']['css'][0]['version']);
+ $this->assertEquals(-1, $libraries['versionless']['js'][0]['version']);
+
+ $this->assertEquals('9.8.7.6', $libraries['versioned']['version']);
+ $this->assertEquals('9.8.7.6', $libraries['versioned']['css'][0]['version']);
+ $this->assertEquals('9.8.7.6', $libraries['versioned']['js'][0]['version']);
+
+ $this->assertEquals(\Drupal::VERSION, $libraries['core-versioned']['version']);
+ $this->assertEquals(\Drupal::VERSION, $libraries['core-versioned']['css'][0]['version']);
+ $this->assertEquals(\Drupal::VERSION, $libraries['core-versioned']['js'][0]['version']);
+ }
+
+ /**
* Tests that the version property of external libraries is handled.
*
* @covers ::buildByExtension
@@ -193,10 +223,11 @@ class LibraryDiscoveryParserTest extends UnitTestCase {
$path = substr($path, strlen($this->root) + 1);
$this->libraryDiscoveryParser->setPaths('module', 'external', $path);
- $libraries = $this->libraryDiscoveryParser->buildByExtension('external', 'example_external');
+ $libraries = $this->libraryDiscoveryParser->buildByExtension('external');
$library = $libraries['example_external'];
- $this->assertEquals($path . '/css/example_external.css', $library['css'][0]['data']);
+ $this->assertEquals('http://example.com/css/example_external.css', $library['css'][0]['data']);
+ $this->assertEquals('http://example.com/example_external.js', $library['js'][0]['data']);
$this->assertEquals('3.14', $library['version']);
}
diff --git a/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset.css b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset.css
new file mode 100644
index 0000000..ba7696d
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset.css
@@ -0,0 +1 @@
+@charset "UTF-8";html{font-family:"sans-serif";}
diff --git a/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset.css.optimized.css b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset.css.optimized.css
new file mode 100644
index 0000000..c9e6ade
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset.css.optimized.css
@@ -0,0 +1 @@
+html{font-family:"sans-serif";}
diff --git a/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_newline.css b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_newline.css
new file mode 100644
index 0000000..68f3f42
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_newline.css
@@ -0,0 +1,2 @@
+@charset 'UTF-8';
+html{font-family:"sans-serif";}
diff --git a/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_sameline.css b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_sameline.css
new file mode 100644
index 0000000..ba7696d
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_sameline.css
@@ -0,0 +1 @@
+@charset "UTF-8";html{font-family:"sans-serif";}
diff --git a/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_sameline.css.optimized.css b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_sameline.css.optimized.css
new file mode 100644
index 0000000..c9e6ade
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Asset/css_test_files/charset_sameline.css.optimized.css
@@ -0,0 +1 @@
+html{font-family:"sans-serif";}
diff --git a/core/tests/Drupal/Tests/Core/Asset/library_test_files/external.libraries.yml b/core/tests/Drupal/Tests/Core/Asset/library_test_files/external.libraries.yml
index 0486a72..c4be4c9 100644
--- a/core/tests/Drupal/Tests/Core/Asset/library_test_files/external.libraries.yml
+++ b/core/tests/Drupal/Tests/Core/Asset/library_test_files/external.libraries.yml
@@ -1,5 +1,7 @@
example_external:
version: v3.14
+ js:
+ http://example.com/example_external.js: { type: external }
css:
theme:
- css/example_external.css: {}
+ http://example.com/css/example_external.css: { type: external }
diff --git a/core/tests/Drupal/Tests/Core/Asset/library_test_files/versions.libraries.yml b/core/tests/Drupal/Tests/Core/Asset/library_test_files/versions.libraries.yml
new file mode 100644
index 0000000..cc3d106
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Asset/library_test_files/versions.libraries.yml
@@ -0,0 +1,22 @@
+versionless:
+ css:
+ theme:
+ versionless.css: {}
+ js:
+ versionless.js: {}
+
+versioned:
+ version: 9.8.7.6
+ css:
+ theme:
+ versioned.css: {}
+ js:
+ versioned.js: {}
+
+core-versioned:
+ version: VERSION
+ css:
+ theme:
+ core-versioned.css: {}
+ js:
+ core-versioned.js: {}