composer update
This commit is contained in:
parent
f6abc3dce2
commit
71dfaca858
1753 changed files with 45274 additions and 14619 deletions
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests\Ajax;
|
||||
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
|
||||
/**
|
||||
* Various tests of AJAX behavior.
|
||||
*
|
||||
* @group Ajax
|
||||
*/
|
||||
class ElementValidationTest extends WebDriverTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['ajax_test', 'ajax_forms_test'];
|
||||
|
||||
/**
|
||||
* Tries to post an Ajax change to a form that has a validated element.
|
||||
*
|
||||
* Drupal AJAX commands update the DOM echoing back the validated values in
|
||||
* the form of messages that appear on the page.
|
||||
*/
|
||||
public function testAjaxElementValidation() {
|
||||
$this->drupalGet('ajax_validation_test');
|
||||
$page = $this->getSession()->getPage();
|
||||
$assert = $this->assertSession();
|
||||
|
||||
// Partially complete the form with a string.
|
||||
$page->fillField('drivertext', 'some dumb text');
|
||||
// Move focus away from this field to trigger AJAX.
|
||||
$page->findField('spare_required_field')->focus();
|
||||
|
||||
// When the AJAX command updates the DOM a <ul> unsorted list
|
||||
// "message__list" structure will appear on the page echoing back the
|
||||
// "some dumb text" message.
|
||||
$placeholder_text = $assert->waitForElement('css', "ul.messages__list li.messages__item em:contains('some dumb text')");
|
||||
$this->assertNotNull($placeholder_text, 'A callback successfully echoed back a string.');
|
||||
|
||||
$this->drupalGet('ajax_validation_test');
|
||||
// Partialy complete the form with a number.
|
||||
$page->fillField('drivernumber', '12345');
|
||||
$page->findField('spare_required_field')->focus();
|
||||
|
||||
// The AJAX request/resonse will complete successfully when a InsertCommand
|
||||
// injects a message with a placeholder element into the DOM with the
|
||||
// submitted number.
|
||||
$placeholder_number = $assert->waitForElement('css', "ul.messages__list li.messages__item em:contains('12345')");
|
||||
$this->assertNotNull($placeholder_number, 'A callback successfully echoed back a number.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests\Ajax;
|
||||
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
|
||||
/**
|
||||
* Tests that form values are properly delivered to AJAX callbacks.
|
||||
*
|
||||
* @group Ajax
|
||||
*/
|
||||
class FormValuesTest extends WebDriverTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node', 'ajax_test', 'ajax_forms_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalLogin($this->drupalCreateUser(['access content']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits forms with select and checkbox elements via Ajax.
|
||||
*/
|
||||
public function testSimpleAjaxFormValue() {
|
||||
|
||||
$this->drupalGet('ajax_forms_test_get_form');
|
||||
|
||||
$session = $this->getSession();
|
||||
$assertSession = $this->assertSession();
|
||||
|
||||
// Verify form values of a select element.
|
||||
foreach (['green', 'blue', 'red'] as $item) {
|
||||
// Updating the field will trigger a AJAX request/response.
|
||||
$session->getPage()->selectFieldOption('select', $item);
|
||||
|
||||
// The AJAX command in the response will update the DOM
|
||||
$select = $assertSession->waitForElement('css', "div#ajax_selected_color:contains('$item')");
|
||||
$this->assertNotNull($select, "DataCommand has updated the page with a value of $item.");
|
||||
}
|
||||
|
||||
// Verify form values of a checkbox element.
|
||||
$session->getPage()->checkField('checkbox');
|
||||
$div0 = $this->assertSession()->waitForElement('css', "div#ajax_checkbox_value:contains('checked')");
|
||||
$this->assertNotNull($div0, 'DataCommand updates the DOM as expected when a checkbox is selected');
|
||||
|
||||
$session->getPage()->uncheckField('checkbox');
|
||||
$div1 = $this->assertSession()->waitForElement('css', "div#ajax_checkbox_value:contains('unchecked')");
|
||||
$this->assertNotNull($div1, 'DataCommand updates the DOM as expected when a checkbox is de-selected');
|
||||
|
||||
// Verify that AJAX elements with invalid callbacks return error code 500.
|
||||
// Ensure the test error log is empty before these tests.
|
||||
$this->assertFalse(file_exists(DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log'), 'PHP error.log is empty.');
|
||||
// We don't need to check for the X-Drupal-Ajax-Token header with these
|
||||
// invalid requests.
|
||||
$this->assertAjaxHeader = FALSE;
|
||||
foreach (['null', 'empty', 'nonexistent'] as $key) {
|
||||
$element_name = 'select_' . $key . '_callback';
|
||||
// Updating the field will trigger a AJAX request/response.
|
||||
$session->getPage()->selectFieldOption($element_name, 'green');
|
||||
|
||||
// The select element is disabled as the AJAX request is issued.
|
||||
$this->assertSession()->waitForElement('css', "select[name=\"$element_name\"]:disabled");
|
||||
|
||||
// The select element is enabled as the response is receieved.
|
||||
$this->assertSession()->waitForElement('css', "select[name=\"$element_name\"]:enabled");
|
||||
$this->assertTrue(file_exists(DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log'), 'PHP error.log is not empty.');
|
||||
$this->assertContains('"The specified #ajax callback is empty or not callable."', file_get_contents(DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log'));
|
||||
// The exceptions are expected. Do not interpret them as a test failure.
|
||||
// Not using File API; a potential error must trigger a PHP warning.
|
||||
unlink(\Drupal::root() . '/' . $this->siteDirectory . '/error.log');
|
||||
}
|
||||
// We need to reload the page to kill any unfinished AJAX calls before
|
||||
// tearDown() is called.
|
||||
$this->drupalGet('ajax_forms_test_get_form');
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\FunctionalTests\Bootstrap;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
|
@ -37,7 +38,7 @@ class UncaughtExceptionTest extends BrowserTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['error_service_test'];
|
||||
public static $modules = ['error_service_test', 'error_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -99,6 +100,31 @@ class UncaughtExceptionTest extends BrowserTestBase {
|
|||
$this->assertErrorLogged($this->expectedExceptionMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests displaying an uncaught fatal error.
|
||||
*/
|
||||
public function testUncaughtFatalError() {
|
||||
$fatal_error = [
|
||||
'%type' => 'Recoverable fatal error',
|
||||
'@message' => 'Argument 1 passed to Drupal\error_test\Controller\ErrorTestController::Drupal\error_test\Controller\{closure}() must be of the type array, string given, called in ' . \Drupal::root() . '/core/modules/system/tests/modules/error_test/src/Controller/ErrorTestController.php on line 62 and defined',
|
||||
'%function' => 'Drupal\error_test\Controller\ErrorTestController->Drupal\error_test\Controller\{closure}()',
|
||||
];
|
||||
if (version_compare(PHP_VERSION, '7.0.0-dev') >= 0) {
|
||||
// In PHP 7, instead of a recoverable fatal error we get a TypeError.
|
||||
$fatal_error['%type'] = 'TypeError';
|
||||
// The error message also changes in PHP 7.
|
||||
$fatal_error['@message'] = 'Argument 1 passed to Drupal\error_test\Controller\ErrorTestController::Drupal\error_test\Controller\{closure}() must be of the type array, string given, called in ' . \Drupal::root() . '/core/modules/system/tests/modules/error_test/src/Controller/ErrorTestController.php on line 62';
|
||||
}
|
||||
$this->drupalGet('error-test/generate-fatals');
|
||||
$this->assertResponse(500, 'Received expected HTTP status code.');
|
||||
$message = new FormattableMarkup('%type: @message in %function (line ', $fatal_error);
|
||||
$this->assertRaw((string) $message);
|
||||
$this->assertRaw('<pre class="backtrace">');
|
||||
// Ensure we are escaping but not double escaping.
|
||||
$this->assertRaw(''');
|
||||
$this->assertNoRaw('&#039;');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests uncaught exception handling with custom exception handler.
|
||||
*/
|
||||
|
|
|
@ -114,6 +114,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
|||
|
||||
// Test drupalPostForm().
|
||||
$edit = ['bananas' => 'red'];
|
||||
// Submit the form using the button label.
|
||||
$result = $this->drupalPostForm('form-test/object-builder', $edit, 'Save');
|
||||
$this->assertSame($this->getSession()->getPage()->getContent(), $result);
|
||||
$value = $config_factory->get('form_test.object')->get('bananas');
|
||||
|
@ -123,6 +124,20 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
|||
$value = $config_factory->get('form_test.object')->get('bananas');
|
||||
$this->assertSame('', $value);
|
||||
|
||||
// Submit the form using the button id.
|
||||
$edit = ['bananas' => 'blue'];
|
||||
$result = $this->drupalPostForm('form-test/object-builder', $edit, 'edit-submit');
|
||||
$this->assertSame($this->getSession()->getPage()->getContent(), $result);
|
||||
$value = $config_factory->get('form_test.object')->get('bananas');
|
||||
$this->assertSame('blue', $value);
|
||||
|
||||
// Submit the form using the button name.
|
||||
$edit = ['bananas' => 'purple'];
|
||||
$result = $this->drupalPostForm('form-test/object-builder', $edit, 'op');
|
||||
$this->assertSame($this->getSession()->getPage()->getContent(), $result);
|
||||
$value = $config_factory->get('form_test.object')->get('bananas');
|
||||
$this->assertSame('purple', $value);
|
||||
|
||||
// Test drupalPostForm() with no-html response.
|
||||
$values = Json::decode($this->drupalPostForm('form_test/form-state-values-clean', [], t('Submit')));
|
||||
$this->assertTrue(1000, $values['beer']);
|
||||
|
|
|
@ -19,7 +19,7 @@ class InstallerDatabaseErrorMessagesTest extends InstallerTestBase {
|
|||
// it will try and create the drupal_install_test table as this is part of
|
||||
// the standard database tests performed by the installer in
|
||||
// Drupal\Core\Database\Install\Tasks.
|
||||
Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NULL)');
|
||||
Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NOT NULL PRIMARY KEY)');
|
||||
parent::setUpSettings();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,12 +48,12 @@ class InstallerTranslationTest extends InstallerTestBase {
|
|||
// it will try and create the drupal_install_test table as this is part of
|
||||
// the standard database tests performed by the installer in
|
||||
// Drupal\Core\Database\Install\Tasks.
|
||||
Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NULL)');
|
||||
Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NOT NULL PRIMARY KEY)');
|
||||
parent::setUpSettings();
|
||||
|
||||
// Ensure that the error message translation is working.
|
||||
$this->assertRaw('Beheben Sie alle Probleme unten, um die Installation fortzusetzen. Informationen zur Konfiguration der Datenbankserver finden Sie in der <a href="https://www.drupal.org/getting-started/install">Installationshandbuch</a>, oder kontaktieren Sie Ihren Hosting-Anbieter.');
|
||||
$this->assertRaw('<strong>CREATE</strong> ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl <em class="placeholder">CREATE TABLE {drupal_install_test} (id int NULL)</em> fehlgeschlagen.');
|
||||
$this->assertRaw('<strong>CREATE</strong> ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl <em class="placeholder">CREATE TABLE {drupal_install_test} (id int NOT NULL PRIMARY KEY)</em> fehlgeschlagen.');
|
||||
|
||||
// Now do it successfully.
|
||||
Database::getConnection('default')->query('DROP TABLE {drupal_install_test}');
|
||||
|
|
|
@ -40,7 +40,7 @@ trait AssertConfigTrait {
|
|||
|
||||
// Allow to skip entire config files.
|
||||
if ($skipped_config[$config_name] === TRUE) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
// Allow to skip some specific lines of imported config files.
|
||||
|
@ -71,12 +71,12 @@ trait AssertConfigTrait {
|
|||
case 'Drupal\Component\Diff\Engine\DiffOpAdd':
|
||||
// The _core property does not exist in the default config.
|
||||
if ($op->closing[0] === '_core:') {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
foreach ($op->closing as $closing) {
|
||||
// The UUIDs don't exist in the default config.
|
||||
if (strpos($closing, 'uuid: ') === 0) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
throw new \Exception($config_name . ': ' . var_export($op, TRUE));
|
||||
}
|
||||
|
|
|
@ -29,8 +29,12 @@ class SizeTest extends KernelTestBase {
|
|||
public function providerTestCommonFormatSize() {
|
||||
$kb = Bytes::KILOBYTE;
|
||||
return [
|
||||
['0 bytes', 0],
|
||||
['1 byte', 1],
|
||||
['-1 bytes', -1],
|
||||
['2 bytes', 2],
|
||||
['-2 bytes', -2],
|
||||
['1023 bytes', $kb - 1],
|
||||
['1 KB', $kb],
|
||||
['1 MB', pow($kb, 2)],
|
||||
['1 GB', pow($kb, 3)],
|
||||
|
@ -39,10 +43,13 @@ class SizeTest extends KernelTestBase {
|
|||
['1 EB', pow($kb, 6)],
|
||||
['1 ZB', pow($kb, 7)],
|
||||
['1 YB', pow($kb, 8)],
|
||||
// Rounded to 1 MB - not 1000 or 1024 kilobyte
|
||||
['1024 YB', pow($kb, 9)],
|
||||
// Rounded to 1 MB - not 1000 or 1024 kilobytes
|
||||
['1 MB', ($kb * $kb) - 1],
|
||||
['-1 MB', -(($kb * $kb) - 1)],
|
||||
// Decimal Megabytes
|
||||
['3.46 MB', 3623651],
|
||||
['3.77 GB', 4053371676],
|
||||
// Decimal Petabytes
|
||||
['59.72 PB', 67234178751368124],
|
||||
// Decimal Yottabytes
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityStorageException;
|
||||
use Drupal\Core\Entity\RevisionLogInterface;
|
||||
use Drupal\Core\Entity\TypedData\EntityDataDefinition;
|
||||
use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface;
|
||||
|
@ -919,4 +920,33 @@ class EntityFieldTest extends EntityKernelTestBase {
|
|||
$this->assertEqual($entity->field_test_text->processed, $target, format_string('%entity_type: Text is processed with the default filter.', ['%entity_type' => $entity_type]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests explicit entity ID assignment.
|
||||
*/
|
||||
public function testEntityIdAssignment() {
|
||||
$entity_type = 'entity_test';
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage($entity_type);
|
||||
|
||||
// Check that an ID can be explicitly assigned on creation.
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $this->createTestEntity($entity_type);
|
||||
$entity_id = 3;
|
||||
$entity->set('id', $entity_id);
|
||||
$this->assertSame($entity_id, $entity->id());
|
||||
$storage->save($entity);
|
||||
$entity = $storage->loadUnchanged($entity->id());
|
||||
$this->assertTrue($entity);
|
||||
|
||||
// Check that an explicitly-assigned ID is preserved on update.
|
||||
$storage->save($entity);
|
||||
$entity = $storage->loadUnchanged($entity->id());
|
||||
$this->assertTrue($entity);
|
||||
|
||||
// Check that an ID cannot be explicitly assigned on update.
|
||||
$this->setExpectedException(EntityStorageException::class);
|
||||
$entity->set('id', $entity_id + 1);
|
||||
$storage->save($entity);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -138,8 +138,11 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
}
|
||||
foreach (array_reverse(str_split(decbin($i))) as $key => $bit) {
|
||||
if ($bit) {
|
||||
list($field_name, $langcode, $values) = $units[$key];
|
||||
$entity->getTranslation($langcode)->{$field_name}[] = $values;
|
||||
// @todo https://www.drupal.org/project/drupal/issues/3001920 Doing
|
||||
// list($field_name, $langcode, $values) = $units[$key]; causes
|
||||
// problems in PHP 7.3. Revert to better variable names once
|
||||
// https://bugs.php.net/bug.php?id=76937 is fixed.
|
||||
$entity->getTranslation($units[$key][1])->{$units[$key][0]}[] = $units[$key][2];
|
||||
}
|
||||
}
|
||||
$entity->save();
|
||||
|
@ -1160,4 +1163,42 @@ class EntityQueryTest extends EntityKernelTestBase {
|
|||
$this->assertEquals($entity->id(), reset($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests entity queries with condition on the revision metadata keys.
|
||||
*/
|
||||
public function testConditionOnRevisionMetadataKeys() {
|
||||
$this->installModule('entity_test_revlog');
|
||||
$this->installEntitySchema('entity_test_revlog');
|
||||
|
||||
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
|
||||
$entity_type_manager = $this->container->get('entity_type.manager');
|
||||
/** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */
|
||||
$entity_type = $entity_type_manager->getDefinition('entity_test_revlog');
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $entity_type_manager->getStorage('entity_test_revlog');
|
||||
|
||||
$revision_created_timestamp = time();
|
||||
$revision_created_field_name = $entity_type->getRevisionMetadataKey('revision_created');
|
||||
$entity = $storage->create([
|
||||
'type' => 'entity_test',
|
||||
$revision_created_field_name => $revision_created_timestamp,
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
// Query only the default revision.
|
||||
$result = $storage->getQuery()
|
||||
->condition($revision_created_field_name, $revision_created_timestamp)
|
||||
->execute();
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals($entity->id(), reset($result));
|
||||
|
||||
// Query all revisions.
|
||||
$result = $storage->getQuery()
|
||||
->condition($revision_created_field_name, $revision_created_timestamp)
|
||||
->allRevisions()
|
||||
->execute();
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertEquals($entity->id(), reset($result));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\File;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests that the phar stream wrapper works.
|
||||
*
|
||||
* @group File
|
||||
*/
|
||||
class PharWrapperTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Tests that only valid phar files can be used.
|
||||
*/
|
||||
public function testPharFile() {
|
||||
$base = $this->getDrupalRoot() . '/core/modules/simpletest/files';
|
||||
// Ensure that file operations via the phar:// stream wrapper work for phar
|
||||
// files with the .phar extension.
|
||||
$this->assertFalse(file_exists("phar://$base/phar-1.phar/no-such-file.php"));
|
||||
$this->assertTrue(file_exists("phar://$base/phar-1.phar/index.php"));
|
||||
$file_contents = file_get_contents("phar://$base/phar-1.phar/index.php");
|
||||
$expected_hash = 'c7e7904ea573c5ebea3ef00bb08c1f86af1a45961fbfbeb1892ff4a98fd73ad5';
|
||||
$this->assertSame($expected_hash, hash('sha256', $file_contents));
|
||||
|
||||
// Ensure that file operations via the phar:// stream wrapper throw an
|
||||
// exception for files without the .phar extension.
|
||||
$this->setExpectedException('TYPO3\PharStreamWrapper\Exception');
|
||||
file_exists("phar://$base/image-2.jpg/index.php");
|
||||
}
|
||||
|
||||
}
|
|
@ -144,4 +144,31 @@ class StreamWrapperTest extends FileTestBase {
|
|||
$this->assertFalse(file_stream_wrapper_valid_scheme(file_uri_scheme('foo://asdf')), 'Did not get a valid stream scheme from foo://asdf');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that phar stream wrapper is registered as expected.
|
||||
*
|
||||
* @see \Drupal\Core\StreamWrapper\StreamWrapperManager::register()
|
||||
*/
|
||||
public function testPharStreamWrapperRegistration() {
|
||||
if (!in_array('phar', stream_get_wrappers(), TRUE)) {
|
||||
$this->markTestSkipped('There is no phar stream wrapper registered. PHP is probably compiled without phar support.');
|
||||
}
|
||||
// Ensure that phar is not treated as a valid scheme.
|
||||
$stream_wrapper_manager = $this->container->get('stream_wrapper_manager');
|
||||
$this->assertFalse($stream_wrapper_manager->getViaScheme('phar'));
|
||||
|
||||
// Ensure that calling register again and unregister do not create errors
|
||||
// due to the PharStreamWrapperManager singleton.
|
||||
$stream_wrapper_manager->register();
|
||||
$this->assertContains('public', stream_get_wrappers());
|
||||
$this->assertContains('phar', stream_get_wrappers());
|
||||
$stream_wrapper_manager->unregister();
|
||||
$this->assertNotContains('public', stream_get_wrappers());
|
||||
// This will have reverted to the builtin phar stream wrapper.
|
||||
$this->assertContains('phar', stream_get_wrappers());
|
||||
$stream_wrapper_manager->register();
|
||||
$this->assertContains('public', stream_get_wrappers());
|
||||
$this->assertContains('phar', stream_get_wrappers());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Plugin;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityViewDisplay;
|
||||
use Drupal\Core\Plugin\Context\EntityContext;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the interaction between entity context and typed data.
|
||||
*
|
||||
* @group Context
|
||||
*/
|
||||
class EntityContextTypedDataTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['entity_test'];
|
||||
|
||||
/**
|
||||
* Tests that entity contexts wrapping a config entity can be validated.
|
||||
*/
|
||||
public function testValidateConfigEntityContext() {
|
||||
$display = EntityViewDisplay::create([
|
||||
'targetEntityType' => 'entity_test',
|
||||
'bundle' => 'entity_test',
|
||||
'mode' => 'default',
|
||||
'status' => TRUE,
|
||||
]);
|
||||
$display->save();
|
||||
|
||||
$violations = EntityContext::fromEntity($display)->validate();
|
||||
$this->assertCount(0, $violations);
|
||||
}
|
||||
|
||||
}
|
|
@ -32,6 +32,14 @@ class MessageTest extends KernelTestBase {
|
|||
$this->render($messages);
|
||||
$this->assertRaw('messages messages--error');
|
||||
$this->assertRaw('messages messages--status');
|
||||
// Tests display of only one type of messages.
|
||||
\Drupal::messenger()->addError('An error occurred');
|
||||
$messages = [
|
||||
'#type' => 'status_messages',
|
||||
'#display' => 'error',
|
||||
];
|
||||
$this->render($messages);
|
||||
$this->assertRaw('messages messages--error');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -238,12 +238,6 @@ abstract class BrowserTestBase extends TestCase {
|
|||
'hidden_field_selector' => new HiddenFieldSelector(),
|
||||
]);
|
||||
$session = new Session($driver, $selectors_handler);
|
||||
$cookies = $this->extractCookiesFromRequest(\Drupal::request());
|
||||
foreach ($cookies as $cookie_name => $values) {
|
||||
foreach ($values as $value) {
|
||||
$session->setCookie($cookie_name, $value);
|
||||
}
|
||||
}
|
||||
$this->mink = new Mink();
|
||||
$this->mink->registerSession('default', $session);
|
||||
$this->mink->setDefaultSessionName('default');
|
||||
|
@ -251,6 +245,16 @@ abstract class BrowserTestBase extends TestCase {
|
|||
|
||||
$this->initFrontPage();
|
||||
|
||||
// Copies cookies from the current environment, for example, XDEBUG_SESSION
|
||||
// in order to support Xdebug.
|
||||
// @see BrowserTestBase::initFrontPage()
|
||||
$cookies = $this->extractCookiesFromRequest(\Drupal::request());
|
||||
foreach ($cookies as $cookie_name => $values) {
|
||||
foreach ($values as $value) {
|
||||
$session->setCookie($cookie_name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
|
@ -676,7 +680,7 @@ abstract class BrowserTestBase extends TestCase {
|
|||
* The JSON decoded drupalSettings value from the current page.
|
||||
*/
|
||||
protected function getDrupalSettings() {
|
||||
$html = $this->getSession()->getPage()->getHtml();
|
||||
$html = $this->getSession()->getPage()->getContent();
|
||||
if (preg_match('@<script type="application/json" data-drupal-selector="drupal-settings-json">([^<]*)</script>@', $html, $matches)) {
|
||||
return Json::decode($matches[1]);
|
||||
}
|
||||
|
|
|
@ -330,7 +330,9 @@ class DateTimePlusTest extends TestCase {
|
|||
// Create a date object in the distant past.
|
||||
// @see https://www.drupal.org/node/2795489#comment-12127088
|
||||
if (version_compare(PHP_VERSION, '5.6.15', '>=')) {
|
||||
$dates[] = ['1809-02-12 10:30', 'America/Chicago', '1809-02-12T10:30:00-06:00'];
|
||||
// Note that this date is after the United States standardized its
|
||||
// timezones.
|
||||
$dates[] = ['1883-11-19 10:30', 'America/Chicago', '1883-11-19T10:30:00-06:00'];
|
||||
}
|
||||
// Create a date object in the far future.
|
||||
$dates[] = ['2345-01-02 02:04', 'UTC', '2345-01-02T02:04:00+00:00'];
|
||||
|
@ -366,7 +368,9 @@ class DateTimePlusTest extends TestCase {
|
|||
// Create a date object in the distant past.
|
||||
// @see https://www.drupal.org/node/2795489#comment-12127088
|
||||
if (version_compare(PHP_VERSION, '5.6.15', '>=')) {
|
||||
$dates[] = [['year' => 1809, 'month' => 2, 'day' => 12], 'America/Chicago', '1809-02-12T00:00:00-06:00'];
|
||||
// Note that this date is after the United States standardized its
|
||||
// timezones.
|
||||
$dates[] = [['year' => 1883, 'month' => 11, 'day' => 19], 'America/Chicago', '1883-11-19T00:00:00-06:00'];
|
||||
}
|
||||
// Create a date object in the far future.
|
||||
$dates[] = [['year' => 2345, 'month' => 1, 'day' => 2], 'UTC', '2345-01-02T00:00:00+00:00'];
|
||||
|
|
|
@ -142,8 +142,6 @@ class PhpTransliterationTest extends TestCase {
|
|||
// Test strings in some other languages.
|
||||
// Turkish, provided by drupal.org user Kartagis.
|
||||
['tr', 'Abayı serdiler bize. Söyleyeceğim yüzlerine. Sanırım hepimiz aynı şeyi düşünüyoruz.', 'Abayi serdiler bize. Soyleyecegim yuzlerine. Sanirim hepimiz ayni seyi dusunuyoruz.'],
|
||||
// Illegal/unknown unicode.
|
||||
['en', chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80), '?'],
|
||||
// Max length.
|
||||
['de', $two_byte, 'Ae Oe', '?', 5],
|
||||
];
|
||||
|
@ -164,6 +162,60 @@ class PhpTransliterationTest extends TestCase {
|
|||
$this->assertSame($trunc_output, $transliteration->transliterate($input, 'de', '?', 18), 'Truncating to 18 characters works');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the unknown character replacement.
|
||||
*
|
||||
* @param string $langcode
|
||||
* The language code to test.
|
||||
* @param string $original
|
||||
* The original string.
|
||||
* @param string $expected
|
||||
* The expected return from PhpTransliteration::transliterate().
|
||||
* @param string $unknown_character
|
||||
* The character to substitute for characters in $string without
|
||||
* transliterated equivalents.
|
||||
* @param int $max_length
|
||||
* The maximum length of the string that returns the transliteration.
|
||||
*
|
||||
* @dataProvider providerTestTransliterationUnknownCharacter
|
||||
*/
|
||||
public function testTransliterationUnknownCharacter($langcode, $original, $expected, $unknown_character = '?', $max_length = NULL) {
|
||||
$transliteration = new PhpTransliteration();
|
||||
$actual = $transliteration->transliterate($original, $langcode, $unknown_character, $max_length);
|
||||
$this->assertSame($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for self::testTransliterationUnknownCharacter().
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays, each containing the parameters for
|
||||
* self::testTransliterationUnknownCharacter().
|
||||
*/
|
||||
public function providerTestTransliterationUnknownCharacter() {
|
||||
return [
|
||||
// Each test case is (language code, input, output, unknown character, max
|
||||
// length).
|
||||
|
||||
// Illegal/unknown unicode.
|
||||
['en', chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80), '?????'],
|
||||
['en', chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80), '-----', '-'],
|
||||
['en', 'Hel' . chr(0x80) . 'o World', 'Hel?o World'],
|
||||
['en', 'Hell' . chr(0x80) . ' World', 'Hell? World'],
|
||||
// Non default replacement.
|
||||
['en', chr(0x80) . 'ello World', '_ello World', '_'],
|
||||
// Keep the original question marks.
|
||||
['en', chr(0xF8) . '?' . chr(0x80), '???'],
|
||||
['en', chr(0x80) . 'ello ? World?', '_ello ? World?', '_'],
|
||||
['pl', 'aąeę' . chr(0x80) . 'oółżźz ?', 'aaee?oolzzz ?'],
|
||||
// Non-US-ASCII replacement.
|
||||
['en', chr(0x80) . 'ello World?', 'Oello World?', 'Ö'],
|
||||
['pl', chr(0x80) . 'óóść', 'ooosc', 'ó'],
|
||||
// Ensure question marks are replaced when max length used.
|
||||
['en', chr(0x80) . 'ello ? World?', '_ello ?', '_', 7],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests inclusion is safe.
|
||||
*
|
||||
|
|
60
web/core/tests/Drupal/Tests/Component/Utility/MailTest.php
Normal file
60
web/core/tests/Drupal/Tests/Component/Utility/MailTest.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Utility;
|
||||
|
||||
use Drupal\Component\Utility\Mail;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test mail helpers implemented in Mail component.
|
||||
*
|
||||
* @group Utility
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Component\Utility\Mail
|
||||
*/
|
||||
class MailTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Tests RFC-2822 'display-name' formatter.
|
||||
*
|
||||
* @dataProvider providerTestDisplayName
|
||||
* @covers ::formatDisplayName
|
||||
*/
|
||||
public function testFormatDisplayName($string, $safe_display_name) {
|
||||
$this->assertEquals($safe_display_name, Mail::formatDisplayName($string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testFormatDisplayName().
|
||||
*
|
||||
* @see testFormatDisplayName()
|
||||
*
|
||||
* @return array
|
||||
* An array containing a string and its 'display-name' safe value.
|
||||
*/
|
||||
public function providerTestDisplayName() {
|
||||
return [
|
||||
// Simple ASCII characters.
|
||||
['Test site', 'Test site'],
|
||||
// ASCII with html entity.
|
||||
['Test & site', 'Test & site'],
|
||||
// Non-ASCII characters.
|
||||
['Tést site', '=?UTF-8?B?VMOpc3Qgc2l0ZQ==?='],
|
||||
// Non-ASCII with special characters.
|
||||
['Tést; site', '=?UTF-8?B?VMOpc3Q7IHNpdGU=?='],
|
||||
// Non-ASCII with html entity.
|
||||
['Tést; site', '=?UTF-8?B?VMOpc3Q7IHNpdGU=?='],
|
||||
// ASCII with special characters.
|
||||
['Test; site', '"Test; site"'],
|
||||
// ASCII with special characters as html entity.
|
||||
['Test < site', '"Test < site"'],
|
||||
// ASCII with special characters and '\'.
|
||||
['Test; \ "site"', '"Test; \\\\ \"site\""'],
|
||||
// String already RFC-2822 compliant.
|
||||
['"Test; site"', '"Test; site"'],
|
||||
// String already RFC-2822 compliant.
|
||||
['"Test; \\\\ \"site\""', '"Test; \\\\ \"site\""'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -85,7 +85,15 @@ class QuickStartTest extends TestCase {
|
|||
public function testQuickStartCommand() {
|
||||
// Install a site using the standard profile to ensure the one time login
|
||||
// link generation works.
|
||||
$install_command = "{$this->php} core/scripts/drupal quick-start standard --site-name='Test site {$this->testDb->getDatabasePrefix()}' --suppress-login";
|
||||
|
||||
$install_command = [
|
||||
$this->php,
|
||||
'core/scripts/drupal',
|
||||
'quick-start',
|
||||
'standard',
|
||||
"--site-name='Test site {$this->testDb->getDatabasePrefix()}'",
|
||||
'--suppress-login',
|
||||
];
|
||||
$process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
|
||||
$process->inheritEnvironmentVariables();
|
||||
$process->setTimeout(500);
|
||||
|
@ -129,7 +137,13 @@ class QuickStartTest extends TestCase {
|
|||
*/
|
||||
public function testQuickStartInstallAndServerCommands() {
|
||||
// Install a site.
|
||||
$install_command = "{$this->php} core/scripts/drupal install testing --site-name='Test site {$this->testDb->getDatabasePrefix()}'";
|
||||
$install_command = [
|
||||
$this->php,
|
||||
'core/scripts/drupal',
|
||||
'install',
|
||||
'testing',
|
||||
"--site-name='Test site {$this->testDb->getDatabasePrefix()}'",
|
||||
];
|
||||
$install_process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
|
||||
$install_process->inheritEnvironmentVariables();
|
||||
$install_process->setTimeout(500);
|
||||
|
@ -139,7 +153,12 @@ class QuickStartTest extends TestCase {
|
|||
$this->assertSame(0, $result);
|
||||
|
||||
// Run the PHP built-in webserver.
|
||||
$server_command = "{$this->php} core/scripts/drupal server --suppress-login";
|
||||
$server_command = [
|
||||
$this->php,
|
||||
'core/scripts/drupal',
|
||||
'server',
|
||||
'--suppress-login',
|
||||
];
|
||||
$server_process = new Process($server_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
|
||||
$server_process->inheritEnvironmentVariables();
|
||||
$server_process->start();
|
||||
|
@ -173,7 +192,13 @@ class QuickStartTest extends TestCase {
|
|||
$this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
|
||||
|
||||
// Try to re-install over the top of an existing site.
|
||||
$install_command = "{$this->php} core/scripts/drupal install testing --site-name='Test another site {$this->testDb->getDatabasePrefix()}'";
|
||||
$install_command = [
|
||||
$this->php,
|
||||
'core/scripts/drupal',
|
||||
'install',
|
||||
'testing',
|
||||
"--site-name='Test another site {$this->testDb->getDatabasePrefix()}'",
|
||||
];
|
||||
$install_process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
|
||||
$install_process->inheritEnvironmentVariables();
|
||||
$install_process->setTimeout(500);
|
||||
|
@ -196,7 +221,13 @@ class QuickStartTest extends TestCase {
|
|||
public function testQuickStartCommandProfileValidation() {
|
||||
// Install a site using the standard profile to ensure the one time login
|
||||
// link generation works.
|
||||
$install_command = "{$this->php} core/scripts/drupal quick-start umami --site-name='Test site {$this->testDb->getDatabasePrefix()}' --suppress-login";
|
||||
$install_command = [
|
||||
$this->php,
|
||||
'core/scripts/drupal',
|
||||
'quick-start',
|
||||
'umami',
|
||||
"--site-name='Test site {$this->testDb->getDatabasePrefix()}' --suppress-login",
|
||||
];
|
||||
$process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
|
||||
$process->inheritEnvironmentVariables();
|
||||
$process->run();
|
||||
|
@ -207,7 +238,12 @@ class QuickStartTest extends TestCase {
|
|||
* Tests the server command when there is no installation.
|
||||
*/
|
||||
public function testServerWithNoInstall() {
|
||||
$server_command = "{$this->php} core/scripts/drupal server --suppress-login";
|
||||
$server_command = [
|
||||
$this->php,
|
||||
'core/scripts/drupal',
|
||||
'server',
|
||||
'--suppress-login',
|
||||
];
|
||||
$server_process = new Process($server_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
|
||||
$server_process->inheritEnvironmentVariables();
|
||||
$server_process->run();
|
||||
|
|
|
@ -114,7 +114,7 @@ RSS;
|
|||
$event = new FilterResponseEvent(
|
||||
$this->prophesize(HttpKernelInterface::class)->reveal(),
|
||||
Request::create('/'),
|
||||
'foo',
|
||||
HttpKernelInterface::MASTER_REQUEST,
|
||||
new Response($content, 200, [
|
||||
'Content-Type' => 'application/rss+xml',
|
||||
])
|
||||
|
|
|
@ -12,6 +12,7 @@ use Drupal\Core\Extension\ThemeHandlerInterface;
|
|||
use Drupal\Core\Layout\LayoutDefault;
|
||||
use Drupal\Core\Layout\LayoutDefinition;
|
||||
use Drupal\Core\Layout\LayoutPluginManager;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use Prophecy\Argument;
|
||||
|
@ -114,8 +115,12 @@ class LayoutPluginManagerTest extends UnitTestCase {
|
|||
$theme_a_path = vfsStream::url('root/themes/theme_a');
|
||||
$layout_definition = $this->layoutPluginManager->getDefinition('theme_a_provided_layout');
|
||||
$this->assertSame('theme_a_provided_layout', $layout_definition->id());
|
||||
$this->assertSame('2 column layout', $layout_definition->getLabel());
|
||||
$this->assertSame('Columns: 2', $layout_definition->getCategory());
|
||||
$this->assertSame('2 column layout', (string) $layout_definition->getLabel());
|
||||
$this->assertSame('Columns: 2', (string) $layout_definition->getCategory());
|
||||
$this->assertSame('A theme provided layout', (string) $layout_definition->getDescription());
|
||||
$this->assertTrue($layout_definition->getLabel() instanceof TranslatableMarkup);
|
||||
$this->assertTrue($layout_definition->getCategory() instanceof TranslatableMarkup);
|
||||
$this->assertTrue($layout_definition->getDescription() instanceof TranslatableMarkup);
|
||||
$this->assertSame('twocol', $layout_definition->getTemplate());
|
||||
$this->assertSame("$theme_a_path/templates", $layout_definition->getPath());
|
||||
$this->assertSame('theme_a/twocol', $layout_definition->getLibrary());
|
||||
|
@ -126,19 +131,26 @@ class LayoutPluginManagerTest extends UnitTestCase {
|
|||
$this->assertSame(LayoutDefault::class, $layout_definition->getClass());
|
||||
$expected_regions = [
|
||||
'left' => [
|
||||
'label' => 'Left region',
|
||||
'label' => new TranslatableMarkup('Left region', [], ['context' => 'layout_region']),
|
||||
],
|
||||
'right' => [
|
||||
'label' => 'Right region',
|
||||
'label' => new TranslatableMarkup('Right region', [], ['context' => 'layout_region']),
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected_regions, $layout_definition->getRegions());
|
||||
$regions = $layout_definition->getRegions();
|
||||
$this->assertEquals($expected_regions, $regions);
|
||||
$this->assertTrue($regions['left']['label'] instanceof TranslatableMarkup);
|
||||
$this->assertTrue($regions['right']['label'] instanceof TranslatableMarkup);
|
||||
|
||||
$module_a_path = vfsStream::url('root/modules/module_a');
|
||||
$layout_definition = $this->layoutPluginManager->getDefinition('module_a_provided_layout');
|
||||
$this->assertSame('module_a_provided_layout', $layout_definition->id());
|
||||
$this->assertSame('1 column layout', $layout_definition->getLabel());
|
||||
$this->assertSame('Columns: 1', $layout_definition->getCategory());
|
||||
$this->assertSame('1 column layout', (string) $layout_definition->getLabel());
|
||||
$this->assertSame('Columns: 1', (string) $layout_definition->getCategory());
|
||||
$this->assertSame('A module provided layout', (string) $layout_definition->getDescription());
|
||||
$this->assertTrue($layout_definition->getLabel() instanceof TranslatableMarkup);
|
||||
$this->assertTrue($layout_definition->getCategory() instanceof TranslatableMarkup);
|
||||
$this->assertTrue($layout_definition->getDescription() instanceof TranslatableMarkup);
|
||||
$this->assertSame(NULL, $layout_definition->getTemplate());
|
||||
$this->assertSame("$module_a_path/layouts", $layout_definition->getPath());
|
||||
$this->assertSame('module_a/onecol', $layout_definition->getLibrary());
|
||||
|
@ -149,19 +161,26 @@ class LayoutPluginManagerTest extends UnitTestCase {
|
|||
$this->assertSame(LayoutDefault::class, $layout_definition->getClass());
|
||||
$expected_regions = [
|
||||
'top' => [
|
||||
'label' => 'Top region',
|
||||
'label' => new TranslatableMarkup('Top region', [], ['context' => 'layout_region']),
|
||||
],
|
||||
'bottom' => [
|
||||
'label' => 'Bottom region',
|
||||
'label' => new TranslatableMarkup('Bottom region', [], ['context' => 'layout_region']),
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected_regions, $layout_definition->getRegions());
|
||||
$regions = $layout_definition->getRegions();
|
||||
$this->assertEquals($expected_regions, $regions);
|
||||
$this->assertTrue($regions['top']['label'] instanceof TranslatableMarkup);
|
||||
$this->assertTrue($regions['bottom']['label'] instanceof TranslatableMarkup);
|
||||
|
||||
$core_path = '/core/lib/Drupal/Core';
|
||||
$layout_definition = $this->layoutPluginManager->getDefinition('plugin_provided_layout');
|
||||
$this->assertSame('plugin_provided_layout', $layout_definition->id());
|
||||
$this->assertEquals('Layout plugin', $layout_definition->getLabel());
|
||||
$this->assertEquals('Columns: 1', $layout_definition->getCategory());
|
||||
$this->assertEquals('Test layout', $layout_definition->getDescription());
|
||||
$this->assertTrue($layout_definition->getLabel() instanceof TranslatableMarkup);
|
||||
$this->assertTrue($layout_definition->getCategory() instanceof TranslatableMarkup);
|
||||
$this->assertTrue($layout_definition->getDescription() instanceof TranslatableMarkup);
|
||||
$this->assertSame('plugin-provided-layout', $layout_definition->getTemplate());
|
||||
$this->assertSame($core_path, $layout_definition->getPath());
|
||||
$this->assertSame(NULL, $layout_definition->getLibrary());
|
||||
|
@ -172,10 +191,12 @@ class LayoutPluginManagerTest extends UnitTestCase {
|
|||
$this->assertSame('Drupal\Core\Plugin\Layout\TestLayout', $layout_definition->getClass());
|
||||
$expected_regions = [
|
||||
'main' => [
|
||||
'label' => 'Main Region',
|
||||
'label' => new TranslatableMarkup('Main Region', [], ['context' => 'layout_region']),
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expected_regions, $layout_definition->getRegions());
|
||||
$regions = $layout_definition->getRegions();
|
||||
$this->assertEquals($expected_regions, $regions);
|
||||
$this->assertTrue($regions['main']['label'] instanceof TranslatableMarkup);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,6 +305,7 @@ EOS;
|
|||
module_a_provided_layout:
|
||||
label: 1 column layout
|
||||
category: 'Columns: 1'
|
||||
description: 'A module provided layout'
|
||||
theme_hook: onecol
|
||||
path: layouts
|
||||
library: module_a/onecol
|
||||
|
@ -301,6 +323,7 @@ theme_a_provided_layout:
|
|||
class: '\Drupal\Core\Layout\LayoutDefault'
|
||||
label: 2 column layout
|
||||
category: 'Columns: 2'
|
||||
description: 'A theme provided layout'
|
||||
template: twocol
|
||||
path: templates
|
||||
library: theme_a/twocol
|
||||
|
@ -325,7 +348,7 @@ use Drupal\Core\Layout\LayoutDefault;
|
|||
* template = "templates/plugin-provided-layout",
|
||||
* regions = {
|
||||
* "main" = {
|
||||
* "label" = @Translation("Main Region")
|
||||
* "label" = @Translation("Main Region", context = "layout_region")
|
||||
* }
|
||||
* }
|
||||
* )
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Core\Plugin\Context;
|
||||
|
||||
use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterface;
|
||||
use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface;
|
||||
use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionTrait;
|
||||
use Drupal\Component\Plugin\Definition\PluginDefinition;
|
||||
use Drupal\Component\Plugin\Exception\ContextException;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginBase;
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
use Drupal\Core\TypedData\Plugin\DataType\StringData;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Plugin\ContextAwarePluginBase
|
||||
* @group Plugin
|
||||
*/
|
||||
class ContextAwarePluginBaseTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The plugin instance under test.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\ContextAwarePluginBase
|
||||
*/
|
||||
private $plugin;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->plugin = new TestContextAwarePlugin([], 'the_sisko', new TestPluginDefinition());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getContextDefinitions
|
||||
*/
|
||||
public function testGetContextDefinitions() {
|
||||
$this->assertInternalType('array', $this->plugin->getContextDefinitions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getContextDefinition
|
||||
*/
|
||||
public function testGetContextDefinition() {
|
||||
// The context is not defined, so an exception will be thrown.
|
||||
$this->setExpectedException(ContextException::class, 'The person context is not a valid context.');
|
||||
$this->plugin->getContextDefinition('person');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setContextValue
|
||||
*/
|
||||
public function testSetContextValue() {
|
||||
$typed_data_manager = $this->prophesize(TypedDataManagerInterface::class);
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('typed_data_manager', $typed_data_manager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$this->plugin->getPluginDefinition()->addContextDefinition('foo', new ContextDefinition('string'));
|
||||
|
||||
$this->assertFalse($this->plugin->setContextCalled);
|
||||
$this->plugin->setContextValue('foo', new StringData(new DataDefinition(), 'bar'));
|
||||
$this->assertTrue($this->plugin->setContextCalled);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestPluginDefinition extends PluginDefinition implements ContextAwarePluginDefinitionInterface {
|
||||
|
||||
use ContextAwarePluginDefinitionTrait;
|
||||
|
||||
}
|
||||
|
||||
class TestContextAwarePlugin extends ContextAwarePluginBase {
|
||||
|
||||
/**
|
||||
* Indicates if ::setContext() has been called or not.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $setContextCalled = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setContext($name, ComponentContextInterface $context) {
|
||||
parent::setContext($name, $context);
|
||||
$this->setContextCalled = TRUE;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,17 +6,38 @@ use Drupal\Core\DependencyInjection\ContainerBuilder;
|
|||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\Context\EntityContextDefinition;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
use Drupal\Core\Validation\ConstraintManager;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* Test deprecated use of ContextDefinition as an EntityContextDefinition.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Plugin\Context\ContextDefinition
|
||||
*
|
||||
* @group Plugin
|
||||
* @group legacy
|
||||
*
|
||||
* @see https://www.drupal.org/node/2976400
|
||||
*/
|
||||
class EntityContextDefinitionDeprecationTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The context definition under test.
|
||||
*
|
||||
* @var \Drupal\Core\Plugin\Context\ContextDefinition
|
||||
*/
|
||||
protected $definition;
|
||||
|
||||
/**
|
||||
* The compatibility layer property on the context definition under test.
|
||||
*
|
||||
* @var \ReflectionProperty
|
||||
*/
|
||||
protected $compatibilityLayer;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -24,41 +45,134 @@ class EntityContextDefinitionDeprecationTest extends UnitTestCase {
|
|||
parent::setUp();
|
||||
|
||||
// Mock container services needed for constraint validation.
|
||||
$constraint_manager = $this->prophesize('\Drupal\Core\Validation\ConstraintManager');
|
||||
$constraint_manager = $this->prophesize(ConstraintManager::class);
|
||||
$constraint_manager->create(Argument::type('string'), Argument::any())->willReturn(TRUE);
|
||||
|
||||
$typed_data_manager = $this->prophesize('\Drupal\Core\TypedData\TypedDataManagerInterface');
|
||||
$typed_data_manager = $this->prophesize(TypedDataManagerInterface::class);
|
||||
$typed_data_manager->getValidationConstraintManager()->willReturn($constraint_manager->reveal());
|
||||
|
||||
$validator = $this->prophesize('\Symfony\Component\Validator\Validator\ValidatorInterface')
|
||||
$validator = $this->prophesize(ValidatorInterface::class)
|
||||
->reveal();
|
||||
$typed_data_manager->getValidator()->willReturn($validator);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('typed_data_manager', $typed_data_manager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
|
||||
*/
|
||||
public function testDeprecationNotice() {
|
||||
$definition = new ContextDefinition('entity:node');
|
||||
// Create a deprecated entity context definition and prepare the
|
||||
// compatibility layer to be overridden.
|
||||
$this->definition = new ContextDefinition('entity:node');
|
||||
// The code paths we're testing are private and protected, so use reflection
|
||||
// to manipulate protected properties.
|
||||
$reflector = new \ReflectionObject($definition);
|
||||
$reflector = new \ReflectionObject($this->definition);
|
||||
|
||||
// Ensure that the BC object was created correctly.
|
||||
$this->assertTrue($reflector->hasProperty('entityContextDefinition'));
|
||||
$property = $reflector->getProperty('entityContextDefinition');
|
||||
$property->setAccessible(TRUE);
|
||||
$this->assertInstanceOf(EntityContextDefinition::class, $property->getValue($definition));
|
||||
$this->compatibilityLayer = $reflector->getProperty('entityContextDefinition');
|
||||
$this->compatibilityLayer->setAccessible(TRUE);
|
||||
$this->assertInstanceOf(EntityContextDefinition::class, $this->compatibilityLayer->getValue($this->definition));
|
||||
}
|
||||
|
||||
// Ensure that getConstraintObjects() adds the EntityType constraint.
|
||||
$method = $reflector->getMethod('getConstraintObjects');
|
||||
$method->setAccessible(TRUE);
|
||||
$this->assertArrayHasKey('EntityType', $method->invoke($definition));
|
||||
/**
|
||||
* Test that the BC layer survives serialization and unserialization.
|
||||
*
|
||||
* @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
|
||||
*/
|
||||
public function testSerialization() {
|
||||
$definition = unserialize(serialize($this->definition));
|
||||
$bc_layer = $this->compatibilityLayer->getValue($definition);
|
||||
$this->assertInstanceOf(EntityContextDefinition::class, $bc_layer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getConstraints() proxies to the compatibility layer.
|
||||
*
|
||||
* @covers ::getConstraints
|
||||
* @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
|
||||
*/
|
||||
public function testGetConstraints() {
|
||||
$bc_mock = $this->getMockBuilder(EntityContextDefinition::class)
|
||||
->setMethods(['getConstraints'])
|
||||
->getMock();
|
||||
|
||||
$constraints = ['test_constraint'];
|
||||
$bc_mock->expects($this->once())
|
||||
->method('getConstraints')
|
||||
->willReturn($constraints);
|
||||
$this->compatibilityLayer->setValue($this->definition, $bc_mock);
|
||||
|
||||
$this->assertSame($constraints, $this->definition->getConstraints());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getConstraint() proxies to the compatibility layer.
|
||||
*
|
||||
* @covers ::getConstraint
|
||||
* @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
|
||||
*/
|
||||
public function testGetConstraint() {
|
||||
$bc_mock = $this->getMockBuilder(EntityContextDefinition::class)
|
||||
->setMethods(['getConstraint'])
|
||||
->getMock();
|
||||
|
||||
$bc_mock->expects($this->once())
|
||||
->method('getConstraint')
|
||||
->with('constraint_name')
|
||||
->willReturn('test_constraint');
|
||||
$this->compatibilityLayer->setValue($this->definition, $bc_mock);
|
||||
|
||||
$this->assertSame('test_constraint', $this->definition->getConstraint('constraint_name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that setConstraints() proxies to the compatibility layer.
|
||||
*
|
||||
* @covers ::setConstraints
|
||||
* @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
|
||||
*/
|
||||
public function testSetConstraints() {
|
||||
$bc_mock = $this->getMockBuilder(EntityContextDefinition::class)
|
||||
->setMethods(['setConstraints'])
|
||||
->getMock();
|
||||
|
||||
$constraints = ['TestConstraint' => []];
|
||||
$bc_mock->expects($this->once())
|
||||
->method('setConstraints')
|
||||
->with($constraints)
|
||||
->willReturnSelf();
|
||||
$this->compatibilityLayer->setValue($this->definition, $bc_mock);
|
||||
|
||||
$this->assertSame($this->definition, $this->definition->setConstraints($constraints));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that addConstraint() proxies to the compatibility layer.
|
||||
*
|
||||
* @covers ::addConstraint
|
||||
* @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
|
||||
*/
|
||||
public function testAddConstraint() {
|
||||
$bc_mock = $this->getMockBuilder(EntityContextDefinition::class)
|
||||
->setMethods(['addConstraint'])
|
||||
->getMock();
|
||||
|
||||
$options = ['options'];
|
||||
$bc_mock->expects($this->once())
|
||||
->method('addConstraint')
|
||||
->with('constraint_name', $options)
|
||||
->willReturnSelf();
|
||||
$this->compatibilityLayer->setValue($this->definition, $bc_mock);
|
||||
|
||||
$this->assertSame($this->definition, $this->definition->addConstraint('constraint_name', $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that isSatisfiedBy() calls the compatibility layer.
|
||||
*
|
||||
* @covers ::isSatisfiedBy
|
||||
* @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
|
||||
*/
|
||||
public function testIsSatisfiedBy() {
|
||||
// Ensure that the BC object's getSampleValues() method is called during
|
||||
// validation.
|
||||
$bc_mock = $this->getMockBuilder(EntityContextDefinition::class)
|
||||
|
@ -68,12 +182,21 @@ class EntityContextDefinitionDeprecationTest extends UnitTestCase {
|
|||
$bc_mock->expects($this->atLeastOnce())
|
||||
->method('getSampleValues')
|
||||
->willReturn([]);
|
||||
$property->setValue($definition, $bc_mock);
|
||||
$definition->isSatisfiedBy(new Context($definition));
|
||||
$this->compatibilityLayer->setValue($this->definition, $bc_mock);
|
||||
$this->definition->isSatisfiedBy(new Context($this->definition));
|
||||
}
|
||||
|
||||
// Ensure that the BC layer survives serialization and unserialization.
|
||||
$definition = unserialize(serialize($definition));
|
||||
$this->assertInstanceOf(EntityContextDefinition::class, $property->getValue($definition));
|
||||
/**
|
||||
* Test that getConstraintObjects() adds the EntityType constraint.
|
||||
*
|
||||
* @covers ::getConstraintObjects
|
||||
* @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
|
||||
*/
|
||||
public function testGetConstraintObjects() {
|
||||
$reflector = new \ReflectionObject($this->definition);
|
||||
$method = $reflector->getMethod('getConstraintObjects');
|
||||
$method->setAccessible(TRUE);
|
||||
$this->assertArrayHasKey('EntityType', $method->invoke($this->definition));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
60
web/core/tests/Drupal/Tests/Core/Routing/RouterTest.php
Normal file
60
web/core/tests/Drupal/Tests/Core/Routing/RouterTest.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Core\Routing;
|
||||
|
||||
use Drupal\Core\Path\CurrentPathStack;
|
||||
use Drupal\Core\Routing\RequestContext;
|
||||
use Drupal\Core\Routing\RouteCompiler;
|
||||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\Core\Routing\Router;
|
||||
use Drupal\Core\Routing\UrlGeneratorInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Prophecy\Argument;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Routing\Router
|
||||
* @group Routing
|
||||
*/
|
||||
class RouterTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::applyFitOrder
|
||||
*/
|
||||
public function testMatchesWithDifferentFitOrder() {
|
||||
$route_provider = $this->prophesize(RouteProviderInterface::class);
|
||||
|
||||
$route_collection = new RouteCollection();
|
||||
|
||||
$route = new Route('/user/{user}');
|
||||
$route->setOption('compiler_class', RouteCompiler::class);
|
||||
$route_collection->add('user_view', $route);
|
||||
|
||||
$route = new Route('/user/login');
|
||||
$route->setOption('compiler_class', RouteCompiler::class);
|
||||
$route_collection->add('user_login', $route);
|
||||
|
||||
$route_provider->getRouteCollectionForRequest(Argument::any())
|
||||
->willReturn($route_collection);
|
||||
|
||||
$url_generator = $this->prophesize(UrlGeneratorInterface::class);
|
||||
$current_path_stack = $this->prophesize(CurrentPathStack::class);
|
||||
$router = new Router($route_provider->reveal(), $current_path_stack->reveal(), $url_generator->reveal());
|
||||
|
||||
$request_context = $this->prophesize(RequestContext::class);
|
||||
$request_context->getScheme()->willReturn('http');
|
||||
$router->setContext($request_context->reveal());
|
||||
|
||||
$current_path_stack->getPath(Argument::any())->willReturn('/user/1');
|
||||
$result = $router->match('/user/1');
|
||||
|
||||
$this->assertEquals('user_view', $result['_route']);
|
||||
|
||||
$current_path_stack->getPath(Argument::any())->willReturn('/user/login');
|
||||
$result = $router->match('/user/login');
|
||||
|
||||
$this->assertEquals('user_login', $result['_route']);
|
||||
}
|
||||
|
||||
}
|
|
@ -167,27 +167,12 @@ trait UiHelperTrait {
|
|||
* @todo change $edit to disallow NULL as a value for Drupal 9.
|
||||
* https://www.drupal.org/node/2802401
|
||||
* @param string $submit
|
||||
* Value of the submit button whose click is to be emulated. For example,
|
||||
* 'Save'. The processing of the request depends on this value. For example,
|
||||
* a form may have one button with the value 'Save' and another button with
|
||||
* the value 'Delete', and execute different code depending on which one is
|
||||
* clicked.
|
||||
*
|
||||
* This function can also be called to emulate an Ajax submission. In this
|
||||
* case, this value needs to be an array with the following keys:
|
||||
* - path: A path to submit the form values to for Ajax-specific processing.
|
||||
* - triggering_element: If the value for the 'path' key is a generic Ajax
|
||||
* processing path, this needs to be set to the name of the element. If
|
||||
* the name doesn't identify the element uniquely, then this should
|
||||
* instead be an array with a single key/value pair, corresponding to the
|
||||
* element name and value. The \Drupal\Core\Form\FormAjaxResponseBuilder
|
||||
* uses this to find the #ajax information for the element, including
|
||||
* which specific callback to use for processing the request.
|
||||
*
|
||||
* This can also be set to NULL in order to emulate an Internet Explorer
|
||||
* submission of a form with a single text field, and pressing ENTER in that
|
||||
* textfield: under these conditions, no button information is added to the
|
||||
* POST data.
|
||||
* The id, name, label or value of the submit button which is to be clicked.
|
||||
* For example, 'Save'. The first element matched by
|
||||
* \Drupal\Tests\WebAssert::buttonExists() will be used. The processing of
|
||||
* the request depends on this value. For example, a form may have one
|
||||
* button with the value 'Save' and another button with the value 'Delete',
|
||||
* and execute different code depending on which one is clicked.
|
||||
* @param array $options
|
||||
* Options to be forwarded to the url generator.
|
||||
* @param string|null $form_html_id
|
||||
|
@ -202,6 +187,8 @@ trait UiHelperTrait {
|
|||
* (deprecated) The response content after submit form. It is necessary for
|
||||
* backwards compatibility and will be removed before Drupal 9.0. You should
|
||||
* just use the webAssert object for your assertions.
|
||||
*
|
||||
* @see \Drupal\Tests\WebAssert::buttonExists()
|
||||
*/
|
||||
protected function drupalPostForm($path, $edit, $submit, array $options = [], $form_html_id = NULL) {
|
||||
if (is_object($submit)) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Tests;
|
||||
|
||||
use Behat\Mink\Exception\ExpectationException;
|
||||
use Behat\Mink\Exception\ResponseTextException;
|
||||
use Behat\Mink\WebAssert as MinkWebAssert;
|
||||
use Behat\Mink\Element\TraversableElement;
|
||||
use Behat\Mink\Exception\ElementNotFoundException;
|
||||
|
@ -545,4 +546,31 @@ class WebAssert extends MinkWebAssert {
|
|||
$this->assert(!preg_match($regex, $actual), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that current page contains text only once.
|
||||
*
|
||||
* @param string $text
|
||||
* The string to look for.
|
||||
*
|
||||
* @see \Behat\Mink\WebAssert::pageTextContains()
|
||||
*/
|
||||
public function pageTextContainsOnce($text) {
|
||||
$actual = $this->session->getPage()->getText();
|
||||
$actual = preg_replace('/\s+/u', ' ', $actual);
|
||||
$regex = '/' . preg_quote($text, '/') . '/ui';
|
||||
$count = preg_match_all($regex, $actual);
|
||||
if ($count === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($count > 1) {
|
||||
$message = sprintf('The text "%s" appears in the text of this page more than once, but it should not.', $text);
|
||||
}
|
||||
else {
|
||||
$message = sprintf('The text "%s" was not found anywhere in the text of the current page.', $text);
|
||||
}
|
||||
|
||||
throw new ResponseTextException($message, $this->session->getDriver());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue