updated core to 8.6.3

This commit is contained in:
2018-11-21 12:49:46 +01:00
parent 8ca34853a3
commit c92c348eee
521 changed files with 12199 additions and 4578 deletions
@@ -0,0 +1,130 @@
<?php
namespace Drupal\FunctionalJavascriptTests\Ajax;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Performs tests on AJAX framework commands.
*
* @group Ajax
*/
class CommandsTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'ajax_test', 'ajax_forms_test'];
/**
* Tests the various Ajax Commands.
*/
public function testAjaxCommands() {
$session = $this->getSession();
$page = $this->getSession()->getPage();
$form_path = 'ajax_forms_test_ajax_commands_form';
$web_user = $this->drupalCreateUser(['access content']);
$this->drupalLogin($web_user);
$this->drupalGet($form_path);
// Tests the 'add_css' command.
$page->pressButton("AJAX 'add_css' command");
$this->assertWaitPageContains('my/file.css');
// Tests the 'after' command.
$page->pressButton("AJAX 'After': Click to put something after the div");
$this->assertWaitPageContains('<div id="after_div">Something can be inserted after this</div>This will be placed after');
// Tests the 'alert' command.
$test_alert_command = <<<JS
window.alert = function() {
document.body.innerHTML += '<div class="alert-command">Alert</div>';
};
JS;
$session->executeScript($test_alert_command);
$page->pressButton("AJAX 'Alert': Click to alert");
$this->assertWaitPageContains('<div class="alert-command">Alert</div>');
// Tests the 'append' command.
$page->pressButton("AJAX 'Append': Click to append something");
$this->assertWaitPageContains('<div id="append_div">Append inside this divAppended text</div>');
// Tests the 'before' command.
$page->pressButton("AJAX 'before': Click to put something before the div");
$this->assertWaitPageContains('Before text<div id="before_div">Insert something before this.</div>');
// Tests the 'changed' command.
$page->pressButton("AJAX changed: Click to mark div changed.");
$this->assertWaitPageContains('<div id="changed_div" class="ajax-changed">');
// Tests the 'changed' command using the second argument.
// Refresh page for testing 'changed' command to same element again.
$this->drupalGet($form_path);
$page->pressButton("AJAX changed: Click to mark div changed with asterisk.");
$this->assertWaitPageContains('<div id="changed_div" class="ajax-changed"> <div id="changed_div_mark_this">This div can be marked as changed or not. <abbr class="ajax-changed" title="Changed">*</abbr> </div></div>');
// Tests the 'css' command.
$page->pressButton("Set the '#box' div to be blue.");
$this->assertWaitPageContains('<div id="css_div" style="background-color: blue;">');
// Tests the 'data' command.
$page->pressButton("AJAX data command: Issue command.");
$this->assertTrue($page->waitFor(10, function () use ($session) {
return 'testvalue' === $session->evaluateScript('window.jQuery("#data_div").data("testkey")');
}));
// Tests the 'html' command.
$page->pressButton("AJAX html: Replace the HTML in a selector.");
$this->assertWaitPageContains('<div id="html_div">replacement text</div>');
// Tests the 'insert' command.
$page->pressButton("AJAX insert: Let client insert based on #ajax['method'].");
$this->assertWaitPageContains('<div id="insert_div">insert replacement textOriginal contents</div>');
// Tests the 'invoke' command.
$page->pressButton("AJAX invoke command: Invoke addClass() method.");
$this->assertWaitPageContains('<div id="invoke_div" class="error">Original contents</div>');
// Tests the 'prepend' command.
$page->pressButton("AJAX 'prepend': Click to prepend something");
$this->assertWaitPageContains('<div id="prepend_div">prepended textSomething will be prepended to this div. </div>');
// Tests the 'remove' command.
$page->pressButton("AJAX 'remove': Click to remove text");
$this->assertWaitPageContains('<div id="remove_div"></div>');
// Tests the 'restripe' command.
$page->pressButton("AJAX 'restripe' command");
$this->assertWaitPageContains('<tr id="table-first" class="odd"><td>first row</td></tr>');
$this->assertWaitPageContains('<tr class="even"><td>second row</td></tr>');
// Tests the 'settings' command.
$test_settings_command = <<<JS
Drupal.behaviors.testSettingsCommand = {
attach: function (context, settings) {
window.jQuery('body').append('<div class="test-settings-command">' + settings.ajax_forms_test.foo + '</div>');
}
};
JS;
$session->executeScript($test_settings_command);
// @todo: Replace after https://www.drupal.org/project/drupal/issues/2616184
$session->executeScript('window.jQuery("#edit-settings-command-example").mousedown();');
$this->assertWaitPageContains('<div class="test-settings-command">42</div>');
}
/**
* Asserts that page contains a text after waiting.
*
* @param string $text
* A needle text.
*/
protected function assertWaitPageContains($text) {
$page = $this->getSession()->getPage();
$page->waitFor(10, function () use ($page, $text) {
return stripos($page->getContent(), $text) !== FALSE;
});
$this->assertContains($text, $page->getContent());
}
}
@@ -0,0 +1,167 @@
<?php
namespace Drupal\FunctionalJavascriptTests\Ajax;
use Drupal\ajax_test\Controller\AjaxTestController;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Performs tests on opening and manipulating dialogs via AJAX commands.
*
* @group Ajax
*/
class DialogTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['ajax_test', 'ajax_forms_test', 'contact'];
/**
* Test sending non-JS and AJAX requests to open and manipulate modals.
*/
public function testDialog() {
$this->drupalLogin($this->drupalCreateUser(['administer contact forms']));
// Ensure the elements render without notices or exceptions.
$this->drupalGet('ajax-test/dialog');
// Set up variables for this test.
$dialog_renderable = AjaxTestController::dialogContents();
$dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable);
// Check that requesting a modal dialog without JS goes to a page.
$this->drupalGet('ajax-test/dialog-contents');
$this->assertSession()->responseContains($dialog_contents);
// Visit the page containing the many test dialog links.
$this->drupalGet('ajax-test/dialog');
// Tests a basic modal dialog by verifying the contents of the dialog are as
// expected.
$this->getSession()->getPage()->clickLink('Link 1 (modal)');
// Clicking the link triggers a AJAX request/response.
// Opens a Dialog panel.
$link1_dialog_div = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
$this->assertNotNull($link1_dialog_div, 'Link was used to open a dialog ( modal )');
$link1_modal = $link1_dialog_div->find('css', '#drupal-modal');
$this->assertNotNull($link1_modal, 'Link was used to open a dialog ( non-modal )');
$this->assertSession()->responseContains($dialog_contents);
$dialog_title = $link1_dialog_div->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')");
$this->assertNotNull($dialog_title);
$dialog_title_amp = $link1_dialog_div->find('css', "span.ui-dialog-title:contains('AJAX Dialog &amp; contents')");
$this->assertNull($dialog_title_amp);
// Close open dialog, return to the dialog links page.
$close_button = $link1_dialog_div->findButton('Close');
$this->assertNotNull($close_button);
$close_button->press();
// Tests a modal with a dialog-option.
// Link 2 is similar to Link 1, except it submits additional width
// information which must be echoed in the resulting DOM update.
$this->getSession()->getPage()->clickLink('Link 2 (modal)');
$dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
$this->assertNotNull($dialog, 'Link was used to open a dialog ( non-modal, with options )');
$style = $dialog->getAttribute('style');
$this->assertContains('width: 400px;', $style, new FormattableMarkup('Modal respected the dialog-options width parameter. Style = style', ['%style' => $style]));
// Reset: Return to the dialog links page.
$this->drupalGet('ajax-test/dialog');
// Test a non-modal dialog ( with target ).
$this->clickLink('Link 3 (non-modal)');
$non_modal_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
$this->assertNotNull($non_modal_dialog, 'Link opens a non-modal dialog.');
// Tests the dialog contains a target element specified in the AJAX request.
$non_modal_dialog->find('css', 'div#ajax-test-dialog-wrapper-1');
$this->assertSession()->responseContains($dialog_contents);
// Reset: Return to the dialog links page.
$this->drupalGet('ajax-test/dialog');
// Tests a non-modal dialog ( without target ).
$this->clickLink('Link 7 (non-modal, no target)');
$no_target_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
$this->assertNotNull($no_target_dialog, 'Link opens a non-modal dialog.');
$contents_no_target = $no_target_dialog->find('css', 'div.ui-dialog-content');
$this->assertNotNull($contents_no_target, 'non-modal dialog opens ( no target ). ');
$id = $contents_no_target->getAttribute('id');
$partial_match = strpos($id, 'drupal-dialog-ajax-testdialog-contents') === 0;
$this->assertTrue($partial_match, 'The non-modal ID has the expected prefix.');
$no_target_button = $no_target_dialog->findButton('Close');
$this->assertNotNull($no_target_button, 'Link dialog has a close button');
$no_target_button->press();
$this->getSession()->getPage()->findButton('Button 1 (modal)')->press();
$button1_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
$this->assertNotNull($button1_dialog, 'Button opens a modal dialog.');
$button1_dialog_content = $button1_dialog->find('css', 'div.ui-dialog-content');
$this->assertNotNull($button1_dialog_content, 'Button opens a modal dialog.');
// Test the HTML escaping of & character.
$button1_dialog_title = $button1_dialog->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')");
$this->assertNotNull($button1_dialog_title);
$button1_dialog_title_amp = $button1_dialog->find('css', "span.ui-dialog-title:contains('AJAX Dialog &amp; contents')");
$this->assertNull($button1_dialog_title_amp);
// Reset: Close the dialog.
$button1_dialog->findButton('Close')->press();
// Abbreviated test for "normal" dialogs, testing only the difference.
$this->getSession()->getPage()->findButton('Button 2 (non-modal)')->press();
$button2_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog-content');
$this->assertNotNull($button2_dialog, 'Non-modal content displays as expected.');
// Use a link to close the pagnel opened by button 2.
$this->getSession()->getPage()->clickLink('Link 4 (close non-modal if open)');
// Form modal.
$this->clickLink('Link 5 (form)');
// Two links have been clicked in succession - This time wait for a change
// in the title as the previous closing dialog may temporarily be open.
$form_dialog_title = $this->assertSession()->waitForElementVisible('css', "span.ui-dialog-title:contains('Ajax Form contents')");
$this->assertNotNull($form_dialog_title, 'Dialog form has the expected title.');
// Locate the newly opened dialog.
$form_dialog = $this->getSession()->getPage()->find('css', 'div.ui-dialog');
$this->assertNotNull($form_dialog, 'Form dialog is visible');
$form_contents = $form_dialog->find('css', "p:contains('Ajax Form contents description.')");
$this->assertNotNull($form_contents, 'For has the expected text.');
$do_it = $form_dialog->findButton('Do it');
$this->assertNotNull($do_it, 'The dialog has a "Do it" button.');
$preview = $form_dialog->findButton('Preview');
$this->assertNotNull($preview, 'The dialog contains a "Preview" button.');
// Reset: close the form.
$form_dialog->findButton('Close')->press();
// Non AJAX version of Link 6.
$this->drupalGet('admin/structure/contact/add');
// Check we get a chunk of the code, we can't test the whole form as form
// build id and token with be different.
$contact_form = $this->xpath("//form[@id='contact-form-add-form']");
$this->assertTrue(!empty($contact_form), 'Non-JS entity form page present.');
// Reset: Return to the dialog links page.
$this->drupalGet('ajax-test/dialog');
$this->clickLink('Link 6 (entity form)');
$dialog_add = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog');
$this->assertNotNull($dialog_add, 'Form dialog is visible');
$form_add = $dialog_add->find('css', 'form.contact-form-add-form');
$this->assertNotNull($form_add, 'Modal dialog JSON contains entity form.');
$form_title = $dialog_add->find('css', "span.ui-dialog-title:contains('Add contact form')");
$this->assertNotNull($form_title, 'The add form title is as expected.');
}
}
@@ -0,0 +1,139 @@
<?php
namespace Drupal\FunctionalJavascriptTests\Ajax;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Tests that AJAX-enabled forms work when multiple instances of the same form
* are on a page.
*
* @group Ajax
*/
class MultiFormTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'form_test'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Page']);
// Create a multi-valued field for 'page' nodes to use for Ajax testing.
$field_name = 'field_ajax_test';
FieldStorageConfig::create([
'entity_type' => 'node',
'field_name' => $field_name,
'type' => 'text',
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
])->save();
FieldConfig::create([
'field_name' => $field_name,
'entity_type' => 'node',
'bundle' => 'page',
])->save();
entity_get_form_display('node', 'page', 'default')
->setComponent($field_name, ['type' => 'text_textfield'])
->save();
// Log in a user who can create 'page' nodes.
$this->drupalLogin($this->drupalCreateUser(['create page content']));
}
/**
* Tests that pages with the 'node_page_form' included twice work correctly.
*/
public function testMultiForm() {
// HTML IDs for elements within the field are potentially modified with
// each Ajax submission, but these variables are stable and help target the
// desired elements.
$field_name = 'field_ajax_test';
$form_xpath = '//form[starts-with(@id, "node-page-form")]';
$field_xpath = '//div[contains(@class, "field--name-field-ajax-test")]';
$button_name = $field_name . '_add_more';
$button_value = t('Add another item');
$button_xpath_suffix = '//input[@name="' . $button_name . '"]';
$field_items_xpath_suffix = '//input[@type="text"]';
// Ensure the initial page contains both node forms and the correct number
// of field items and "add more" button for the multi-valued field within
// each form.
$this->drupalGet('form-test/two-instances-of-same-form');
// Wait for javascript on the page to prepare the form attributes.
$this->assertSession()->assertWaitOnAjaxRequest();
$session = $this->getSession();
$page = $session->getPage();
$fields = $page->findAll('xpath', $form_xpath . $field_xpath);
$this->assertEqual(count($fields), 2);
foreach ($fields as $field) {
$this->assertCount(1, $field->findAll('xpath', '.' . $field_items_xpath_suffix), 'Found the correct number of field items on the initial page.');
$this->assertFieldsByValue($field->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button on the initial page.');
}
$this->assertNoDuplicateIds();
// Submit the "add more" button of each form twice. After each corresponding
// page update, ensure the same as above.
for ($i = 0; $i < 2; $i++) {
$forms = $page->find('xpath', $form_xpath);
foreach ($forms as $offset => $form) {
$button = $form->findButton($button_value);
$this->assertNotNull($button, 'Add Another Item button exists');
$button->press();
// Wait for page update.
$this->assertSession()->assertWaitOnAjaxRequest();
// After AJAX request and response page will update.
$page_updated = $session->getPage();
$field = $page_updated->findAll('xpath', '.' . $field_xpath);
$this->assertEqual(count($field[0]->find('xpath', '.' . $field_items_xpath_suffix)), $i + 2, 'Found the correct number of field items after an AJAX submission.');
$this->assertFieldsByValue($field[0]->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button after an AJAX submission.');
$this->assertNoDuplicateIds();
}
}
}
/**
* Asserts that each HTML ID is used for just a single element on the page.
*
* @param string $message
* (optional) A message to display with the assertion.
*/
protected function assertNoDuplicateIds($message = '') {
$args = ['@url' => $this->getUrl()];
if (!$elements = $this->xpath('//*[@id]')) {
$this->fail(new FormattableMarkup('The page @url contains no HTML IDs.', $args));
return;
}
$message = $message ?: new FormattableMarkup('The page @url does not contain duplicate HTML IDs', $args);
$seen_ids = [];
foreach ($elements as $element) {
$id = $element->getAttribute('id');
if (isset($seen_ids[$id])) {
$this->fail($message);
return;
}
$seen_ids[$id] = TRUE;
}
$this->assertTrue(TRUE, $message);
}
}
@@ -2,10 +2,10 @@
namespace Drupal\FunctionalJavascriptTests\EntityReference;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\simpletest\ContentTypeCreationTrait;
use Drupal\simpletest\NodeCreationTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
/**
* Tests the output of entity reference autocomplete widgets.
@@ -576,7 +576,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
$this->assertFieldChecked('edit-checkbox-enabled');
$this->assertNoFieldChecked('edit-checkbox-disabled');
// Test that the assertion fails correctly with non-existant field id.
// Test that the assertion fails correctly with non-existent field id.
try {
$this->assertNoFieldChecked('incorrect_checkbox_id');
$this->fail('The "incorrect_checkbox_id" field was found');
@@ -0,0 +1,122 @@
<?php
namespace Drupal\FunctionalTests\Datetime;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the functionality of TimestampAgoFormatter core field formatter.
*
* @group field
*/
class TimestampAgoFormatterTest extends BrowserTestBase {
/**
* An array of display options to pass to entity_get_display().
*
* @var array
*/
protected $displayOptions;
/**
* A field storage to use in this test class.
*
* @var \Drupal\field\Entity\FieldStorageConfig
*/
protected $fieldStorage;
/**
* The field used in this test class.
*
* @var \Drupal\field\Entity\FieldConfig
*/
protected $field;
/**
* {@inheritdoc}
*/
public static $modules = ['entity_test', 'field_ui'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$web_user = $this->drupalCreateUser([
'access administration pages',
'view test entity',
'administer entity_test content',
'administer entity_test fields',
'administer entity_test display',
'administer entity_test form display',
'view the administration theme',
]);
$this->drupalLogin($web_user);
$field_name = 'field_timestamp';
$type = 'timestamp';
$widget_type = 'datetime_timestamp';
$formatter_type = 'timestamp_ago';
$this->fieldStorage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
'type' => $type,
]);
$this->fieldStorage->save();
$this->field = FieldConfig::create([
'field_storage' => $this->fieldStorage,
'bundle' => 'entity_test',
'required' => TRUE,
]);
$this->field->save();
EntityFormDisplay::load('entity_test.entity_test.default')
->setComponent($field_name, ['type' => $widget_type])
->save();
$this->displayOptions = [
'type' => $formatter_type,
'label' => 'hidden',
];
EntityViewDisplay::create([
'targetEntityType' => $this->field->getTargetEntityTypeId(),
'bundle' => $this->field->getTargetBundle(),
'mode' => 'full',
'status' => TRUE,
])->setComponent($field_name, $this->displayOptions)
->save();
}
/**
* Tests the formatter settings.
*/
public function testSettings() {
$this->drupalGet('entity_test/structure/entity_test/display');
$edit = [
'fields[field_timestamp][region]' => 'content',
'fields[field_timestamp][type]' => 'timestamp_ago',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->drupalPostForm(NULL, [], 'field_timestamp_settings_edit');
$edit = [
'fields[field_timestamp][settings_edit_form][settings][future_format]' => 'ends in @interval',
'fields[field_timestamp][settings_edit_form][settings][past_format]' => 'started @interval ago',
'fields[field_timestamp][settings_edit_form][settings][granularity]' => 3,
];
$this->drupalPostForm(NULL, $edit, 'Update');
$this->drupalPostForm(NULL, [], 'Save');
$this->assertSession()->pageTextContains('ends in 1 year 1 month 1 week');
$this->assertSession()->pageTextContains('started 1 year 1 month 1 week ago');
}
}
@@ -69,7 +69,7 @@ class InstallerExistingSettingsMismatchProfileTest extends InstallerTestBase {
* {@inheritdoc}
*/
protected function setUpLanguage() {
// This step is skipped, because there is a lagcode as a query param.
// This step is skipped, because there is a langcode as a query param.
}
/**
@@ -0,0 +1,38 @@
<?php
namespace Drupal\FunctionalTests\Installer;
/**
* Tests that an install profile can implement hook_requirements().
*
* @group Installer
*/
class InstallerProfileRequirementsTest extends InstallerTestBase {
/**
* {@inheritdoc}
*/
protected $profile = 'testing_requirements';
/**
* {@inheritdoc}
*/
protected function setUpSettings() {
// This form will never be reached.
}
/**
* {@inheritdoc}
*/
protected function setUpSite() {
// This form will never be reached.
}
/**
* Assert that the profile failed hook_requirements().
*/
public function testHookRequirementsFailure() {
$this->assertSession()->pageTextContains('Testing requirements failed requirements.');
}
}
@@ -2,14 +2,9 @@
namespace Drupal\FunctionalTests\Update;
use Behat\Mink\Driver\GoutteDriver;
use Behat\Mink\Mink;
use Behat\Mink\Selector\SelectorsHandler;
use Behat\Mink\Session;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Test\TestRunnerKernel;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\HiddenFieldSelector;
use Drupal\Tests\SchemaCheckTestTrait;
use Drupal\Core\Database\Database;
use Drupal\Core\DependencyInjection\ContainerBuilder;
@@ -197,14 +192,7 @@ abstract class UpdatePathTestBase extends BrowserTestBase {
require_once $this->root . '/core/includes/update.inc';
// Setup Mink.
$session = $this->initMink();
$cookies = $this->extractCookiesFromRequest(\Drupal::request());
foreach ($cookies as $cookie_name => $values) {
foreach ($values as $value) {
$session->setCookie($cookie_name, $value);
}
}
$this->initMink();
// Set up the browser test output file.
$this->initBrowserOutputFile();
@@ -244,37 +232,8 @@ abstract class UpdatePathTestBase extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected function initMink() {
$driver = $this->getDefaultDriverInstance();
if ($driver instanceof GoutteDriver) {
// Turn off curl timeout. Having a timeout is not a problem in a normal
// test running, but it is a problem when debugging. Also, disable SSL
// peer verification so that testing under HTTPS always works.
/** @var \GuzzleHttp\Client $client */
$client = $this->container->get('http_client_factory')->fromOptions([
'timeout' => NULL,
'verify' => FALSE,
]);
// Inject a Guzzle middleware to generate debug output for every request
// performed in the test.
$handler_stack = $client->getConfig('handler');
$handler_stack->push($this->getResponseLogHandler());
$driver->getClient()->setClient($client);
}
$selectors_handler = new SelectorsHandler([
'hidden_field_selector' => new HiddenFieldSelector(),
]);
$session = new Session($driver, $selectors_handler);
$this->mink = new Mink();
$this->mink->registerSession('default', $session);
$this->mink->setDefaultSessionName('default');
$this->registerSessions();
return $session;
protected function initFrontPage() {
// Do nothing as Drupal is not installed yet.
}
/**
@@ -337,7 +296,10 @@ abstract class UpdatePathTestBase extends BrowserTestBase {
// Ensure there are no failed updates.
if ($this->checkFailedUpdates) {
$this->assertNoRaw('<strong>' . t('Failed:') . '</strong>');
$failure = $this->cssSelect('.failure');
if ($failure) {
$this->fail('The update failed with the following message: "' . reset($failure)->getText() . '"');
}
// Ensure that there are no pending updates.
foreach (['update', 'post_update'] as $update_type) {
@@ -0,0 +1,103 @@
<?php
namespace Drupal\KernelTests\Core\Ajax;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\KernelTests\KernelTestBase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
/**
* Performs tests on AJAX framework commands.
*
* @group Ajax
*/
class CommandsTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['system', 'node', 'ajax_test', 'ajax_forms_test'];
/**
* Regression test: Settings command exists regardless of JS aggregation.
*/
public function testAttachedSettings() {
$assert = function ($message) {
$response = new AjaxResponse();
$response->setAttachments([
'library' => ['core/drupalSettings'],
'drupalSettings' => ['foo' => 'bar'],
]);
$ajax_response_attachments_processor = \Drupal::service('ajax_response.attachments_processor');
$subscriber = new AjaxResponseSubscriber($ajax_response_attachments_processor);
$event = new FilterResponseEvent(
\Drupal::service('http_kernel'),
new Request(),
HttpKernelInterface::MASTER_REQUEST,
$response
);
$subscriber->onResponse($event);
$expected = [
'command' => 'settings',
];
$this->assertCommand($response->getCommands(), $expected, $message);
};
$config = $this->config('system.performance');
$config->set('js.preprocess', FALSE)->save();
$assert('Settings command exists when JS aggregation is disabled.');
$config->set('js.preprocess', TRUE)->save();
$assert('Settings command exists when JS aggregation is enabled.');
}
/**
* Asserts the array of Ajax commands contains the searched command.
*
* An AjaxResponse object stores an array of Ajax commands. This array
* sometimes includes commands automatically provided by the framework in
* addition to commands returned by a particular controller. During testing,
* we're usually interested that a particular command is present, and don't
* care whether other commands precede or follow the one we're interested in.
* Additionally, the command we're interested in may include additional data
* that we're not interested in. Therefore, this function simply asserts that
* one of the commands in $haystack contains all of the keys and values in
* $needle. Furthermore, if $needle contains a 'settings' key with an array
* value, we simply assert that all keys and values within that array are
* present in the command we're checking, and do not consider it a failure if
* the actual command contains additional settings that aren't part of
* $needle.
*
* @param $haystack
* An array of rendered Ajax commands returned by the server.
* @param $needle
* Array of info we're expecting in one of those commands.
* @param $message
* An assertion message.
*/
protected function assertCommand($haystack, $needle, $message) {
$found = FALSE;
foreach ($haystack as $command) {
// If the command has additional settings that we're not testing for, do
// not consider that a failure.
if (isset($command['settings']) && is_array($command['settings']) && isset($needle['settings']) && is_array($needle['settings'])) {
$command['settings'] = array_intersect_key($command['settings'], $needle['settings']);
}
// If the command has additional data that we're not testing for, do not
// consider that a failure. Also, == instead of ===, because we don't
// require the key/value pairs to be in any particular order
// (http://php.net/manual/language.operators.array.php).
if (array_intersect_key($command, $needle) == $needle) {
$found = TRUE;
break;
}
}
$this->assertTrue($found, $message);
}
}
@@ -12,62 +12,42 @@ use Drupal\KernelTests\KernelTestBase;
* @group Common
*/
class SizeTest extends KernelTestBase {
protected $exactTestCases;
protected $roundedTestCases;
protected function setUp() {
parent::setUp();
$kb = Bytes::KILOBYTE;
$this->exactTestCases = [
'1 byte' => 1,
'1 KB' => $kb,
'1 MB' => $kb * $kb,
'1 GB' => $kb * $kb * $kb,
'1 TB' => $kb * $kb * $kb * $kb,
'1 PB' => $kb * $kb * $kb * $kb * $kb,
'1 EB' => $kb * $kb * $kb * $kb * $kb * $kb,
'1 ZB' => $kb * $kb * $kb * $kb * $kb * $kb * $kb,
'1 YB' => $kb * $kb * $kb * $kb * $kb * $kb * $kb * $kb,
];
$this->roundedTestCases = [
'2 bytes' => 2,
// Rounded to 1 MB (not 1000 or 1024 kilobyte!).
'1 MB' => ($kb * $kb) - 1,
// Megabytes.
round(3623651 / ($this->exactTestCases['1 MB']), 2) . ' MB' => 3623651,
// Petabytes.
round(67234178751368124 / ($this->exactTestCases['1 PB']), 2) . ' PB' => 67234178751368124,
// Yottabytes.
round(235346823821125814962843827 / ($this->exactTestCases['1 YB']), 2) . ' YB' => 235346823821125814962843827,
];
}
/**
* Checks that format_size() returns the expected string.
*
* @dataProvider providerTestCommonFormatSize
*/
public function testCommonFormatSize() {
foreach ([$this->exactTestCases, $this->roundedTestCases] as $test_cases) {
foreach ($test_cases as $expected => $input) {
$this->assertEqual(
($result = format_size($input, NULL)),
$expected,
$expected . ' == ' . $result . ' (' . $input . ' bytes)'
);
}
}
public function testCommonFormatSize($expected, $input) {
$size = format_size($input, NULL);
$this->assertEquals($expected, $size);
}
/**
* Cross-tests Bytes::toInt() and format_size().
* Provides a list of byte size to test.
*/
public function testCommonParseSizeFormatSize() {
foreach ($this->exactTestCases as $size) {
$this->assertEqual(
$size,
($parsed_size = Bytes::toInt($string = format_size($size, NULL))),
$size . ' == ' . $parsed_size . ' (' . $string . ')'
);
}
public function providerTestCommonFormatSize() {
$kb = Bytes::KILOBYTE;
return [
['1 byte', 1],
['2 bytes', 2],
['1 KB', $kb],
['1 MB', pow($kb, 2)],
['1 GB', pow($kb, 3)],
['1 TB', pow($kb, 4)],
['1 PB', pow($kb, 5)],
['1 EB', pow($kb, 6)],
['1 ZB', pow($kb, 7)],
['1 YB', pow($kb, 8)],
// Rounded to 1 MB - not 1000 or 1024 kilobyte
['1 MB', ($kb * $kb) - 1],
// Decimal Megabytes
['3.46 MB', 3623651],
// Decimal Petabytes
['59.72 PB', 67234178751368124],
// Decimal Yottabytes
['194.67 YB', 235346823821125814962843827],
];
}
}
@@ -623,7 +623,7 @@ class ConfigImporterTest extends KernelTestBase {
}
}
// Make a config entity have mulitple unmet dependencies.
// Make a config entity have multiple unmet dependencies.
$config_entity_data = $sync->read('config_test.dynamic.dotted.default');
$config_entity_data['dependencies'] = ['module' => ['unknown', 'dblog']];
$sync->write('config_test.dynamic.dotted.module', $config_entity_data);
@@ -848,7 +848,7 @@ class ConfigImporterTest extends KernelTestBase {
}
/**
* Helper meothd to test custom config installer steps.
* Helper method to test custom config installer steps.
*
* @param array $context
* Batch context.
@@ -151,6 +151,11 @@ abstract class ConfigStorageTestBase extends KernelTestBase {
// Listing on a non-existing storage bin returns an empty array.
$result = $this->invalidStorage->listAll();
$this->assertIdentical($result, []);
// Getting all collections on a non-existing storage bin return an empty
// array.
$this->assertSame([], $this->invalidStorage->getAllCollectionNames());
// Writing to a non-existing storage bin creates the bin.
$this->invalidStorage->write($name, ['foo' => 'bar']);
$result = $this->invalidStorage->read($name);
@@ -30,7 +30,7 @@ class PrefixInfoTest extends DatabaseTestBase {
$db1_schema = $db1_connection->schema();
$db2_connection = Database::getConnection('default', 'extra');
// Get the prefix info for the first databse.
// Get the prefix info for the first database.
$method = new \ReflectionMethod($db1_schema, 'getPrefixInfo');
$method->setAccessible(TRUE);
$db1_info = $method->invoke($db1_schema);
@@ -22,6 +22,10 @@ class SelectCloneTest extends DatabaseTestBase {
$query->condition('id', $subquery, 'IN');
$clone = clone $query;
// Cloned query should have a different unique identifier.
$this->assertNotEquals($query->uniqueIdentifier(), $clone->uniqueIdentifier());
// Cloned query should not be altered by the following modification
// happening on original query.
$subquery->condition('age', 25, '>');
@@ -34,4 +38,31 @@ class SelectCloneTest extends DatabaseTestBase {
$this->assertEqual(2, $query_result, 'The query returns the expected number of rows');
}
/**
* Tests that nested SELECT queries are cloned properly.
*/
public function testNestedQueryCloning() {
$sub_query = $this->connection->select('test', 't');
$sub_query->addField('t', 'id', 'id');
$sub_query->condition('age', 28, '<');
$query = $this->connection->select($sub_query, 't');
$clone = clone $query;
// Cloned query should have a different unique identifier.
$this->assertNotEquals($query->uniqueIdentifier(), $clone->uniqueIdentifier());
// Cloned query should not be altered by the following modification
// happening on original query.
$sub_query->condition('age', 25, '>');
$clone_result = $clone->countQuery()->execute()->fetchField();
$query_result = $query->countQuery()->execute()->fetchField();
// Make sure the cloned query has not been modified.
$this->assertEquals(3, $clone_result, 'The cloned query returns the expected number of rows');
$this->assertEquals(2, $query_result, 'The query returns the expected number of rows');
}
}
@@ -0,0 +1,35 @@
<?php
namespace Drupal\KernelTests\Core\Entity;
/**
* @coversDefaultClass \Drupal\Core\Entity\EntityBundleListener
*
* @group Entity
*/
class EntityBundleListenerTest extends EntityKernelTestBase {
/**
* @covers ::onBundleCreate
*
* Note: Installing the entity_schema_test module will mask the bug this test
* was written to cover, as the field map cache is cleared manually by
* \Drupal\Core\Field\FieldDefinitionListener::onFieldDefinitionCreate().
*/
public function testOnBundleCreate() {
$field_map = $this->container->get('entity_field.manager')->getFieldMap();
$expected = [
'entity_test' => 'entity_test',
];
$this->assertEquals($expected, $field_map['entity_test']['id']['bundles']);
entity_test_create_bundle('custom');
$field_map = $this->container->get('entity_field.manager')->getFieldMap();
$expected = [
'entity_test' => 'entity_test',
'custom' => 'custom',
];
$this->assertSame($expected, $field_map['entity_test']['id']['bundles']);
}
}
@@ -57,7 +57,7 @@ class EntityDecoupledTranslationRevisionsTest extends EntityKernelTestBase {
protected $previousRevisionId = [];
/**
* The previous unstranslatable field value.
* The previous untranslatable field value.
*
* @var string[]
*/
@@ -4,9 +4,9 @@ namespace Drupal\KernelTests\Core\Entity;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
/**
* Tests the Entity Query relationship API.
@@ -6,10 +6,10 @@ use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_test\Entity\EntityTestMulRev;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Symfony\Component\HttpFoundation\Request;
/**
@@ -630,7 +630,7 @@ class EntityQueryTest extends EntityKernelTestBase {
->condition("$figures.%delta", 1)
->sort('id')
->execute();
// Entity needs to have atleast two figures.
// Entity needs to have at least two figures.
$this->assertResult(3, 7, 11, 15);
// Numeric delta on single value base field should return results only if
@@ -7,9 +7,9 @@ use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
@@ -3,11 +3,13 @@
namespace Drupal\KernelTests\Core\Entity;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
/**
* Tests adding a custom bundle field.
* Tests the default entity storage schema handler.
*
* @group system
* @group Entity
*/
class EntitySchemaTest extends EntityKernelTestBase {
@@ -109,6 +111,178 @@ class EntitySchemaTest extends EntityKernelTestBase {
$this->assertTrue($schema_handler->tableExists($dedicated_tables[0]), new FormattableMarkup('Field schema correct for the @table table.', ['@table' => $table]));
}
/**
* Tests deleting and creating a field that is part of a primary key.
*
* @param string $entity_type_id
* The ID of the entity type whose schema is being tested.
* @param string $field_name
* The name of the field that is being re-installed.
*
* @dataProvider providerTestPrimaryKeyUpdate
*/
public function testPrimaryKeyUpdate($entity_type_id, $field_name) {
// EntityKernelTestBase::setUp() already installs the schema for the
// 'entity_test' entity type.
if ($entity_type_id !== 'entity_test') {
$this->installEntitySchema($entity_type_id);
}
/* @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface $update_manager */
$update_manager = $this->container->get('entity.definition_update_manager');
$entity_type = $update_manager->getEntityType($entity_type_id);
/* @see \Drupal\Core\Entity\ContentEntityBase::baseFieldDefinitions() */
switch ($field_name) {
case 'id':
$field = BaseFieldDefinition::create('integer')
->setLabel('ID')
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE);
break;
case 'revision_id':
$field = BaseFieldDefinition::create('integer')
->setLabel('Revision ID')
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE);
break;
case 'langcode':
$field = BaseFieldDefinition::create('language')
->setLabel('Language');
if ($entity_type->isRevisionable()) {
$field->setRevisionable(TRUE);
}
if ($entity_type->isTranslatable()) {
$field->setTranslatable(TRUE);
}
break;
}
$field
->setName($field_name)
->setTargetEntityTypeId($entity_type_id)
->setProvider($entity_type->getProvider());
// Build up a map of expected primary keys depending on the entity type
// configuration.
$id_key = $entity_type->getKey('id');
$revision_key = $entity_type->getKey('revision');
$langcode_key = $entity_type->getKey('langcode');
$expected = [];
$expected[$entity_type->getBaseTable()] = [$id_key];
if ($entity_type->isRevisionable()) {
$expected[$entity_type->getRevisionTable()] = [$revision_key];
}
if ($entity_type->isTranslatable()) {
$expected[$entity_type->getDataTable()] = [$id_key, $langcode_key];
}
if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) {
$expected[$entity_type->getRevisionDataTable()] = [$revision_key, $langcode_key];
}
// First, test explicitly deleting and re-installing a field. Make sure that
// all primary keys are there to start with.
$this->assertSame($expected, $this->findPrimaryKeys($entity_type));
// Then uninstall the field and make sure all primary keys that the field
// was part of have been updated. Since this is not a valid state of the
// entity type (for example a revisionable entity type without a revision ID
// field or a translatable entity type without a language code field) the
// actual primary keys at this point are irrelevant.
$update_manager->uninstallFieldStorageDefinition($field);
$this->assertNotEquals($expected, $this->findPrimaryKeys($entity_type));
// Finally, reinstall the field and make sure the primary keys have been
// recreated.
$update_manager->installFieldStorageDefinition($field->getName(), $entity_type_id, $field->getProvider(), $field);
$this->assertSame($expected, $this->findPrimaryKeys($entity_type));
// Now test updating a field without data. This will end up deleting
// and re-creating the field, similar to the code above.
$update_manager->updateFieldStorageDefinition($field);
$this->assertSame($expected, $this->findPrimaryKeys($entity_type));
// Now test updating a field with data.
/* @var \Drupal\Core\Entity\FieldableEntityStorageInterface $storage */
$storage = $this->entityManager->getStorage($entity_type_id);
// The schema of ID fields is incorrectly recreated as 'int' instead of
// 'serial', so we manually have to specify an ID.
// @todo Remove this in https://www.drupal.org/project/drupal/issues/2928906
$storage->create(['id' => 1, 'revision_id' => 1])->save();
$this->assertTrue($storage->countFieldData($field, TRUE));
$update_manager->updateFieldStorageDefinition($field);
$this->assertSame($expected, $this->findPrimaryKeys($entity_type));
$this->assertTrue($storage->countFieldData($field, TRUE));
}
/**
* Finds the primary keys for a given entity type.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type whose primary keys are being fetched.
*
* @return array[]
* An array where the keys are the table names of the entity type's tables
* and the values are a list of the respective primary keys.
*/
protected function findPrimaryKeys(EntityTypeInterface $entity_type) {
$base_table = $entity_type->getBaseTable();
$revision_table = $entity_type->getRevisionTable();
$data_table = $entity_type->getDataTable();
$revision_data_table = $entity_type->getRevisionDataTable();
$schema = $this->database->schema();
$find_primary_key_columns = new \ReflectionMethod(get_class($schema), 'findPrimaryKeyColumns');
$find_primary_key_columns->setAccessible(TRUE);
// Build up a map of primary keys depending on the entity type
// configuration. If the field that is being removed is part of a table's
// primary key, we skip the assertion for that table as this represents an
// intermediate and invalid state of the entity schema.
$primary_keys[$base_table] = $find_primary_key_columns->invoke($schema, $base_table);
if ($entity_type->isRevisionable()) {
$primary_keys[$revision_table] = $find_primary_key_columns->invoke($schema, $revision_table);
}
if ($entity_type->isTranslatable()) {
$primary_keys[$data_table] = $find_primary_key_columns->invoke($schema, $data_table);
}
if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) {
$primary_keys[$revision_data_table] = $find_primary_key_columns->invoke($schema, $revision_data_table);
}
return $primary_keys;
}
/**
* Provides test cases for EntitySchemaTest::testPrimaryKeyUpdate()
*
* @return array
* An array of test cases consisting of an entity type ID and a field name.
*/
public function providerTestPrimaryKeyUpdate() {
// Build up test cases for all possible entity type configurations.
// For each entity type we test reinstalling each field that is part of
// any table's primary key.
$tests = [];
$tests['entity_test:id'] = ['entity_test', 'id'];
$tests['entity_test_rev:id'] = ['entity_test_rev', 'id'];
$tests['entity_test_rev:revision_id'] = ['entity_test_rev', 'revision_id'];
$tests['entity_test_mul:id'] = ['entity_test_mul', 'id'];
$tests['entity_test_mul:langcode'] = ['entity_test_mul', 'langcode'];
$tests['entity_test_mulrev:id'] = ['entity_test_mulrev', 'id'];
$tests['entity_test_mulrev:revision_id'] = ['entity_test_mulrev', 'revision_id'];
$tests['entity_test_mulrev:langcode'] = ['entity_test_mulrev', 'langcode'];
return $tests;
}
/**
* {@inheritdoc}
*/
@@ -4,8 +4,8 @@ namespace Drupal\KernelTests\Core\Entity;
use Drupal\Core\Entity\EntityViewBuilder;
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Core\Cache\Cache;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
@@ -154,12 +154,12 @@ class RevisionableContentEntityBaseTest extends EntityKernelTestBase {
}
/**
* Asserts the ammount of items on entity related tables.
* Asserts the amount of items on entity related tables.
*
* @param int $count
* The number of items expected to be in revisions related tables.
* @param \Drupal\Core\Entity\EntityTypeInterface $definition
* The definition and metada of the entity being tested.
* The definition and metadata of the entity being tested.
*/
protected function assertItemsTableCount($count, EntityTypeInterface $definition) {
$this->assertEqual(1, db_query('SELECT COUNT(*) FROM {' . $definition->getBaseTable() . '}')->fetchField());
@@ -6,9 +6,9 @@ use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
@@ -201,7 +201,7 @@ class ValidReferenceConstraintValidatorTest extends EntityKernelTestBase {
$violations = $referencing_entity->field_test->validate();
$this->assertCount(0, $violations);
// Remove one of the referencable bundles and check that a pre-existing node
// Remove one of the referenceable bundles and check that a pre-existing node
// of that bundle can not be referenced anymore.
$field = FieldConfig::loadByName('entity_test', 'entity_test', 'field_test');
$field->setSetting('handler_settings', ['target_bundles' => ['article']]);
@@ -53,7 +53,7 @@ class MimeTypeTest extends FileTestBase {
$this->assertIdentical($output, $expected, format_string('Mimetype (using default mappings) for %input is %output (expected: %expected).', ['%input' => $input, '%output' => $output, '%expected' => $expected]));
}
// Now test the extension gusser by passing in a custom mapping.
// Now test the extension guesser by passing in a custom mapping.
$mapping = [
'mimetypes' => [
0 => 'application/java-archive',
@@ -8,7 +8,7 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests form validation mesages are displayed in the same order as the fields.
* Tests form validation messages are displayed in the same order as the fields.
*
* @group Form
*/
@@ -0,0 +1,50 @@
<?php
namespace Drupal\KernelTests\Core\Menu;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests the local action manager.
*
* @coversDefaultClass \Drupal\Core\Menu\LocalActionManager
* @group Menu
*/
class LocalActionManagerTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['menu_test', 'user', 'system'];
/**
* Tests the cacheability of local actions.
*/
public function testCacheability() {
/** @var \Drupal\Core\Menu\LocalActionManager $local_action_manager */
$local_action_manager = \Drupal::service('plugin.manager.menu.local_action');
$build = [
'#cache' => [
'key' => 'foo',
],
$local_action_manager->getActionsForRoute('menu_test.local_action7'),
];
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
$renderer->renderRoot($build);
$this->assertContains('menu_local_action7', $build[0]['menu_test.local_action7']['#cache']['tags']);
$this->assertContains('url.query_args:menu_local_action7', $build[0]['menu_test.local_action7']['#cache']['contexts']);
$this->assertContains('menu_local_action8', $build[0]['menu_test.local_action8']['#cache']['tags']);
$this->assertContains('url.query_args:menu_local_action8', $build[0]['menu_test.local_action8']['#cache']['contexts']);
$this->assertContains('menu_local_action7', $build['#cache']['tags']);
$this->assertContains('url.query_args:menu_local_action7', $build['#cache']['contexts']);
$this->assertContains('menu_local_action8', $build['#cache']['tags']);
$this->assertContains('url.query_args:menu_local_action8', $build['#cache']['contexts']);
}
}
@@ -241,7 +241,7 @@ class AliasTest extends PathUnitTestBase {
// Lookup admin path in whitelist. It will query the DB and figure out
// that it indeed has an alias, and add it to the internal whitelist and
// flag it to be peristed to cache.
// flag it to be persisted to cache.
$this->assertTrue($whitelist->get('admin'));
// Destruct the whitelist so it persists its cache.
@@ -0,0 +1,63 @@
<?php
namespace Drupal\KernelTests\Core\Plugin;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\Plugin\DataType\StringData;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests that contexts work properly with the typed data manager.
*
* @coversDefaultClass \Drupal\Core\Plugin\Context\Context
* @group Context
*/
class ContextTypedDataTest extends KernelTestBase {
/**
* Tests that contexts can be serialized.
*/
public function testSerialize() {
$definition = new ContextDefinition('any');
$data_definition = DataDefinition::create('string');
$typed_data = new StringData($data_definition);
$typed_data->setValue('example string');
$context = new Context($definition, $typed_data);
// getContextValue() will cause the context to reference the typed data
// manager service.
$value = $context->getContextValue();
$context = serialize($context);
$context = unserialize($context);
$this->assertSame($value, $context->getContextValue());
}
/**
* Tests that getting a context value does not throw fatal errors.
*
* This test ensures that the typed data manager is set correctly on the
* Context class.
*
* @covers ::getContextValue
*/
public function testGetContextValue() {
$data_definition = DataDefinition::create('string');
$typed_data = new StringData($data_definition);
$typed_data->setValue('example string');
// Prepare a container that holds the typed data manager mock.
$typed_data_manager = $this->prophesize(TypedDataManagerInterface::class);
$typed_data_manager->getCanonicalRepresentation($typed_data)->will(function ($arguments) {
return $arguments[0]->getValue();
});
$this->container->set('typed_data_manager', $typed_data_manager->reveal());
$definition = new ContextDefinition('any');
$context = new Context($definition, $typed_data);
$value = $context->getContextValue();
$this->assertSame($value, $typed_data->getValue());
}
}
@@ -2,9 +2,7 @@
namespace Drupal\KernelTests\Core\Routing;
use Drupal\Core\Cache\MemoryBackend;
use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
use Drupal\Core\Lock\NullLockBackend;
use Drupal\Core\State\State;
use Drupal\KernelTests\KernelTestBase;
use Symfony\Component\Routing\Route;
@@ -38,7 +36,7 @@ class MatcherDumperTest extends KernelTestBase {
parent::setUp();
$this->fixtures = new RoutingFixtures();
$this->state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend());
$this->state = new State(new KeyValueMemoryFactory());
}
/**
@@ -12,7 +12,6 @@ use Drupal\Core\Cache\MemoryBackend;
use Drupal\Core\Database\Database;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
use Drupal\Core\Lock\NullLockBackend;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\Routing\MatcherDumper;
use Drupal\Core\Routing\RouteProvider;
@@ -84,7 +83,7 @@ class RouteProviderTest extends KernelTestBase {
protected function setUp() {
parent::setUp();
$this->fixtures = new RoutingFixtures();
$this->state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend());
$this->state = new State(new KeyValueMemoryFactory());
$this->currentPath = new CurrentPathStack(new RequestStack());
$this->cache = new MemoryBackend();
$this->pathProcessor = \Drupal::service('path_processor_manager');
@@ -97,7 +96,7 @@ class RouteProviderTest extends KernelTestBase {
public function register(ContainerBuilder $container) {
parent::register($container);
// Readd the incoming path alias for these tests.
// Read the incoming path alias for these tests.
if ($container->hasDefinition('path_processor_alias')) {
$definition = $container->getDefinition('path_processor_alias');
$definition->addTag('path_processor_inbound');
@@ -19,6 +19,13 @@ class AnonymousPrivateTempStoreTest extends KernelTestBase {
*/
public static $modules = ['system'];
/**
* The private temp store.
*
* @var \Drupal\Core\TempStore\PrivateTempStore
*/
protected $tempStore;
/**
* {@inheritdoc}
*/
@@ -29,30 +36,35 @@ class AnonymousPrivateTempStoreTest extends KernelTestBase {
// full Drupal environment.
$this->installSchema('system', ['key_value_expire']);
$session = $this->container->get('session');
$request = Request::create('/');
$request->setSession($session);
$stack = $this->container->get('request_stack');
$stack->pop();
$stack->push($request);
$this->tempStore = $this->container->get('tempstore.private')->get('anonymous_private_temp_store');
}
/**
* Tests anonymous can get without a previous set.
*/
public function testAnonymousCanUsePrivateTempStoreGet() {
$actual = $this->tempStore->get('foo');
$this->assertNull($actual);
}
/**
* Tests anonymous can use the PrivateTempStore.
*/
public function testAnonymousCanUsePrivateTempStore() {
$temp_store = $this->container->get('tempstore.private')->get('anonymous_private_temp_store');
$temp_store->set('foo', 'bar');
$metadata1 = $temp_store->getMetadata('foo');
public function testAnonymousCanUsePrivateTempStoreSet() {
$this->tempStore->set('foo', 'bar');
$metadata1 = $this->tempStore->getMetadata('foo');
$this->assertEquals('bar', $temp_store->get('foo'));
$this->assertEquals('bar', $this->tempStore->get('foo'));
$this->assertNotEmpty($metadata1->owner);
$temp_store->set('foo', 'bar2');
$metadata2 = $temp_store->getMetadata('foo');
$this->assertEquals('bar2', $temp_store->get('foo'));
$this->tempStore->set('foo', 'bar2');
$metadata2 = $this->tempStore->getMetadata('foo');
$this->assertEquals('bar2', $this->tempStore->get('foo'));
$this->assertNotEmpty($metadata2->owner);
$this->assertEquals($metadata2->owner, $metadata1->owner);
}
@@ -0,0 +1,23 @@
module.exports = {
'@tags': ['core'],
before(browser) {
browser.drupalInstall().drupalLoginAsAdmin(() => {
browser
.drupalRelativeURL('/admin/modules')
.setValue('input[type="search"]', 'FormAPI')
.waitForElementVisible('input[name="modules[form_test][enable]"]', 1000)
.click('input[name="modules[form_test][enable]"]')
.click('input[type="submit"]') // Submit module form.
.click('input[type="submit"]'); // Confirm installation of dependencies.
});
},
after(browser) {
browser.drupalUninstall();
},
'Test form with state API': browser => {
browser
.drupalRelativeURL('/form-test/javascript-states-form')
.waitForElementVisible('body', 1000)
.waitForElementNotVisible('input[name="textfield"]', 1000);
},
};
+8 -9
View File
@@ -124,7 +124,7 @@ abstract class BrowserTestBase extends TestCase {
/*
* Mink class for the default driver to use.
*
* Shoud be a fully qualified class name that implements
* Should be a fully-qualified class name that implements
* Behat\Mink\Driver\DriverInterface.
*
* Value can be overridden using the environment variable MINK_DRIVER_CLASS.
@@ -238,6 +238,12 @@ 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');
@@ -388,14 +394,7 @@ abstract class BrowserTestBase extends TestCase {
$this->installDrupal();
// Setup Mink.
$session = $this->initMink();
$cookies = $this->extractCookiesFromRequest(\Drupal::request());
foreach ($cookies as $cookie_name => $values) {
foreach ($values as $value) {
$session->setCookie($cookie_name, $value);
}
}
$this->initMink();
// Set up the browser test output file.
$this->initBrowserOutputFile();
@@ -807,7 +807,7 @@ class DateTimePlusTest extends TestCase {
public function testValidateFormat() {
// Check that an input that does not strictly follow the input format will
// produce the desired date. In this case the year string '11' doesn't
// precisely match the 'Y' formater parameter, but PHP will parse it
// precisely match the 'Y' formatter parameter, but PHP will parse it
// regardless. However, when formatted with the same string, the year will
// be output with four digits. With the ['validate_format' => FALSE]
// $settings, this will not thrown an exception.
@@ -3,6 +3,8 @@
namespace Drupal\Tests\Component\Plugin;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Component\Plugin\Mapper\MapperInterface;
use Drupal\Component\Plugin\PluginManagerBase;
use PHPUnit\Framework\TestCase;
/**
@@ -90,4 +92,43 @@ class PluginManagerBaseTest extends TestCase {
$this->assertEquals($configuration_array, $fallback_result['configuration']);
}
/**
* @covers ::getInstance
*/
public function testGetInstance() {
$options = [
'foo' => 'F00',
'bar' => 'bAr',
];
$instance = new \stdClass();
$mapper = $this->prophesize(MapperInterface::class);
$mapper->getInstance($options)
->shouldBeCalledTimes(1)
->willReturn($instance);
$manager = new StubPluginManagerBaseWithMapper($mapper->reveal());
$this->assertEquals($instance, $manager->getInstance($options));
}
/**
* @covers ::getInstance
*/
public function testGetInstanceWithoutMapperShouldThrowException() {
$options = [
'foo' => 'F00',
'bar' => 'bAr',
];
/** @var \Drupal\Component\Plugin\PluginManagerBase $manager */
$manager = $this->getMockBuilder(PluginManagerBase::class)
->getMockForAbstractClass();
// Set the expected exception thrown by ::getInstance.
if (method_exists($this, 'expectException')) {
$this->expectException(\BadMethodCallException::class);
$this->expectExceptionMessage(sprintf('%s does not support this method unless %s::$mapper is set.', get_class($manager), get_class($manager)));
}
else {
$this->setExpectedException(\BadMethodCallException::class, sprintf('%s does not support this method unless %s::$mapper is set.', get_class($manager), get_class($manager)));
}
$manager->getInstance($options);
}
}
@@ -0,0 +1,22 @@
<?php
namespace Drupal\Tests\Component\Plugin;
use Drupal\Component\Plugin\Mapper\MapperInterface;
use Drupal\Component\Plugin\PluginManagerBase;
/**
* Stubs \Drupal\Component\Plugin\PluginManagerBase to take a MapperInterface.
*/
final class StubPluginManagerBaseWithMapper extends PluginManagerBase {
/**
* Constructs a new instance.
*
* @param \Drupal\Component\Plugin\Mapper\MapperInterface $mapper
*/
public function __construct(MapperInterface $mapper) {
$this->mapper = $mapper;
}
}
@@ -106,7 +106,7 @@ class PhpTransliterationTest extends TestCase {
// Make some strings with two, three, and four-byte characters for testing.
// Note that the 3-byte character is overridden by the 'kg' language.
$two_byte = 'Ä Ö Ü Å Ø äöüåøhello';
// This is a Cyrrillic character that looks something like a u. See
// This is a Cyrillic character that looks something like a "u". See
// http://www.unicode.org/charts/PDF/U0400.pdf
$three_byte = html_entity_decode('&#x446;', ENT_NOQUOTES, 'UTF-8');
// This is a Canadian Aboriginal character like a triangle. See
@@ -107,7 +107,7 @@ class CssOptimizerUnitTest extends UnitTestCase {
str_replace('url(../images/icon.png)', 'url(' . file_url_transform_relative(file_create_url($path . 'images/icon.png')) . ')', file_get_contents($absolute_path . 'css_subfolder/css_input_with_import.css.optimized.css')),
],
// File. Tests:
// - Any @charaset declaration at the beginning of a file should be
// - Any @charset declaration at the beginning of a file should be
// removed without breaking subsequent CSS.
[
[
@@ -50,7 +50,7 @@ class ValidateHostnameTest extends UnitTestCase {
$data[] = ['72.21.91.99:80', 'Properly formed HTTP_HOST with IPv4 address valid.', TRUE];
$data[] = ['2607:f8b0:4004:803::1002:80', 'Properly formed HTTP_HOST with IPv6 address valid.', TRUE];
// Verfies that the IPv6 loopback address is valid.
// Verifies that the IPv6 loopback address is valid.
$data[] = ['[::1]:80', 'HTTP_HOST containing IPv6 loopback is valid.', TRUE];
return $data;
@@ -383,6 +383,14 @@ class SqlContentEntityStorageTest extends UnitTestCase {
$this->entityType->expects($this->once())
->method('getKeys')
->will($this->returnValue(['id' => 'id']));
$this->entityType->expects($this->any())
->method('hasKey')
->will($this->returnValueMap([
// SqlContentEntityStorageSchema::initializeBaseTable()
['revision', FALSE],
// SqlContentEntityStorageSchema::processBaseTable()
['id', TRUE],
]));
$this->entityType->expects($this->any())
->method('getKey')
->will($this->returnValueMap([
@@ -7,12 +7,10 @@
namespace Drupal\Tests\Core\Extension;
use Drupal\Core\Cache\MemoryBackend;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\InfoParser;
use Drupal\Core\Extension\ThemeHandler;
use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
use Drupal\Core\Lock\NullLockBackend;
use Drupal\Core\State\State;
use Drupal\Tests\UnitTestCase;
@@ -80,7 +78,7 @@ class ThemeHandlerTest extends UnitTestCase {
],
]);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend());
$this->state = new State(new KeyValueMemoryFactory());
$this->infoParser = $this->getMock('Drupal\Core\Extension\InfoParserInterface');
$this->extensionDiscovery = $this->getMockBuilder('Drupal\Core\Extension\ExtensionDiscovery')
->disableOriginalConstructor()
@@ -287,7 +287,7 @@ class FormStateDecoratorBaseTest extends UnitTestCase {
* @dataProvider providerLimitValidationErrors
*
* @param array[]|null $limit_validation_errors
* Any valid vlaue for
* Any valid value for
* \Drupal\Core\Form\FormStateInterface::getLimitValidationErrors()'s
* return value;
*/
@@ -13,7 +13,9 @@ use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultForbidden;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\Controller\ControllerResolver;
use Drupal\Core\DependencyInjection\Container;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Menu\LocalActionManager;
@@ -23,6 +25,7 @@ use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
@@ -113,7 +116,15 @@ class LocalActionManagerTest extends UnitTestCase {
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
$access_result = new AccessResultForbidden();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
$cache_contexts_manager->assertValidTokens(Argument::any())
->willReturn(TRUE);
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager->reveal());
\Drupal::setContainer($container);
$access_result = (new AccessResultForbidden())->cachePerPermissions();
$this->accessManager = $this->getMock('Drupal\Core\Access\AccessManagerInterface');
$this->accessManager->expects($this->any())
->method('checkNamedRoute')
@@ -186,6 +197,14 @@ class LocalActionManagerTest extends UnitTestCase {
}
public function getActionsForRouteProvider() {
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
$cache_contexts_manager->assertValidTokens(Argument::any())
->willReturn(TRUE);
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager->reveal());
\Drupal::setContainer($container);
// Single available and single expected plugins.
$data[] = [
'test_route',
@@ -201,7 +220,9 @@ class LocalActionManagerTest extends UnitTestCase {
],
[
'#cache' => [
'contexts' => ['route'],
'tags' => [],
'contexts' => ['route', 'user.permissions'],
'max-age' => 0,
],
'plugin_id_1' => [
'#theme' => 'menu_local_action',
@@ -210,13 +231,8 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2'),
'localized_options' => '',
],
'#access' => AccessResult::forbidden(),
'#access' => AccessResult::forbidden()->cachePerPermissions(),
'#weight' => 0,
'#cache' => [
'contexts' => [],
'tags' => [],
'max-age' => 0,
],
],
],
];
@@ -243,7 +259,9 @@ class LocalActionManagerTest extends UnitTestCase {
],
[
'#cache' => [
'contexts' => ['route'],
'tags' => [],
'contexts' => ['route', 'user.permissions'],
'max-age' => 0,
],
'plugin_id_1' => [
'#theme' => 'menu_local_action',
@@ -252,13 +270,8 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2'),
'localized_options' => '',
],
'#access' => AccessResult::forbidden(),
'#access' => AccessResult::forbidden()->cachePerPermissions(),
'#weight' => 0,
'#cache' => [
'contexts' => [],
'tags' => [],
'max-age' => 0,
],
],
],
];
@@ -286,7 +299,9 @@ class LocalActionManagerTest extends UnitTestCase {
],
[
'#cache' => [
'contexts' => ['route'],
'contexts' => ['route', 'user.permissions'],
'tags' => [],
'max-age' => 0,
],
'plugin_id_1' => [
'#theme' => 'menu_local_action',
@@ -295,13 +310,8 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2'),
'localized_options' => '',
],
'#access' => AccessResult::forbidden(),
'#access' => AccessResult::forbidden()->cachePerPermissions(),
'#weight' => 1,
'#cache' => [
'contexts' => [],
'tags' => [],
'max-age' => 0,
],
],
'plugin_id_2' => [
'#theme' => 'menu_local_action',
@@ -310,13 +320,8 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_3'),
'localized_options' => '',
],
'#access' => AccessResult::forbidden(),
'#access' => AccessResult::forbidden()->cachePerPermissions(),
'#weight' => 0,
'#cache' => [
'contexts' => [],
'tags' => [],
'max-age' => 0,
],
],
],
];
@@ -346,7 +351,9 @@ class LocalActionManagerTest extends UnitTestCase {
],
[
'#cache' => [
'contexts' => ['route'],
'contexts' => ['route', 'user.permissions'],
'tags' => [],
'max-age' => 0,
],
'plugin_id_1' => [
'#theme' => 'menu_local_action',
@@ -355,13 +362,8 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2', ['test1']),
'localized_options' => '',
],
'#access' => AccessResult::forbidden(),
'#access' => AccessResult::forbidden()->cachePerPermissions(),
'#weight' => 1,
'#cache' => [
'contexts' => [],
'tags' => [],
'max-age' => 0,
],
],
'plugin_id_2' => [
'#theme' => 'menu_local_action',
@@ -370,13 +372,8 @@ class LocalActionManagerTest extends UnitTestCase {
'url' => Url::fromRoute('test_route_2', ['test2']),
'localized_options' => '',
],
'#access' => AccessResult::forbidden(),
'#access' => AccessResult::forbidden()->cachePerPermissions(),
'#weight' => 0,
'#cache' => [
'contexts' => [],
'tags' => [],
'max-age' => 0,
],
],
],
];
@@ -162,6 +162,28 @@ class LocalTaskDefaultTest extends UnitTestCase {
$this->assertEquals(['parameter' => 'example'], $this->localTaskBase->getRouteParameters($route_match));
}
/**
* Tests the getRouteParameters method for a route with upcasted parameters.
*
* @covers ::getRouteParameters
*/
public function testGetRouteParametersForDynamicRouteWithUpcastedParametersEmptyRawParameters() {
$this->pluginDefinition = [
'route_name' => 'test_route',
];
$route = new Route('/test-route/{parameter}');
$this->routeProvider->expects($this->once())
->method('getRouteByName')
->with('test_route')
->will($this->returnValue($route));
$this->setupLocalTaskDefault();
$route_match = new RouteMatch('', $route, ['parameter' => (object) 'example2']);
$this->assertEquals(['parameter' => (object) 'example2'], $this->localTaskBase->getRouteParameters($route_match));
}
/**
* Defines a data provider for testGetWeight().
*
@@ -1,62 +0,0 @@
<?php
namespace Drupal\Tests\Core\Plugin\Context;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\Plugin\DataType\StringData;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\Tests\UnitTestCase;
/**
* Tests that contexts work properly with the typed data manager.
*
* @coversDefaultClass \Drupal\Core\Plugin\Context\Context
* @group Context
*/
class ContextTypedDataTest extends UnitTestCase {
/**
* The typed data object used during testing.
*
* @var \Drupal\Core\TypedData\Plugin\DataType\StringData
*/
protected $typedData;
/**
* Tests that getting a context value does not throw fatal errors.
*
* This test ensures that the typed data manager is set correctly on the
* Context class.
*
* @covers ::getContextValue
*/
public function testGetContextValue() {
// Prepare a container that holds the typed data manager mock.
$typed_data_manager = $this->getMock(TypedDataManagerInterface::class);
$typed_data_manager->expects($this->once())
->method('getCanonicalRepresentation')
->will($this->returnCallback([$this, 'getCanonicalRepresentation']));
$container = new ContainerBuilder();
$container->set('typed_data_manager', $typed_data_manager);
\Drupal::setContainer($container);
$definition = new ContextDefinition('any');
$data_definition = DataDefinition::create('string');
$this->typedData = new StringData($data_definition);
$this->typedData->setValue('example string');
$context = new Context($definition, $this->typedData);
$value = $context->getContextValue();
$this->assertSame($value, $this->typedData->getValue());
}
/**
* Helper mock callback to return the typed data value.
*/
public function getCanonicalRepresentation() {
return $this->typedData->getValue();
}
}
@@ -9,7 +9,6 @@ namespace Drupal\Tests\Core\Render;
use Drupal\Core\Cache\MemoryBackend;
use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
use Drupal\Core\Lock\NullLockBackend;
use Drupal\Core\State\State;
use Drupal\Core\Cache\Cache;
@@ -539,7 +538,7 @@ class RendererBubblingTest extends RendererTestBase {
$this->setupMemoryCache();
// Mock the State service.
$memory_state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend());
$memory_state = new State(new KeyValueMemoryFactory());
\Drupal::getContainer()->set('state', $memory_state);
$this->controllerResolver->expects($this->any())
->method('getControllerFromDefinition')
@@ -97,8 +97,8 @@ class UnroutedUrlAssemblerTest extends UnitTestCase {
['https://example.com/test', ['https' => FALSE], 'http://example.com/test'],
['https://example.com/test?foo=1#bar', [], 'https://example.com/test?foo=1#bar'],
'override-query' => ['https://example.com/test?foo=1#bar', ['query' => ['foo' => 2]], 'https://example.com/test?foo=2#bar'],
'override-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => 2]], 'https://example.com/test?bar=2&foo=1#bar'],
'override-deep-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => ['baz' => 'foo']]], 'https://example.com/test?bar%5Bbaz%5D=foo&foo=1#bar'],
'override-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => 2]], 'https://example.com/test?foo=1&bar=2#bar'],
'override-deep-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => ['baz' => 'foo']]], 'https://example.com/test?foo=1&bar%5Bbaz%5D=foo#bar'],
'override-fragment' => ['https://example.com/test?foo=1#bar', ['fragment' => 'baz'], 'https://example.com/test?foo=1#baz'],
['//www.drupal.org', [], '//www.drupal.org'],
];
@@ -92,10 +92,18 @@ trait DeprecationListenerTrait {
/**
* A list of deprecations to ignore whilst fixes are put in place.
*
* Do not add any new deprecations to this list. All deprecation errors will
* eventually be removed from this list.
*
* @return string[]
* A list of deprecations to ignore.
*
* @internal
*
* @todo Fix all these deprecations and remove them from this list.
* https://www.drupal.org/project/drupal/issues/2959269
*
* @see https://www.drupal.org/node/2811561
*/
public static function getSkippedDeprecations() {
return [
+1 -1
View File
@@ -371,7 +371,7 @@ trait UiHelperTrait {
* Options to be passed to Url::fromUri().
*
* @return string
* An absolute URL stsring.
* An absolute URL string.
*/
protected function buildUrl($path, array $options = []) {
if ($path instanceof Url) {
+1 -1
View File
@@ -167,7 +167,7 @@ class WebAssert extends MinkWebAssert {
* @param string $select
* One of id|name|label|value for the select field.
* @param string $option
* The option value that shoulkd not exist.
* The option value that should not exist.
* @param \Behat\Mink\Element\TraversableElement $container
* (optional) The document to check against. Defaults to the current page.
*