composer update

This commit is contained in:
Oliver Davies 2019-01-24 08:00:03 +00:00
parent f6abc3dce2
commit 71dfaca858
1753 changed files with 45274 additions and 14619 deletions

View file

@ -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.');
}
}

View file

@ -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');
}
}

View file

@ -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('&#039;');
$this->assertNoRaw('&amp;#039;');
}
/**
* Tests uncaught exception handling with custom exception handler.
*/

View file

@ -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']);

View file

@ -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();
}

View file

@ -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}');

View file

@ -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));
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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));
}
}

View file

@ -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");
}
}

View file

@ -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());
}
}

View file

@ -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);
}
}

View file

@ -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');
}
}

View file

@ -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]);
}

View file

@ -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'];

View file

@ -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.
*

View 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 &amp; 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&eacute;st; site', '=?UTF-8?B?VMOpc3Q7IHNpdGU=?='],
// ASCII with special characters.
['Test; site', '"Test; site"'],
// ASCII with special characters as html entity.
['Test &lt; 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\""'],
];
}
}

View file

@ -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();

View file

@ -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',
])

View file

@ -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")
* }
* }
* )

View file

@ -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;
}
}

View file

@ -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));
}
}

View 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']);
}
}

View file

@ -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)) {

View file

@ -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());
}
}