Update to Drupal 8.2.6. For more information, see https://www.drupal.org/project/drupal/releases/8.2.6
This commit is contained in:
parent
db56c09587
commit
f1e72395cb
588 changed files with 26857 additions and 2777 deletions
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests\Dialog;
|
||||
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
|
||||
/**
|
||||
* Tests the JavaScript functionality of the dialog position.
|
||||
*
|
||||
* @group dialog
|
||||
*/
|
||||
class DialogPositionTest extends JavascriptTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block'];
|
||||
|
||||
/**
|
||||
* Tests if the dialog UI works properly with block layout page.
|
||||
*/
|
||||
public function testDialogOpenAndClose() {
|
||||
$admin_user = $this->drupalCreateUser(['administer blocks']);
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$session = $this->getSession();
|
||||
$assert_session = $this->assertSession();
|
||||
$page = $session->getPage();
|
||||
|
||||
// Open the dialog using the place block link.
|
||||
$placeBlockLink = $page->findLink('Place block');
|
||||
$this->assertTrue($placeBlockLink->isVisible(), 'Place block button exists.');
|
||||
$placeBlockLink->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$dialog = $page->find('css', '.ui-dialog');
|
||||
$this->assertTrue($dialog->isVisible(), 'Dialog is opened after clicking the Place block button.');
|
||||
|
||||
// Close the dialog again.
|
||||
$closeButton = $page->find('css', '.ui-dialog-titlebar-close');
|
||||
$closeButton->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$dialog = $page->find('css', '.ui-dialog');
|
||||
$this->assertNull($dialog, 'Dialog is closed after clicking the close button.');
|
||||
|
||||
// Resize the window. The test should pass after waiting for Javascript to
|
||||
// finish as no Javascript errors should have been triggered. If there were
|
||||
// javascript errors the test will fail on that.
|
||||
$session->resizeWindow(625, 625);
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
}
|
||||
|
||||
}
|
|
@ -26,21 +26,149 @@ class JSWebAssert extends WebAssert {
|
|||
* be displayed.
|
||||
*/
|
||||
public function assertWaitOnAjaxRequest($timeout = 10000, $message = 'Unable to complete AJAX request.') {
|
||||
$result = $this->session->wait($timeout, '(typeof(jQuery)=="undefined" || (0 === jQuery.active && 0 === jQuery(\':animated\').length))');
|
||||
$condition = <<<JS
|
||||
(function() {
|
||||
function isAjaxing(instance) {
|
||||
return instance && instance.ajaxing === true;
|
||||
}
|
||||
return (
|
||||
// Assert no AJAX request is running (via jQuery or Drupal) and no
|
||||
// animation is running.
|
||||
(typeof jQuery === 'undefined' || (jQuery.active === 0 && jQuery(':animated').length === 0)) &&
|
||||
(typeof Drupal === 'undefined' || typeof Drupal.ajax === 'undefined' || !Drupal.ajax.instances.some(isAjaxing))
|
||||
);
|
||||
}());
|
||||
JS;
|
||||
$result = $this->session->wait($timeout, $condition);
|
||||
if (!$result) {
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the specified selector and returns it when available.
|
||||
*
|
||||
* @param string $selector
|
||||
* The selector engine name. See ElementInterface::findAll() for the
|
||||
* supported selectors.
|
||||
* @param string|array $locator
|
||||
* The selector locator.
|
||||
* @param int $timeout
|
||||
* (Optional) Timeout in milliseconds, defaults to 10000.
|
||||
*
|
||||
* @return \Behat\Mink\Element\NodeElement|null
|
||||
* The page element node if found, NULL if not.
|
||||
*
|
||||
* @see \Behat\Mink\Element\ElementInterface::findAll()
|
||||
*/
|
||||
public function waitForElement($selector, $locator, $timeout = 10000) {
|
||||
$page = $this->session->getPage();
|
||||
|
||||
$result = $page->waitFor($timeout / 1000, function() use ($page, $selector, $locator) {
|
||||
return $page->find($selector, $locator);
|
||||
});
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the specified selector and returns it when available and visible.
|
||||
*
|
||||
* @param string $selector
|
||||
* The selector engine name. See ElementInterface::findAll() for the
|
||||
* supported selectors.
|
||||
* @param string|array $locator
|
||||
* The selector locator.
|
||||
* @param int $timeout
|
||||
* (Optional) Timeout in milliseconds, defaults to 10000.
|
||||
*
|
||||
* @return \Behat\Mink\Element\NodeElement|null
|
||||
* The page element node if found and visible, NULL if not.
|
||||
*
|
||||
* @see \Behat\Mink\Element\ElementInterface::findAll()
|
||||
*/
|
||||
public function waitForElementVisible($selector, $locator, $timeout = 10000) {
|
||||
$page = $this->session->getPage();
|
||||
|
||||
$result = $page->waitFor($timeout / 1000, function() use ($page, $selector, $locator) {
|
||||
$element = $page->find($selector, $locator);
|
||||
if (!empty($element) && $element->isVisible()) {
|
||||
return $element;
|
||||
}
|
||||
return NULL;
|
||||
});
|
||||
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* Waits for a button (input[type=submit|image|button|reset], button) with
|
||||
* specified locator and returns it.
|
||||
*
|
||||
* @param string $locator
|
||||
* The button ID, value or alt string.
|
||||
* @param int $timeout
|
||||
* (Optional) Timeout in milliseconds, defaults to 10000.
|
||||
*
|
||||
* @return \Behat\Mink\Element\NodeElement|null
|
||||
* The page element node if found, NULL if not.
|
||||
*/
|
||||
public function waitForButton($locator, $timeout = 10000) {
|
||||
return $this->waitForElement('named', array('button', $locator), $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a link with specified locator and returns it when available.
|
||||
*
|
||||
* @param string $locator
|
||||
* The link ID, title, text or image alt.
|
||||
* @param int $timeout
|
||||
* (Optional) Timeout in milliseconds, defaults to 10000.
|
||||
*
|
||||
* @return \Behat\Mink\Element\NodeElement|null
|
||||
* The page element node if found, NULL if not.
|
||||
*/
|
||||
public function waitForLink($locator, $timeout = 10000) {
|
||||
return $this->waitForElement('named', array('link', $locator), $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a field with specified locator and returns it when available.
|
||||
*
|
||||
* @param string $locator
|
||||
* The input ID, name or label for the field (input, textarea, select).
|
||||
* @param int $timeout
|
||||
* (Optional) Timeout in milliseconds, defaults to 10000.
|
||||
*
|
||||
* @return \Behat\Mink\Element\NodeElement|null
|
||||
* The page element node if found, NULL if not.
|
||||
*/
|
||||
public function waitForField($locator, $timeout = 10000) {
|
||||
return $this->waitForElement('named', array('field', $locator), $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for an element by its id and returns it when available.
|
||||
*
|
||||
* @param string $id
|
||||
* The element ID.
|
||||
* @param int $timeout
|
||||
* (Optional) Timeout in milliseconds, defaults to 10000.
|
||||
*
|
||||
* @return \Behat\Mink\Element\NodeElement|null
|
||||
* The page element node if found, NULL if not.
|
||||
*/
|
||||
public function waitForId($id, $timeout = 10000) {
|
||||
return $this->waitForElement('named', array('id', $id), $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the jQuery autocomplete delay duration.
|
||||
*
|
||||
* @see https://api.jqueryui.com/autocomplete/#option-delay
|
||||
*/
|
||||
public function waitOnAutocomplete() {
|
||||
// Drupal is using the default delay value of 300 milliseconds.
|
||||
$this->session->wait(300);
|
||||
$this->assertWaitOnAjaxRequest();
|
||||
// Wait for the autocomplete to be visible.
|
||||
return $this->waitForElementVisible('css', '.ui-autocomplete li');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests\Tests;
|
||||
|
||||
use Behat\Mink\Element\NodeElement;
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
|
||||
/**
|
||||
* Tests for the JSWebAssert class.
|
||||
*
|
||||
* @group javascript
|
||||
*/
|
||||
class JSWebAssertTest extends JavascriptTestBase {
|
||||
|
||||
/**
|
||||
* Required modules.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['js_webassert_test'];
|
||||
|
||||
/**
|
||||
* Tests that JSWebAssert assertions work correctly.
|
||||
*/
|
||||
public function testJsWebAssert() {
|
||||
$this->drupalGet('js_webassert_test_form');
|
||||
|
||||
$session = $this->getSession();
|
||||
$assert_session = $this->assertSession();
|
||||
$page = $session->getPage();
|
||||
|
||||
$test_button = $page->findButton('Add button');
|
||||
$test_link = $page->findButton('Add link');
|
||||
$test_field = $page->findButton('Add field');
|
||||
$test_id = $page->findButton('Add ID');
|
||||
$test_wait_on_ajax = $page->findButton('Test assertWaitOnAjaxRequest');
|
||||
$test_wait_on_element_visible = $page->findButton('Test waitForElementVisible');
|
||||
|
||||
// Test the wait...() methods by first checking the fields aren't available
|
||||
// and then are available after the wait method.
|
||||
$result = $page->findButton('Added button');
|
||||
$this->assertEmpty($result);
|
||||
$test_button->click();
|
||||
$result = $assert_session->waitForButton('Added button');
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertTrue($result instanceof NodeElement);
|
||||
|
||||
$result = $page->findLink('Added link');
|
||||
$this->assertEmpty($result);
|
||||
$test_link->click();
|
||||
$result = $assert_session->waitForLink('Added link');
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertTrue($result instanceof NodeElement);
|
||||
|
||||
$result = $page->findField('added_field');
|
||||
$this->assertEmpty($result);
|
||||
$test_field->click();
|
||||
$result = $assert_session->waitForField('added_field');
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertTrue($result instanceof NodeElement);
|
||||
|
||||
$result = $page->findById('js_webassert_test_field_id');
|
||||
$this->assertEmpty($result);
|
||||
$test_id->click();
|
||||
$result = $assert_session->waitForId('js_webassert_test_field_id');
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertTrue($result instanceof NodeElement);
|
||||
|
||||
// Test waitOnAjaxRequest. Verify the element is available after the wait
|
||||
// and the behaviors have run on completing by checking the value.
|
||||
$result = $page->findField('test_assert_wait_on_ajax_input');
|
||||
$this->assertEmpty($result);
|
||||
$test_wait_on_ajax->click();
|
||||
$assert_session->assertWaitOnAjaxRequest();
|
||||
$result = $page->findField('test_assert_wait_on_ajax_input');
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertTrue($result instanceof NodeElement);
|
||||
$this->assertEquals('js_webassert_test', $result->getValue());
|
||||
|
||||
$result = $page->findButton('Added WaitForElementVisible');
|
||||
$this->assertEmpty($result);
|
||||
$test_wait_on_element_visible->click();
|
||||
$result = $assert_session->waitForElementVisible('named', array('button', 'Added WaitForElementVisible'));
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertTrue($result instanceof NodeElement);
|
||||
$this->assertEquals(TRUE, $result->isVisible());
|
||||
}
|
||||
|
||||
}
|
|
@ -113,4 +113,12 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
|||
$this->assertText($sanitized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Drupal install done in \Drupal\Tests\BrowserTestBase::setUp().
|
||||
*/
|
||||
public function testInstall() {
|
||||
$htaccess_filename = $this->tempFilesDirectory . '/.htaccess';
|
||||
$this->assertTrue(file_exists($htaccess_filename), "$htaccess_filename exists");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
|
|||
/**
|
||||
* Tests for configuration dependencies.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Config\ConfigManager
|
||||
*
|
||||
* @group config
|
||||
*/
|
||||
class ConfigDependencyTest extends EntityKernelTestBase {
|
||||
|
@ -346,6 +348,123 @@ class ConfigDependencyTest extends EntityKernelTestBase {
|
|||
$this->assertFalse($storage->load($entity_4->id()), 'Entity 4 deleted');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::uninstall
|
||||
* @covers ::getConfigEntitiesToChangeOnDependencyRemoval
|
||||
*/
|
||||
public function testConfigEntityUninstallThirdParty() {
|
||||
/** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
|
||||
$config_manager = \Drupal::service('config.manager');
|
||||
/** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $storage */
|
||||
$storage = $this->container->get('entity_type.manager')
|
||||
->getStorage('config_test');
|
||||
// Entity 1 will be fixed because it only has a dependency via third-party
|
||||
// settings, which are fixable.
|
||||
$entity_1 = $storage->create([
|
||||
'id' => 'entity_1',
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'module' => ['config_test'],
|
||||
],
|
||||
],
|
||||
'third_party_settings' => [
|
||||
'node' => [
|
||||
'foo' => 'bar',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$entity_1->save();
|
||||
|
||||
// Entity 2 has a dependency on entity 1.
|
||||
$entity_2 = $storage->create([
|
||||
'id' => 'entity_2',
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'config' => [$entity_1->getConfigDependencyName()],
|
||||
],
|
||||
],
|
||||
'third_party_settings' => [
|
||||
'node' => [
|
||||
'foo' => 'bar',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$entity_2->save();
|
||||
|
||||
// Entity 3 will be unchanged because it is dependent on entity 2 which can
|
||||
// be fixed. The ConfigEntityInterface::onDependencyRemoval() method will
|
||||
// not be called for this entity.
|
||||
$entity_3 = $storage->create([
|
||||
'id' => 'entity_3',
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'config' => [$entity_2->getConfigDependencyName()],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$entity_3->save();
|
||||
|
||||
// Entity 4's config dependency will be fixed but it will still be deleted
|
||||
// because it also depends on the node module.
|
||||
$entity_4 = $storage->create([
|
||||
'id' => 'entity_4',
|
||||
'dependencies' => [
|
||||
'enforced' => [
|
||||
'config' => [$entity_1->getConfigDependencyName()],
|
||||
'module' => ['node', 'config_test'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$entity_4->save();
|
||||
|
||||
\Drupal::state()->set('config_test.fix_dependencies', []);
|
||||
\Drupal::state()->set('config_test.on_dependency_removal_called', []);
|
||||
|
||||
// Do a dry run using
|
||||
// \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval().
|
||||
$config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('module', ['node']);
|
||||
$config_entity_ids = [
|
||||
'update' => [],
|
||||
'delete' => [],
|
||||
'unchanged' => [],
|
||||
];
|
||||
foreach ($config_entities as $type => $config_entities_by_type) {
|
||||
foreach ($config_entities_by_type as $config_entity) {
|
||||
$config_entity_ids[$type][] = $config_entity->id();
|
||||
}
|
||||
}
|
||||
$expected = [
|
||||
'update' => [$entity_1->id(), $entity_2->id()],
|
||||
'delete' => [$entity_4->id()],
|
||||
'unchanged' => [$entity_3->id()],
|
||||
];
|
||||
$this->assertSame($expected, $config_entity_ids);
|
||||
|
||||
$called = \Drupal::state()->get('config_test.on_dependency_removal_called', []);
|
||||
$this->assertFalse(in_array($entity_3->id(), $called), 'ConfigEntityInterface::onDependencyRemoval() is not called for entity 3.');
|
||||
$this->assertSame([$entity_1->id(), $entity_4->id(), $entity_2->id()], $called, 'The most dependent entities have ConfigEntityInterface::onDependencyRemoval() called first.');
|
||||
|
||||
// Perform a module rebuild so we can know where the node module is located
|
||||
// and uninstall it.
|
||||
// @todo Remove as part of https://www.drupal.org/node/2186491
|
||||
system_rebuild_module_data();
|
||||
// Perform the uninstall.
|
||||
$config_manager->uninstall('module', 'node');
|
||||
|
||||
// Test that expected actions have been performed.
|
||||
$entity_1 = $storage->load($entity_1->id());
|
||||
$this->assertTrue($entity_1, 'Entity 1 not deleted');
|
||||
$this->assertSame($entity_1->getThirdPartySettings('node'), [], 'Entity 1 third party settings updated.');
|
||||
$entity_2 = $storage->load($entity_2->id());
|
||||
$this->assertTrue($entity_2, 'Entity 2 not deleted');
|
||||
$this->assertSame($entity_2->getThirdPartySettings('node'), [], 'Entity 2 third party settings updated.');
|
||||
$this->assertSame($entity_2->calculateDependencies()->getDependencies()['config'], [$entity_1->getConfigDependencyName()], 'Entity 2 still depends on entity 1.');
|
||||
$entity_3 = $storage->load($entity_3->id());
|
||||
$this->assertTrue($entity_3, 'Entity 3 not deleted');
|
||||
$this->assertSame($entity_3->calculateDependencies()->getDependencies()['config'], [$entity_2->getConfigDependencyName()], 'Entity 3 still depends on entity 2.');
|
||||
$this->assertFalse($storage->load($entity_4->id()), 'Entity 4 deleted');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a configuration entity and dependency management.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\comment\Entity\CommentType;
|
||||
use Drupal\Core\Entity\Entity\EntityViewDisplay;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityDisplayBase
|
||||
*
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityDisplayBaseTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['entity_test', 'entity_test_third_party', 'field', 'system', 'comment'];
|
||||
|
||||
/**
|
||||
* @covers ::onDependencyRemoval
|
||||
*/
|
||||
public function testOnDependencyRemoval() {
|
||||
// Create a comment field for entity_test.
|
||||
$comment_bundle = CommentType::create([
|
||||
'id' => 'entity_test',
|
||||
'label' => 'entity_test',
|
||||
'description' => '',
|
||||
'target_entity_type_id' => 'entity_test',
|
||||
]);
|
||||
$comment_bundle->save();
|
||||
$comment_display = EntityViewDisplay::create([
|
||||
'targetEntityType' => 'comment',
|
||||
'bundle' => 'entity_test',
|
||||
'mode' => 'default',
|
||||
'status' => TRUE,
|
||||
'third_party_settings' => [
|
||||
'entity_test_third_party' => [
|
||||
'key' => 'value',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$comment_display->save();
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'test_field',
|
||||
'type' => 'comment',
|
||||
'settings' => [
|
||||
'comment_type' => 'entity_test',
|
||||
],
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'label' => $this->randomMachineName(),
|
||||
'bundle' => 'entity_test',
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
// Create an entity view display for entity_test.
|
||||
$entity_display = EntityViewDisplay::create([
|
||||
'targetEntityType' => 'entity_test',
|
||||
'bundle' => 'entity_test',
|
||||
'mode' => 'default',
|
||||
'status' => TRUE,
|
||||
'content' => [
|
||||
'test_field' => ['type' => 'comment_default', 'settings' => ['view_mode' => 'default'], 'label' => 'hidden', 'third_party_settings' => []],
|
||||
],
|
||||
'third_party_settings' => [
|
||||
'entity_test_third_party' => [
|
||||
'key' => 'value',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$entity_display->save();
|
||||
|
||||
$expected_component = [
|
||||
'type' => 'comment_default',
|
||||
'settings' => ['view_mode' => 'default'],
|
||||
'label' => 'hidden',
|
||||
'third_party_settings' => [],
|
||||
];
|
||||
$entity_display->getComponent('test_field');
|
||||
$this->assertEquals($expected_component, $entity_display->getComponent('test_field'));
|
||||
$expected_dependencies = [
|
||||
'config' => [
|
||||
'core.entity_view_display.comment.entity_test.default',
|
||||
'field.field.entity_test.entity_test.test_field',
|
||||
],
|
||||
'module' => [
|
||||
'comment',
|
||||
'entity_test',
|
||||
'entity_test_third_party',
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected_dependencies, $entity_display->getDependencies());
|
||||
|
||||
// Uninstall the third-party settings provider and reload the display.
|
||||
$this->container->get('module_installer')->uninstall(['entity_test_third_party']);
|
||||
$entity_display = EntityViewDisplay::load('entity_test.entity_test.default');
|
||||
|
||||
// The component should remain unchanged.
|
||||
$this->assertEquals($expected_component, $entity_display->getComponent('test_field'));
|
||||
// The dependencies should no longer contain 'entity_test_third_party'.
|
||||
$expected_dependencies['module'] = [
|
||||
'comment',
|
||||
'entity_test',
|
||||
];
|
||||
$this->assertSame($expected_dependencies, $entity_display->getDependencies());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Field;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the exception when missing a field type.
|
||||
*
|
||||
* @group Field
|
||||
*/
|
||||
class FieldMissingTypeTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* Set to FALSE because we are hacking a field storage to use a fake type.
|
||||
*
|
||||
* @see \Drupal\Core\Config\Development\ConfigSchemaChecker
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $strictConfigSchema = FALSE;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$entity_type_id = 'entity_test_mulrev';
|
||||
$this->installEntitySchema($entity_type_id);
|
||||
$this->fieldName = Unicode::strtolower($this->randomMachineName());
|
||||
|
||||
/** @var \Drupal\field\Entity\FieldStorageConfig $field_storage */
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => $this->fieldName,
|
||||
'type' => 'text',
|
||||
'entity_type' => $entity_type_id,
|
||||
'cardinality' => 1,
|
||||
])->save();
|
||||
|
||||
FieldConfig::create([
|
||||
'entity_type' => $entity_type_id,
|
||||
'field_name' => $this->fieldName,
|
||||
'bundle' => $entity_type_id,
|
||||
'label' => 'Test field',
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the exception thrown when missing a field type in field storages.
|
||||
*
|
||||
* @see \Drupal\field\FieldStorageConfigStorage::mapFromStorageRecords()
|
||||
*/
|
||||
public function testFieldStorageMissingType() {
|
||||
$this->setExpectedException(\RuntimeException::class, "Unable to determine class for field type 'foo_field_storage' found in the 'field.storage.entity_test_mulrev.{$this->fieldName}' configuration");
|
||||
$entity = EntityTestMulRev::create([
|
||||
'name' => $this->randomString(),
|
||||
'field_test_item' => $this->randomString(),
|
||||
$this->fieldName => $this->randomString(),
|
||||
]);
|
||||
$entity->save();
|
||||
// Hack the field storage to use a non-existent field type.
|
||||
$this->config('field.storage.entity_test_mulrev.' . $this->fieldName)->set('type', 'foo_field_storage')->save();
|
||||
\Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
|
||||
EntityTestMulRev::load($entity->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the exception thrown when missing a field type in fields.
|
||||
*
|
||||
* @see \Drupal\field\FieldConfigStorageBase::mapFromStorageRecords()
|
||||
*/
|
||||
public function testFieldMissingType() {
|
||||
$this->setExpectedException(\RuntimeException::class, "Unable to determine class for field type 'foo_field' found in the 'field.field.entity_test_mulrev.entity_test_mulrev.{$this->fieldName}' configuration");
|
||||
$entity = EntityTestMulRev::create([
|
||||
'name' => $this->randomString(),
|
||||
'field_test_item' => $this->randomString(),
|
||||
$this->fieldName => $this->randomString(),
|
||||
]);
|
||||
$entity->save();
|
||||
// Hack the field to use a non-existent field type.
|
||||
$this->config('field.field.entity_test_mulrev.entity_test_mulrev.' . $this->fieldName)->set('field_type', 'foo_field')->save();
|
||||
\Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
|
||||
EntityTestMulRev::load($entity->id());
|
||||
}
|
||||
|
||||
}
|
|
@ -119,7 +119,11 @@ abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase {
|
|||
/**
|
||||
* The temp file directory for the test environment.
|
||||
*
|
||||
* This is set in BrowserTestBase::prepareEnvironment().
|
||||
* This is set in BrowserTestBase::prepareEnvironment(). This value has to
|
||||
* match the temporary directory created in install_base_system() for test
|
||||
* installs.
|
||||
*
|
||||
* @see install_base_system()
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
@ -351,7 +355,11 @@ abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase {
|
|||
$driver = $this->getDefaultDriverInstance();
|
||||
|
||||
if ($driver instanceof GoutteDriver) {
|
||||
$driver->getClient()->setClient(\Drupal::httpClient());
|
||||
// Turn off curl timeout. Having a timeout is not a problem in a normal
|
||||
// test running, but it is a problem when debugging.
|
||||
/** @var \GuzzleHttp\Client $client */
|
||||
$client = $this->container->get('http_client_factory')->fromOptions(['timeout' => NULL]);
|
||||
$driver->getClient()->setClient($client);
|
||||
}
|
||||
|
||||
$session = new Session($driver);
|
||||
|
@ -1015,9 +1023,13 @@ abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase {
|
|||
$directory = DRUPAL_ROOT . '/' . $this->siteDirectory;
|
||||
copy(DRUPAL_ROOT . '/sites/default/default.settings.php', $directory . '/settings.php');
|
||||
|
||||
// All file system paths are created by System module during installation.
|
||||
// The public file system path is created during installation. Additionally,
|
||||
// during tests:
|
||||
// - The temporary directory is set and created by install_base_system().
|
||||
// - The private file directory is created post install by this method.
|
||||
// @see system_requirements()
|
||||
// @see TestBase::prepareEnvironment()
|
||||
// @see install_base_system()
|
||||
$settings['settings']['file_public_path'] = (object) array(
|
||||
'value' => $this->publicFilesDirectory,
|
||||
'required' => TRUE,
|
||||
|
@ -1092,16 +1104,8 @@ abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
$config = $container->get('config.factory');
|
||||
|
||||
// Manually create and configure private and temporary files directories.
|
||||
// Manually create the private directory.
|
||||
file_prepare_directory($this->privateFilesDirectory, FILE_CREATE_DIRECTORY);
|
||||
file_prepare_directory($this->tempFilesDirectory, FILE_CREATE_DIRECTORY);
|
||||
// While the temporary files path could be preset/enforced in settings.php
|
||||
// like the public files directory above, some tests expect it to be
|
||||
// configurable in the UI. If declared in settings.php, it would no longer
|
||||
// be configurable.
|
||||
$config->getEditable('system.file')
|
||||
->set('path.temporary', $this->tempFilesDirectory)
|
||||
->save();
|
||||
|
||||
// Manually configure the test mail collector implementation to prevent
|
||||
// tests from sending out emails and collect them in state instead.
|
||||
|
|
|
@ -74,19 +74,18 @@ class ComposerIntegrationTest extends UnitTestCase {
|
|||
public function testComposerJson() {
|
||||
foreach ($this->getPaths() as $path) {
|
||||
$json = file_get_contents($path . '/composer.json');
|
||||
|
||||
$result = json_decode($json);
|
||||
$this->assertNotNull($result, $this->getErrorMessages()[json_last_error()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests composer.lock hash.
|
||||
* Tests composer.lock content-hash.
|
||||
*/
|
||||
public function testComposerLockHash() {
|
||||
$json = file_get_contents($this->root . '/composer.json');
|
||||
$content_hash = self::getContentHash(file_get_contents($this->root . '/composer.json'));
|
||||
$lock = json_decode(file_get_contents($this->root . '/composer.lock'), TRUE);
|
||||
$this->assertSame(md5($json), $lock['hash']);
|
||||
$this->assertSame($content_hash, $lock['content-hash']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,4 +125,50 @@ class ComposerIntegrationTest extends UnitTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
/**
|
||||
* The following method is copied from \Composer\Package\Locker.
|
||||
*
|
||||
* @see https://github.com/composer/composer
|
||||
*/
|
||||
/**
|
||||
* Returns the md5 hash of the sorted content of the composer file.
|
||||
*
|
||||
* @param string $composerFileContents The contents of the composer file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getContentHash($composerFileContents)
|
||||
{
|
||||
$content = json_decode($composerFileContents, true);
|
||||
|
||||
$relevantKeys = array(
|
||||
'name',
|
||||
'version',
|
||||
'require',
|
||||
'require-dev',
|
||||
'conflict',
|
||||
'replace',
|
||||
'provide',
|
||||
'minimum-stability',
|
||||
'prefer-stable',
|
||||
'repositories',
|
||||
'extra',
|
||||
);
|
||||
|
||||
$relevantContent = array();
|
||||
|
||||
foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
|
||||
$relevantContent[$key] = $content[$key];
|
||||
}
|
||||
if (isset($content['config']['platform'])) {
|
||||
$relevantContent['config']['platform'] = $content['config']['platform'];
|
||||
}
|
||||
|
||||
ksort($relevantContent);
|
||||
|
||||
return md5(json_encode($relevantContent));
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Drupal\Tests\Core\DrupalKernel {
|
|||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use Symfony\Component\ClassLoader\ApcClassLoader;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
|
@ -47,6 +48,63 @@ namespace Drupal\Tests\Core\DrupalKernel {
|
|||
Request::setFactory(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the reregistration of autoloaders if APCu available.
|
||||
*
|
||||
* This test runs in a separate process since it registers class loaders and
|
||||
* results in statics being set.
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
* @requires function apcu_fetch
|
||||
* @covers ::initializeSettings
|
||||
*/
|
||||
public function testInitializeSettings() {
|
||||
$request = new Request();
|
||||
$classloader = new fakeAutoloader();
|
||||
|
||||
// Create a kernel suitable for testing.
|
||||
$kernel = $this->getMockBuilder(DrupalKernel::class)
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['do_not_mock_any_methods'])
|
||||
->getMock();
|
||||
$classloader_property = new \ReflectionProperty($kernel, 'classLoader');
|
||||
$classloader_property->setAccessible(TRUE);
|
||||
$classloader_property->setValue($kernel, $classloader);
|
||||
$method = new \ReflectionMethod($kernel, 'initializeSettings');
|
||||
$method->setAccessible(TRUE);
|
||||
|
||||
// Prepend another autoloader to simulate Drush's autoloader.
|
||||
$fake_drush_autoloader = function () {
|
||||
return NULL;
|
||||
};
|
||||
spl_autoload_register($fake_drush_autoloader, TRUE, TRUE);
|
||||
|
||||
// Before calling DrupalKernel::initializeSettings() the first autoloader
|
||||
// is the fake Drush autoloader.
|
||||
$this->assertSame($fake_drush_autoloader, spl_autoload_functions()[0]);
|
||||
|
||||
// Call DrupalKernel::initializeSettings() to simulate part of a Drupal
|
||||
// bootstrap. During the include of autoload.php Composer would prepend
|
||||
// Drupal's autoloader and then this method should not result in Drush's
|
||||
// autoloader becoming the first autoloader even if it swaps out
|
||||
// Composer's autoloader for an optimised one.
|
||||
$method->invoke($kernel, $request);
|
||||
|
||||
$autoloaders = spl_autoload_functions();
|
||||
// The first autoloader should be the APCu based autoloader.
|
||||
$this->assertInstanceOf(ApcClassLoader::class, $autoloaders[0][0]);
|
||||
// The second autoloader should be the original autoloader the kernel was
|
||||
// constructed with.
|
||||
$this->assertSame($classloader, $autoloaders[1][0]);
|
||||
// The third autoloader should be Drush's autoloader.
|
||||
$this->assertSame($fake_drush_autoloader, $autoloaders[2]);
|
||||
|
||||
// Reset the request factory because it is statically stored on the
|
||||
// request.
|
||||
Request::setFactory(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testTrustedHosts().
|
||||
*/
|
||||
|
@ -136,6 +194,49 @@ EOD;
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* A fake autoloader for testing
|
||||
*/
|
||||
class fakeAutoloader {
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend
|
||||
* Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = FALSE) {
|
||||
spl_autoload_register(array($this, 'loadClass'), TRUE, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister() {
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @return null
|
||||
* This class never loads.
|
||||
*/
|
||||
public function loadClass() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a file by class name while caching lookups to APC.
|
||||
*
|
||||
* @return null
|
||||
* This class never finds.
|
||||
*/
|
||||
public function findFile() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Core\EventSubscriber;
|
||||
|
||||
use Drupal\Core\EventSubscriber\RssResponseRelativeUrlFilter;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\EventSubscriber\RssResponseRelativeUrlFilter
|
||||
* @group event_subscriber
|
||||
*/
|
||||
class RssResponseRelativeUrlFilterTest extends UnitTestCase {
|
||||
|
||||
public function providerTestOnResponse() {
|
||||
$data = [];
|
||||
|
||||
$valid_feed = <<<RSS
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0" xml:base="https://www.drupal.org">
|
||||
<channel>
|
||||
<title>Drupal.org</title>
|
||||
<link>https://www.drupal.org</link>
|
||||
<description>Come for the software, stay for the community
|
||||
D rupal is an open source content management platform powering millions of websites and applications. It’s built, used, and supported by an active and diverse community of people around the world.</description>
|
||||
<language>en</language>
|
||||
<item>
|
||||
<title>Drupal 8 turns one!</title>
|
||||
<link>https://www.drupal.org/blog/drupal-8-turns-one</link>
|
||||
<description><a href="localhost/node/1">Hello</a>
|
||||
</description>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
RSS;
|
||||
|
||||
$valid_expected_feed = <<<RSS
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0" xml:base="https://www.drupal.org">
|
||||
<channel>
|
||||
<title>Drupal.org</title>
|
||||
<link>https://www.drupal.org</link>
|
||||
<description>Come for the software, stay for the community
|
||||
D rupal is an open source content management platform powering millions of websites and applications. It’s built, used, and supported by an active and diverse community of people around the world.</description>
|
||||
<language>en</language>
|
||||
<item>
|
||||
<title>Drupal 8 turns one!</title>
|
||||
<link>https://www.drupal.org/blog/drupal-8-turns-one</link>
|
||||
<description><a href="localhost/node/1">Hello</a>
|
||||
</description>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
|
||||
RSS;
|
||||
|
||||
$data['valid-feed'] = [$valid_feed, $valid_expected_feed];
|
||||
|
||||
$invalid_feed = <<<RSS
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<rss version="2.0" xml:base="https://www.drupal.org" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<channel>
|
||||
<title>Drupal.org</title>
|
||||
<link>https://www.drupal.org</link>
|
||||
<description>Come for the software, stay for the community
|
||||
D rupal is an open source content management platform powering millions of websites and applications. It’s built, used, and supported by an active and diverse community of people around the world.</description>
|
||||
<language>en</language>
|
||||
<item>
|
||||
<title>Drupal 8 turns one!</title>
|
||||
<link>https://www.drupal.org/blog/drupal-8-turns-one</link>
|
||||
<description>
|
||||
<![CDATA[
|
||||
<a href="localhost/node/1">Hello</a>
|
||||
<script>
|
||||
<!--//--><![CDATA[// ><!--
|
||||
|
||||
<!--//--><![CDATA[// ><!--
|
||||
|
||||
<!--//--><![CDATA[// ><!--
|
||||
(function(d, s, id) {
|
||||
var js, fjs = d.getElementsByTagName(s)[0];
|
||||
if (d.getElementById(id)) return;
|
||||
js = d.createElement(s); js.id = id;
|
||||
js.src = "//connect.facebook.net/de_DE/sdk.js#xfbml=1&version=v2.3";
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}(document, 'script', 'facebook-jssdk'));
|
||||
//--><!]]]]]]><![CDATA[><![CDATA[>
|
||||
|
||||
//--><!]]]]><![CDATA[>
|
||||
|
||||
//--><!]]>
|
||||
</script>
|
||||
]]>
|
||||
</description>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
RSS;
|
||||
|
||||
|
||||
$data['invalid-feed'] = [$invalid_feed, $invalid_feed];
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerTestOnResponse
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $expected_content
|
||||
*/
|
||||
public function testOnResponse($content, $expected_content) {
|
||||
$event = new FilterResponseEvent(
|
||||
$this->prophesize(HttpKernelInterface::class)->reveal(),
|
||||
Request::create('/'),
|
||||
'foo',
|
||||
new Response($content, 200, [
|
||||
'Content-Type' => 'application/rss+xml'
|
||||
])
|
||||
);
|
||||
|
||||
$url_filter = new RssResponseRelativeUrlFilter();
|
||||
$url_filter->onResponse($event);
|
||||
|
||||
$this->assertEquals($expected_content, $event->getResponse()->getContent());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Core\StringTranslation;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the TranslatableMarkup class.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\StringTranslation\PluralTranslatableMarkup
|
||||
* @group StringTranslation
|
||||
*/
|
||||
class PluralTranslatableMarkupTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests serialization of PluralTranslatableMarkup().
|
||||
*
|
||||
* @dataProvider providerPluralTranslatableMarkupSerialization
|
||||
*/
|
||||
public function testPluralTranslatableMarkupSerialization($count, $expected_text) {
|
||||
// Add a mock string translation service to the container.
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('string_translation', $this->getStringTranslationStub());
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
// Create an object to serialize and unserialize.
|
||||
$markup = new PluralTranslatableMarkup($count, 'singular @count', 'plural @count');
|
||||
$serialized_markup = unserialize(serialize($markup));
|
||||
$this->assertEquals($expected_text, $serialized_markup->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testPluralTranslatableMarkupSerialization().
|
||||
*/
|
||||
public function providerPluralTranslatableMarkupSerialization() {
|
||||
return [
|
||||
[1, 'singular 1'],
|
||||
[2, 'plural 2'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue