Skip to content
Snippets Groups Projects
Verified Commit d44fb628 authored by Théodore Biadala's avatar Théodore Biadala
Browse files

Issue #3463875 by spokje, jrb, godotislate, smustgrave: Ensure uniqueBundleId is unique in LoadJS

parent 2ad947f2
No related branches found
No related tags found
No related merge requests found
......@@ -1720,16 +1720,18 @@
*/
add_css(ajax, response, status) {
const allUniqueBundleIds = response.data.map(function (style) {
const uniqueBundleId = style.href + ajax.instanceIndex;
const uniqueBundleId = style.href;
// Force file to load as a CSS stylesheet using 'css!' flag.
loadjs(`css!${style.href}`, uniqueBundleId, {
before(path, styleEl) {
// This allows all attributes to be added, like media.
Object.keys(style).forEach((attributeKey) => {
styleEl.setAttribute(attributeKey, style[attributeKey]);
});
},
});
if (!loadjs.isDefined(uniqueBundleId)) {
loadjs(`css!${style.href}`, uniqueBundleId, {
before(path, styleEl) {
// This allows all attributes to be added, like media.
Object.keys(style).forEach((attributeKey) => {
styleEl.setAttribute(attributeKey, style[attributeKey]);
});
},
});
}
return uniqueBundleId;
});
// Returns the promise so that the next AJAX command waits on the
......@@ -1795,32 +1797,31 @@
const parentEl = document.querySelector(response.selector || 'body');
const settings = ajax.settings || drupalSettings;
const allUniqueBundleIds = response.data.map((script) => {
// loadjs requires a unique ID, and an AJAX instance's `instanceIndex`
// is guaranteed to be unique.
// @see Drupal.behaviors.AJAX.detach
const uniqueBundleId = script.src + ajax.instanceIndex;
loadjs(script.src, uniqueBundleId, {
// The default loadjs behavior is to load script with async, in Drupal
// we need to explicitly tell scripts to load async, this is set in
// the before callback below if necessary.
async: false,
before(path, scriptEl) {
// This allows all attributes to be added, like defer, async and
// crossorigin.
Object.keys(script).forEach((attributeKey) => {
scriptEl.setAttribute(attributeKey, script[attributeKey]);
});
// By default, loadjs appends the script to the head. When scripts
// are loaded via AJAX, their location has no impact on
// functionality. But, since non-AJAX loaded scripts can choose
// their parent element, we provide that option here for the sake of
// consistency.
parentEl.appendChild(scriptEl);
// Return false to bypass loadjs' default DOM insertion mechanism.
return false;
},
});
const uniqueBundleId = script.src;
if (!loadjs.isDefined(uniqueBundleId)) {
loadjs(script.src, uniqueBundleId, {
// The default loadjs behavior is to load script with async, in Drupal
// we need to explicitly tell scripts to load async, this is set in
// the before callback below if necessary.
async: false,
before(path, scriptEl) {
// This allows all attributes to be added, like defer, async and
// crossorigin.
Object.keys(script).forEach((attributeKey) => {
scriptEl.setAttribute(attributeKey, script[attributeKey]);
});
// By default, loadjs appends the script to the head. When scripts
// are loaded via AJAX, their location has no impact on
// functionality. But, since non-AJAX loaded scripts can choose
// their parent element, we provide that option here for the sake of
// consistency.
parentEl.appendChild(scriptEl);
// Return false to bypass loadjs' default DOM insertion mechanism.
return false;
},
});
}
return uniqueBundleId;
});
// Returns the promise so that the next AJAX command waits on the
......
<?php
declare(strict_types=1);
namespace Drupal\Tests\config\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Tests the user interface for importing configuration.
*
* @group config
*/
class ConfigImportUIAjaxTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'config',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* Tests an updated configuration object can be viewed more than once.
*/
public function testImport(): void {
$name = 'system.site';
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$user = $this->drupalCreateUser(['synchronize configuration']);
$this->drupalLogin($user);
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
// Create updated configuration object.
$new_site_name = 'Config import test ' . $this->randomString();
$sync = $this->container->get('config.storage.sync');
// Create updated configuration object.
$config_data = $this->config('system.site')->get();
$config_data['name'] = $new_site_name;
$sync->write('system.site', $config_data);
$this->assertTrue($sync->exists($name), $name . ' found.');
// Verify that system.site appears as ready to import.
$this->drupalGet('admin/config/development/configuration');
$this->assertSession()->responseContains('<td>' . $name);
$this->assertSession()->buttonExists('Import all');
// Click the dropbutton to show the differences in a modal and close it.
$page->find('css', '.dropbutton-action')->click();
$assert_session->waitForElementVisible('css', '.ui-dialog');
$assert_session->assertVisibleInViewport('css', '.ui-dialog .ui-dialog-content');
$page->pressButton('Close');
$assert_session->assertNoElementAfterWait('css', '.ui-dialog');
// Do this again to make sure no JavaScript errors occur on revisits.
$page->find('css', '.dropbutton-action')->click();
$assert_session->waitForElementVisible('css', '.ui-dialog');
$assert_session->assertVisibleInViewport('css', '.ui-dialog .ui-dialog-content');
$page->pressButton('Close');
$assert_session->assertNoElementAfterWait('css', '.ui-dialog');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment