updated core from 8.4 to 8.5 : bug with login_destination
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests\Ajax;
|
||||
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
|
||||
/**
|
||||
* Tests the compatibility of the ajax.es6.js file.
|
||||
*
|
||||
* @group Ajax
|
||||
*/
|
||||
class BackwardCompatibilityTest extends JavascriptTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'js_ajax_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* Ensures Drupal.Ajax.element_settings BC layer.
|
||||
*/
|
||||
public function testAjaxBackwardCompatibility() {
|
||||
$this->drupalGet('/js_ajax_test');
|
||||
$this->click('#edit-test-button');
|
||||
|
||||
$this->assertSession()
|
||||
->waitForElement('css', '#js_ajax_test_form_element');
|
||||
$elements = $this->cssSelect('#js_ajax_test_form_element');
|
||||
$this->assertCount(1, $elements);
|
||||
$json = $elements[0]->getText();
|
||||
$data = json_decode($json, TRUE);
|
||||
$this->assertEquals([
|
||||
'element_settings' => 'catbro',
|
||||
'elementSettings' => 'catbro',
|
||||
], $data);
|
||||
}
|
||||
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests\Core\Installer\Form;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Session\UserSession;
|
||||
use Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware;
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
/**
|
||||
* Tests the select profile form.
|
||||
*
|
||||
* @group Installer
|
||||
*/
|
||||
class SelectProfileFormTest extends JavascriptTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->setupBaseUrl();
|
||||
|
||||
$this->prepareDatabasePrefix();
|
||||
|
||||
// Install Drupal test site.
|
||||
$this->prepareEnvironment();
|
||||
|
||||
// Define information about the user 1 account.
|
||||
$this->rootUser = new UserSession([
|
||||
'uid' => 1,
|
||||
'name' => 'admin',
|
||||
'mail' => 'admin@example.com',
|
||||
'pass_raw' => $this->randomMachineName(),
|
||||
]);
|
||||
|
||||
// If any $settings are defined for this test, copy and prepare an actual
|
||||
// settings.php, so as to resemble a regular installation.
|
||||
if (!empty($this->settings)) {
|
||||
// Not using File API; a potential error must trigger a PHP warning.
|
||||
copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php');
|
||||
$this->writeSettings($this->settings);
|
||||
}
|
||||
|
||||
// Note that FunctionalTestSetupTrait::installParameters() returns form
|
||||
// input values suitable for a programmed
|
||||
// \Drupal::formBuilder()->submitForm().
|
||||
// @see InstallerTestBase::translatePostValues()
|
||||
$this->parameters = $this->installParameters();
|
||||
|
||||
// Set up a minimal container (required by BrowserTestBase). Set cookie and
|
||||
// server information so that XDebug works.
|
||||
// @see install_begin_request()
|
||||
$request = Request::create($GLOBALS['base_url'] . '/core/install.php', 'GET', [], $_COOKIE, [], $_SERVER);
|
||||
$this->container = new ContainerBuilder();
|
||||
$request_stack = new RequestStack();
|
||||
$request_stack->push($request);
|
||||
$this->container
|
||||
->set('request_stack', $request_stack);
|
||||
$this->container
|
||||
->setParameter('language.default_values', Language::$defaultValues);
|
||||
$this->container
|
||||
->register('language.default', 'Drupal\Core\Language\LanguageDefault')
|
||||
->addArgument('%language.default_values%');
|
||||
$this->container
|
||||
->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager')
|
||||
->addArgument(new Reference('language.default'));
|
||||
$this->container
|
||||
->register('http_client', 'GuzzleHttp\Client')
|
||||
->setFactory('http_client_factory:fromOptions');
|
||||
$this->container
|
||||
->register('http_client_factory', 'Drupal\Core\Http\ClientFactory')
|
||||
->setArguments([new Reference('http_handler_stack')]);
|
||||
$handler_stack = HandlerStack::create();
|
||||
$test_http_client_middleware = new TestHttpClientMiddleware();
|
||||
$handler_stack->push($test_http_client_middleware(), 'test.http_client.middleware');
|
||||
$this->container
|
||||
->set('http_handler_stack', $handler_stack);
|
||||
|
||||
$this->container
|
||||
->set('app.root', DRUPAL_ROOT);
|
||||
\Drupal::setContainer($this->container);
|
||||
|
||||
// Setup Mink.
|
||||
$this->initMink();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initMink() {
|
||||
// The temporary files directory doesn't exist yet, as install_base_system()
|
||||
// has not run. We need to create the template cache directory recursively.
|
||||
$path = $this->tempFilesDirectory . DIRECTORY_SEPARATOR . 'browsertestbase-templatecache';
|
||||
if (!file_exists($path)) {
|
||||
mkdir($path, 0777, TRUE);
|
||||
}
|
||||
|
||||
parent::initMink();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* BrowserTestBase::refreshVariables() tries to operate on persistent storage,
|
||||
* which is only available after the installer completed.
|
||||
*/
|
||||
protected function refreshVariables() {
|
||||
// Intentionally empty as the site is not yet installed.
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a warning message is displayed when the Umami profile is selected.
|
||||
*/
|
||||
public function testUmamiProfileWarningMessage() {
|
||||
$this->drupalGet($GLOBALS['base_url'] . '/core/install.php');
|
||||
$edit = [
|
||||
'langcode' => 'en',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, 'Save and continue');
|
||||
$page = $this->getSession()->getPage();
|
||||
$warning_message = $page->find('css', '.description .messages--warning');
|
||||
$this->assertFalse($warning_message->isVisible());
|
||||
$page->selectFieldOption('profile', 'demo_umami');
|
||||
$this->assertTrue($warning_message->isVisible());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests;
|
||||
|
||||
use Behat\Mink\Driver\Selenium2Driver;
|
||||
|
||||
/**
|
||||
* Provides a driver for Selenium testing.
|
||||
*/
|
||||
class DrupalSelenium2Driver extends Selenium2Driver {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setCookie($name, $value = NULL) {
|
||||
if ($value === NULL) {
|
||||
$this->getWebDriverSession()->deleteCookie($name);
|
||||
return;
|
||||
}
|
||||
|
||||
$cookieArray = [
|
||||
'name' => $name,
|
||||
'value' => urlencode($value),
|
||||
'secure' => FALSE,
|
||||
// Unlike \Behat\Mink\Driver\Selenium2Driver::setCookie we set a domain
|
||||
// and an expire date, as otherwise cookies leak from one test site into
|
||||
// another.
|
||||
'domain' => parse_url($this->getWebDriverSession()->url(), PHP_URL_HOST),
|
||||
'expires' => time() + 80000,
|
||||
];
|
||||
|
||||
$this->getWebDriverSession()->setCookie($cookieArray);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -172,7 +172,7 @@ JS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a node, or it's specific corner, is visible in the viewport.
|
||||
* Test that a node, or its specific corner, is visible in the viewport.
|
||||
*
|
||||
* Note: Always set the viewport size. This can be done with a PhantomJS
|
||||
* startup parameter or in your test with \Behat\Mink\Session->resizeWindow().
|
||||
@@ -255,7 +255,7 @@ JS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the visibility of a node, or it's specific corner.
|
||||
* Check the visibility of a node, or its specific corner.
|
||||
*
|
||||
* @param \Behat\Mink\Element\NodeElement $node
|
||||
* A valid node.
|
||||
|
||||
@@ -15,6 +15,9 @@ abstract class JavascriptTestBase extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* To use a webdriver based approach, please use DrupalSelenium2Driver::class.
|
||||
* We will switch the default later.
|
||||
*/
|
||||
protected $minkDefaultDriverClass = PhantomJSDriver::class;
|
||||
|
||||
@@ -22,14 +25,19 @@ abstract class JavascriptTestBase extends BrowserTestBase {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initMink() {
|
||||
// Set up the template cache used by the PhantomJS mink driver.
|
||||
$path = $this->tempFilesDirectory . DIRECTORY_SEPARATOR . 'browsertestbase-templatecache';
|
||||
$this->minkDefaultDriverArgs = [
|
||||
'http://127.0.0.1:8510',
|
||||
$path,
|
||||
];
|
||||
if (!file_exists($path)) {
|
||||
mkdir($path);
|
||||
if ($this->minkDefaultDriverClass === DrupalSelenium2Driver::class) {
|
||||
$this->minkDefaultDriverArgs = ['chrome', NULL, 'http://localhost:4444/'];
|
||||
}
|
||||
elseif ($this->minkDefaultDriverClass === PhantomJSDriver::class) {
|
||||
// Set up the template cache used by the PhantomJS mink driver.
|
||||
$path = $this->tempFilesDirectory . DIRECTORY_SEPARATOR . 'browsertestbase-templatecache';
|
||||
$this->minkDefaultDriverArgs = [
|
||||
'http://127.0.0.1:8510',
|
||||
$path,
|
||||
];
|
||||
if (!file_exists($path)) {
|
||||
mkdir($path);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -63,6 +71,19 @@ abstract class JavascriptTestBase extends BrowserTestBase {
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getMinkDriverArgs() {
|
||||
if ($this->minkDefaultDriverClass === DrupalSelenium2Driver::class) {
|
||||
return getenv('MINK_DRIVER_ARGS_WEBDRIVER') ?: getenv('MINK_DRIVER_ARGS_PHANTOMJS') ?: parent::getMinkDriverArgs();
|
||||
}
|
||||
elseif ($this->minkDefaultDriverClass === PhantomJSDriver::class) {
|
||||
return getenv('MINK_DRIVER_ARGS_PHANTOMJS') ?: parent::getMinkDriverArgs();
|
||||
}
|
||||
return parent::getMinkDriverArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the element with the given CSS selector is visible.
|
||||
*
|
||||
@@ -169,4 +190,12 @@ EndOfScript;
|
||||
return $this->getSession()->evaluateScript($script) ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getHtmlOutputHeaders() {
|
||||
// The webdriver API does not support fetching headers.
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests;
|
||||
|
||||
use Zumba\Mink\Driver\PhantomJSDriver;
|
||||
|
||||
/**
|
||||
* Runs a browser test using PhantomJS.
|
||||
*
|
||||
@@ -9,6 +11,11 @@ namespace Drupal\FunctionalJavascriptTests;
|
||||
*/
|
||||
abstract class LegacyJavascriptTestBase extends JavascriptTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $minkDefaultDriverClass = PhantomJSDriver::class;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\FunctionalJavascriptTests\Tests;
|
||||
|
||||
use Drupal\FunctionalJavascriptTests\DrupalSelenium2Driver;
|
||||
|
||||
/**
|
||||
* Tests for the JSWebAssert class using webdriver.
|
||||
*
|
||||
* @group javascript
|
||||
*/
|
||||
class JSWebWithWebDriverAssertTest extends JSWebAssertTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $minkDefaultDriverClass = DrupalSelenium2Driver::class;
|
||||
|
||||
}
|
||||
@@ -55,4 +55,56 @@ class WebDriverWebAssert extends JSWebAssert {
|
||||
parent::responseHeaderNotEquals($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The use of responseHeaderContains() is not available.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the header.
|
||||
* @param string $value
|
||||
* The value to check the header against.
|
||||
*/
|
||||
public function responseHeaderContains($name, $value) {
|
||||
@trigger_error('Support for responseHeaderContains is to be dropped from Javascript tests. See https://www.drupal.org/node/2857562.');
|
||||
parent::responseHeaderContains($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The use of responseHeaderNotContains() is not available.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the header.
|
||||
* @param string $value
|
||||
* The value to check the header against.
|
||||
*/
|
||||
public function responseHeaderNotContains($name, $value) {
|
||||
@trigger_error('Support for responseHeaderNotContains is to be dropped from Javascript tests. See https://www.drupal.org/node/2857562.');
|
||||
parent::responseHeaderNotContains($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The use of responseHeaderMatches() is not available.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the header.
|
||||
* @param string $regex
|
||||
* The value to check the header against.
|
||||
*/
|
||||
public function responseHeaderMatches($name, $regex) {
|
||||
@trigger_error('Support for responseHeaderMatches is to be dropped from Javascript tests. See https://www.drupal.org/node/2857562.');
|
||||
parent::responseHeaderMatches($name, $regex);
|
||||
}
|
||||
|
||||
/**
|
||||
* The use of responseHeaderNotMatches() is not available.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the header.
|
||||
* @param string $regex
|
||||
* The value to check the header against.
|
||||
*/
|
||||
public function responseHeaderNotMatches($name, $regex) {
|
||||
@trigger_error('Support for responseHeaderNotMatches is to be dropped from Javascript tests. See https://www.drupal.org/node/2857562.');
|
||||
parent::responseHeaderNotMatches($name, $regex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
||||
/**
|
||||
* Tests legacy text asserts.
|
||||
*/
|
||||
public function testLegacyTextAsserts() {
|
||||
public function testTextAsserts() {
|
||||
$this->drupalGet('test-encoded');
|
||||
$dangerous = 'Bad html <script>alert(123);</script>';
|
||||
$sanitized = Html::escape($dangerous);
|
||||
@@ -202,7 +202,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
||||
/**
|
||||
* Tests legacy field asserts which use xpath directly.
|
||||
*/
|
||||
public function testLegacyXpathAsserts() {
|
||||
public function testXpathAsserts() {
|
||||
$this->drupalGet('test-field-xpath');
|
||||
$this->assertFieldsByValue($this->xpath("//h1[@class = 'page-title']"), NULL);
|
||||
$this->assertFieldsByValue($this->xpath('//table/tbody/tr[2]/td[1]'), 'one');
|
||||
@@ -245,7 +245,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
||||
/**
|
||||
* Tests legacy field asserts using textfields.
|
||||
*/
|
||||
public function testLegacyFieldAssertsForTextfields() {
|
||||
public function testFieldAssertsForTextfields() {
|
||||
$this->drupalGet('test-field-xpath');
|
||||
|
||||
// *** 1. assertNoField().
|
||||
@@ -387,7 +387,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
||||
/**
|
||||
* Tests legacy field asserts for options field type.
|
||||
*/
|
||||
public function testLegacyFieldAssertsForOptions() {
|
||||
public function testFieldAssertsForOptions() {
|
||||
$this->drupalGet('test-field-xpath');
|
||||
|
||||
// Option field type.
|
||||
@@ -443,7 +443,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
||||
/**
|
||||
* Tests legacy field asserts for button field type.
|
||||
*/
|
||||
public function testLegacyFieldAssertsForButton() {
|
||||
public function testFieldAssertsForButton() {
|
||||
$this->drupalGet('test-field-xpath');
|
||||
|
||||
$this->assertFieldById('edit-save', NULL);
|
||||
@@ -485,7 +485,7 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
||||
/**
|
||||
* Tests legacy field asserts for checkbox field type.
|
||||
*/
|
||||
public function testLegacyFieldAssertsForCheckbox() {
|
||||
public function testFieldAssertsForCheckbox() {
|
||||
$this->drupalGet('test-field-xpath');
|
||||
|
||||
// Part 1 - Test by name.
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\FunctionalTests\Core\Test;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests Drupal's integration with Symfony PHPUnit Bridge.
|
||||
*
|
||||
* @group Test
|
||||
* @group legacy
|
||||
*/
|
||||
class PhpUnitBridgeTest extends BrowserTestBase {
|
||||
|
||||
protected static $modules = ['deprecation_test'];
|
||||
|
||||
/**
|
||||
* @expectedDeprecation This is the deprecation message for deprecation_test_function().
|
||||
*/
|
||||
public function testSilencedError() {
|
||||
$this->assertEquals('known_return_value', deprecation_test_function());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation This is the deprecation message for deprecation_test_function().
|
||||
*/
|
||||
public function testErrorOnSiteUnderTest() {
|
||||
$this->drupalGet(Url::fromRoute('deprecation_test.route'));
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -138,7 +138,7 @@ class ContentEntityFormFieldValidationFilteringTest extends BrowserTestBase {
|
||||
// \Drupal\file\Plugin\Field\FieldWidget\FileWidget::process().
|
||||
$text_file = current($this->getTestFiles('text'));
|
||||
$edit = [
|
||||
'files[test_file_0]' => drupal_realpath($text_file->uri)
|
||||
'files[test_file_0]' => \Drupal::service('file_system')->realpath($text_file->uri)
|
||||
];
|
||||
$assert_session->elementNotExists('css', 'input#edit-test-file-0-remove-button');
|
||||
$this->drupalPostForm(NULL, $edit, 'Upload');
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\FunctionalTests\Routing;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\link\LinkItemInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that route lookup is cached by the current language.
|
||||
*
|
||||
* @group routing
|
||||
*/
|
||||
class RouteCachingLanguageTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['path', 'node', 'content_translation', 'link', 'block'];
|
||||
|
||||
/**
|
||||
* An user with permissions to administer content types.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $webUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->createContentType(['type' => 'page']);
|
||||
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
|
||||
$permissions = [
|
||||
'access administration pages',
|
||||
'administer content translation',
|
||||
'administer content types',
|
||||
'administer languages',
|
||||
'administer url aliases',
|
||||
'create content translations',
|
||||
'create page content',
|
||||
'create url aliases',
|
||||
'edit any page content',
|
||||
'translate any entity',
|
||||
];
|
||||
// Create and log in user.
|
||||
$this->webUser = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($this->webUser);
|
||||
|
||||
// Enable French language.
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
|
||||
// Enable translation for page node.
|
||||
$edit = [
|
||||
'entity_types[node]' => 1,
|
||||
'settings[node][page][translatable]' => 1,
|
||||
'settings[node][page][fields][path]' => 1,
|
||||
'settings[node][page][fields][body]' => 1,
|
||||
'settings[node][page][settings][language][language_alterable]' => 1,
|
||||
];
|
||||
$this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
|
||||
|
||||
// Create a field with settings to validate.
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => 'field_link',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'link',
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => 'page',
|
||||
'settings' => [
|
||||
'title' => DRUPAL_OPTIONAL,
|
||||
'link_type' => LinkItemInterface::LINK_GENERIC,
|
||||
],
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
entity_get_form_display('node', 'page', 'default')
|
||||
->setComponent('field_link', [
|
||||
'type' => 'link_default',
|
||||
])
|
||||
->save();
|
||||
entity_get_display('node', 'page', 'full')
|
||||
->setComponent('field_link', [
|
||||
'type' => 'link',
|
||||
])
|
||||
->save();
|
||||
|
||||
// Enable URL language detection and selection and set a prefix for both
|
||||
// languages.
|
||||
$edit = ['language_interface[enabled][language-url]' => 1];
|
||||
$this->drupalPostForm('admin/config/regional/language/detection', $edit, 'Save settings');
|
||||
$edit = ['prefix[en]' => 'en'];
|
||||
$this->drupalPostForm('admin/config/regional/language/detection/url', $edit, 'Save configuration');
|
||||
|
||||
// Reset the cache after changing the negotiation settings as that changes
|
||||
// how links are built.
|
||||
$this->resetAll();
|
||||
|
||||
$definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('node', 'page');
|
||||
$this->assertTrue($definitions['path']->isTranslatable(), 'Node path is translatable.');
|
||||
$this->assertTrue($definitions['body']->isTranslatable(), 'Node body is translatable.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates content with a link field pointing to an alias of another language.
|
||||
*
|
||||
* @dataProvider providerLanguage
|
||||
*/
|
||||
public function testLinkTranslationWithAlias($source_langcode) {
|
||||
$source_url_options = [
|
||||
'language' => ConfigurableLanguage::load($source_langcode),
|
||||
];
|
||||
|
||||
// Create a target node in the source language that is the link target.
|
||||
$edit = [
|
||||
'langcode[0][value]' => $source_langcode,
|
||||
'title[0][value]' => 'Target page',
|
||||
'path[0][alias]' => '/target-page',
|
||||
];
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'), $source_url_options);
|
||||
|
||||
// Confirm that the alias works.
|
||||
$assert_session = $this->assertSession();
|
||||
$assert_session->addressEquals($source_langcode . '/target-page');
|
||||
$assert_session->statusCodeEquals(200);
|
||||
$assert_session->pageTextContains('Target page');
|
||||
|
||||
// Create a second node that links to the first through the link field.
|
||||
$edit = [
|
||||
'langcode[0][value]' => $source_langcode,
|
||||
'title[0][value]' => 'Link page',
|
||||
'field_link[0][uri]' => '/target-page',
|
||||
'field_link[0][title]' => 'Target page',
|
||||
'path[0][alias]' => '/link-page',
|
||||
];
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save'), $source_url_options);
|
||||
|
||||
// Make sure the link node is displayed with a working link.
|
||||
$assert_session->pageTextContains('Link page');
|
||||
$this->clickLink('Target page');
|
||||
$assert_session->addressEquals($source_langcode . '/target-page');
|
||||
$assert_session->statusCodeEquals(200);
|
||||
$assert_session->pageTextContains('Target page');
|
||||
|
||||
// Clear all caches, then add a translation for the link node.
|
||||
$this->resetAll();
|
||||
|
||||
$this->drupalGet('link-page', $source_url_options);
|
||||
$this->clickLink('Translate');
|
||||
$this->clickLink(t('Add'));
|
||||
|
||||
// Do not change the link field.
|
||||
$edit = [
|
||||
'title[0][value]' => 'Translated link page',
|
||||
'path[0][alias]' => '/translated-link-page',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, 'Save (this translation)');
|
||||
|
||||
$assert_session->pageTextContains('Translated link page');
|
||||
|
||||
// @todo Clicking on the link does not include the language prefix.
|
||||
$this->drupalGet('target-page', $source_url_options);
|
||||
$assert_session->statusCodeEquals(200);
|
||||
$assert_session->pageTextContains('Target page');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testFromUri().
|
||||
*/
|
||||
public function providerLanguage() {
|
||||
return [
|
||||
['en'],
|
||||
['fr'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\FunctionalTests\Routing;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests the route cache when the language is not in the path.
|
||||
*
|
||||
* @group language
|
||||
*/
|
||||
class RouteCachingNonPathLanguageNegotiationTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['language', 'block'];
|
||||
|
||||
/**
|
||||
* The admin user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create and log in user.
|
||||
$this->adminUser = $this->drupalCreateUser(['administer blocks', 'administer languages', 'access administration pages']);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Add language.
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
|
||||
// Enable session language detection and selection.
|
||||
$edit = [
|
||||
'language_interface[enabled][language-url]' => FALSE,
|
||||
'language_interface[enabled][language-session]' => TRUE,
|
||||
];
|
||||
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
|
||||
|
||||
// A more common scenario is domain-based negotiation but that can not be
|
||||
// tested. Session negotiation by default is not considered by the URL
|
||||
// language type that is used to resolve the alias. Explicitly enable
|
||||
// that to be able to test this scenario.
|
||||
// @todo Improve in https://www.drupal.org/project/drupal/issues/1125428.
|
||||
$this->config('language.types')
|
||||
->set('negotiation.language_url.enabled', ['language-session' => 0])
|
||||
->save();
|
||||
|
||||
// Enable the language switching block.
|
||||
$this->drupalPlaceBlock('language_block:' . LanguageInterface::TYPE_INTERFACE, [
|
||||
'id' => 'test_language_block',
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests aliases when the negotiated language is not in the path.
|
||||
*/
|
||||
public function testAliases() {
|
||||
// Switch to French and try to access the now inaccessible block.
|
||||
$this->drupalGet('');
|
||||
|
||||
// Create an alias for user/UID just for en, make sure that this is a 404
|
||||
// on the french page exist in english, no matter which language is
|
||||
// checked first. Create the alias after visiting frontpage to make sure
|
||||
// there is no existing cache entry for this that affects the tests.
|
||||
\Drupal::service('path.alias_storage')->save('/user/' . $this->adminUser->id(), '/user-page', 'en');
|
||||
|
||||
$this->clickLink('French');
|
||||
$this->drupalGet('user-page');
|
||||
$this->assertSession()->statusCodeEquals(404);
|
||||
|
||||
// Switch to english, make sure it works now.
|
||||
$this->clickLink('English');
|
||||
$this->drupalGet('user-page');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
|
||||
// Clear cache and repeat the check, this time with english first.
|
||||
$this->resetAll();
|
||||
$this->drupalGet('user-page');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
|
||||
$this->clickLink('French');
|
||||
$this->drupalGet('user-page');
|
||||
$this->assertSession()->statusCodeEquals(404);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -374,7 +374,6 @@ abstract class UpdatePathTestBase extends BrowserTestBase {
|
||||
|
||||
// Ensure that the update hooks updated all entity schema.
|
||||
$needs_updates = \Drupal::entityDefinitionUpdateManager()->needsUpdates();
|
||||
$this->assertFalse($needs_updates, 'After all updates ran, entity schema is up to date.');
|
||||
if ($needs_updates) {
|
||||
foreach (\Drupal::entityDefinitionUpdateManager()
|
||||
->getChangeSummary() as $entity_type_id => $summary) {
|
||||
@@ -382,6 +381,9 @@ abstract class UpdatePathTestBase extends BrowserTestBase {
|
||||
$this->fail($message);
|
||||
}
|
||||
}
|
||||
// The above calls to `fail()` should prevent this from ever being
|
||||
// called, but it is here in case something goes really wrong.
|
||||
$this->assertFalse($needs_updates, 'After all updates ran, entity schema is up to date.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,12 +81,6 @@ class DefaultConfigTest extends KernelTestBase {
|
||||
/** @var \Drupal\Core\Extension\ModuleInstallerInterface $module_installer */
|
||||
$module_installer = $this->container->get('module_installer');
|
||||
|
||||
// @todo https://www.drupal.org/node/2308745 Rest has an implicit dependency
|
||||
// on the Node module remove once solved.
|
||||
if (in_array($module, ['rest', 'hal'])) {
|
||||
$module_installer->install(['node']);
|
||||
}
|
||||
|
||||
// Work out any additional modules and themes that need installing to create
|
||||
// an optional config.
|
||||
$optional_config_storage = new FileStorage($module_path . InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Action;
|
||||
|
||||
use Drupal\Core\Action\Plugin\Action\Derivative\EntityPublishedActionDeriver;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRevPub;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\system\Entity\Action;
|
||||
|
||||
/**
|
||||
* @group Action
|
||||
*/
|
||||
class PublishActionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'entity_test', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('entity_test_mulrevpub');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\Derivative\EntityPublishedActionDeriver::getDerivativeDefinitions
|
||||
*/
|
||||
public function testGetDerivativeDefinitions() {
|
||||
$deriver = new EntityPublishedActionDeriver(\Drupal::entityTypeManager());
|
||||
$this->assertArraySubset([
|
||||
'entity_test_mulrevpub' => [
|
||||
'type' => 'entity_test_mulrevpub',
|
||||
'label' => 'Save test entity - revisions, data table, and published interface',
|
||||
'action_label' => 'Save',
|
||||
],
|
||||
], $deriver->getDerivativeDefinitions([
|
||||
'action_label' => 'Save',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\PublishAction::execute
|
||||
*/
|
||||
public function testPublishAction() {
|
||||
$entity = EntityTestMulRevPub::create(['name' => 'test']);
|
||||
$entity->setUnpublished()->save();
|
||||
|
||||
$action = Action::create([
|
||||
'id' => 'entity_publish_action',
|
||||
'plugin' => 'entity:publish_action:entity_test_mulrevpub',
|
||||
]);
|
||||
$action->save();
|
||||
$this->assertFalse($entity->isPublished());
|
||||
$action->execute([$entity]);
|
||||
$this->assertTrue($entity->isPublished());
|
||||
$this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\UnpublishAction::execute
|
||||
*/
|
||||
public function testUnpublishAction() {
|
||||
$entity = EntityTestMulRevPub::create(['name' => 'test']);
|
||||
$entity->setPublished()->save();
|
||||
|
||||
$action = Action::create([
|
||||
'id' => 'entity_unpublish_action',
|
||||
'plugin' => 'entity:unpublish_action:entity_test_mulrevpub',
|
||||
]);
|
||||
$action->save();
|
||||
$this->assertTrue($entity->isPublished());
|
||||
$action->execute([$entity]);
|
||||
$this->assertFalse($entity->isPublished());
|
||||
$this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Action;
|
||||
|
||||
use Drupal\Core\Action\Plugin\Action\Derivative\EntityChangedActionDeriver;
|
||||
use Drupal\entity_test\Entity\EntityTestMulChanged;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\system\Entity\Action;
|
||||
|
||||
/**
|
||||
* @group Action
|
||||
*/
|
||||
class SaveActionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'entity_test', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('entity_test_mul_changed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\Derivative\EntityChangedActionDeriver::getDerivativeDefinitions
|
||||
*/
|
||||
public function testGetDerivativeDefinitions() {
|
||||
$deriver = new EntityChangedActionDeriver(\Drupal::entityTypeManager());
|
||||
$this->assertArraySubset([
|
||||
'entity_test_mul_changed' => [
|
||||
'type' => 'entity_test_mul_changed',
|
||||
'label' => 'Save test entity - data table',
|
||||
'action_label' => 'Save',
|
||||
],
|
||||
], $deriver->getDerivativeDefinitions([
|
||||
'action_label' => 'Save',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Action\Plugin\Action\SaveAction::execute
|
||||
*/
|
||||
public function testSaveAction() {
|
||||
$entity = EntityTestMulChanged::create(['name' => 'test']);
|
||||
$entity->save();
|
||||
$saved_time = $entity->getChangedTime();
|
||||
|
||||
$action = Action::create([
|
||||
'id' => 'entity_save_action',
|
||||
'plugin' => 'entity:save_action:entity_test_mul_changed',
|
||||
]);
|
||||
$action->save();
|
||||
$action->execute([$entity]);
|
||||
$this->assertNotSame($saved_time, $entity->getChangedTime());
|
||||
$this->assertArraySubset(['module' => ['entity_test']], $action->getDependencies());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -108,6 +108,10 @@ class ResolvedLibraryDefinitionsFilesMatchTest extends KernelTestBase {
|
||||
}
|
||||
return TRUE;
|
||||
});
|
||||
// Remove demo_umami_content module as its install hook creates content
|
||||
// that relies on the presence of entity tables and various other elements
|
||||
// not present in a kernel test.
|
||||
unset($all_modules['demo_umami_content']);
|
||||
$this->allModules = array_keys($all_modules);
|
||||
$this->allModules[] = 'system';
|
||||
sort($this->allModules);
|
||||
|
||||
@@ -20,10 +20,4 @@ class DrupalSetMessageTest extends KernelTestBase {
|
||||
$this->assertEquals('A message: bar', (string) $messages['status'][0]);
|
||||
}
|
||||
|
||||
protected function tearDown() {
|
||||
// Clear session to prevent global leakage.
|
||||
unset($_SESSION['messages']);
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ class ConfigFileContentTest extends KernelTestBase {
|
||||
$this->assertIdentical($config->get('null'), NULL);
|
||||
|
||||
// Read false that had been nested in an array value.
|
||||
$this->assertSame($config->get($casting_array_false_value_key), FALSE, "Nested boolean FALSE value returned FALSE.");
|
||||
$this->assertSame(FALSE, $config->get($casting_array_false_value_key), "Nested boolean FALSE value returned FALSE.");
|
||||
|
||||
// Unset a top level value.
|
||||
$config->clear($key);
|
||||
|
||||
@@ -67,9 +67,15 @@ class QueryTest extends DatabaseTestBase {
|
||||
public function testConditionOperatorArgumentsSQLInjection() {
|
||||
$injection = "IS NOT NULL) ;INSERT INTO {test} (name) VALUES ('test12345678'); -- ";
|
||||
|
||||
// Convert errors to exceptions for testing purposes below.
|
||||
set_error_handler(function ($severity, $message, $filename, $lineno) {
|
||||
throw new \ErrorException($message, 0, $severity, $filename, $lineno);
|
||||
$previous_error_handler = set_error_handler(function ($severity, $message, $filename, $lineno, $context) use (&$previous_error_handler) {
|
||||
// Normalize the filename to use UNIX directory separators.
|
||||
if (preg_match('@core/lib/Drupal/Core/Database/Query/Condition.php$@', str_replace(DIRECTORY_SEPARATOR, '/', $filename))) {
|
||||
// Convert errors to exceptions for testing purposes below.
|
||||
throw new \ErrorException($message, 0, $severity, $filename, $lineno);
|
||||
}
|
||||
if ($previous_error_handler) {
|
||||
return $previous_error_handler($severity, $message, $filename, $lineno, $context);
|
||||
}
|
||||
});
|
||||
try {
|
||||
$result = db_select('test', 't')
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Datetime;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests timestamp schema.
|
||||
*
|
||||
* @group Common
|
||||
*/
|
||||
class TimestampSchemaTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['entity_test', 'field', 'field_timestamp_test'];
|
||||
|
||||
/**
|
||||
* Tests if the timestamp field schema is validated.
|
||||
*/
|
||||
public function testTimestampSchema() {
|
||||
$this->installConfig(['field_timestamp_test']);
|
||||
// Make at least an assertion.
|
||||
$this->assertTrue(TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -297,7 +297,7 @@ class ContentEntityCloneTest extends EntityKernelTestBase {
|
||||
// Retrieve the entity properties.
|
||||
$reflection = new \ReflectionClass($entity);
|
||||
$properties = $reflection->getProperties(~\ReflectionProperty::IS_STATIC);
|
||||
$translation_unique_properties = ['activeLangcode', 'translationInitialize', 'fieldDefinitions', 'languages', 'langcodeKey', 'defaultLangcode', 'defaultLangcodeKey', 'validated', 'validationRequired', 'entityTypeId', 'typedData', 'cacheContexts', 'cacheTags', 'cacheMaxAge', '_serviceIds'];
|
||||
$translation_unique_properties = ['activeLangcode', 'translationInitialize', 'fieldDefinitions', 'languages', 'langcodeKey', 'defaultLangcode', 'defaultLangcodeKey', 'revisionTranslationAffectedKey', 'validated', 'validationRequired', 'entityTypeId', 'typedData', 'cacheContexts', 'cacheTags', 'cacheMaxAge', '_serviceIds'];
|
||||
|
||||
foreach ($properties as $property) {
|
||||
// Modify each entity property on the clone and assert that the change is
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
|
||||
/**
|
||||
* Tests the ContentEntityStorageBase::createWithSampleValues method.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\ContentEntityStorageBase
|
||||
* @group Entity
|
||||
*/
|
||||
class CreateSampleEntityTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'field', 'filter', 'text', 'file', 'user', 'node', 'comment', 'taxonomy'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setup();
|
||||
|
||||
$this->installEntitySchema('file');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('node_type');
|
||||
$this->installEntitySchema('file');
|
||||
$this->installEntitySchema('comment');
|
||||
$this->installEntitySchema('comment_type');
|
||||
$this->installEntitySchema('taxonomy_vocabulary');
|
||||
$this->installEntitySchema('taxonomy_term');
|
||||
$this->entityTypeManager = $this->container->get('entity_type.manager');
|
||||
NodeType::create(['type' => 'article', 'name' => 'Article'])->save();
|
||||
NodeType::create(['type' => 'page', 'name' => 'Page'])->save();
|
||||
Vocabulary::create(['name' => 'Tags', 'vid' => 'tags'])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests sample value content entity creation of all types.
|
||||
*
|
||||
* @covers ::createWithSampleValues
|
||||
*/
|
||||
public function testSampleValueContentEntity() {
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $definition) {
|
||||
if ($definition->entityClassImplements(FieldableEntityInterface::class)) {
|
||||
$label = $definition->getKey('label');
|
||||
$values = [];
|
||||
if ($label) {
|
||||
$title = $this->randomString();
|
||||
$values[$label] = $title;
|
||||
}
|
||||
// Create sample entities with bundles.
|
||||
if ($bundle_type = $definition->getBundleEntityType()) {
|
||||
foreach ($this->entityTypeManager->getStorage($bundle_type)->loadMultiple() as $bundle) {
|
||||
$entity = $this->entityTypeManager->getStorage($entity_type_id)->createWithSampleValues($bundle->id(), $values);
|
||||
$violations = $entity->validate();
|
||||
$this->assertCount(0, $violations);
|
||||
if ($label) {
|
||||
$this->assertEquals($title, $entity->label());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create sample entities without bundles.
|
||||
else {
|
||||
$entity = $this->entityTypeManager->getStorage($entity_type_id)->createWithSampleValues(FALSE, $values);
|
||||
$violations = $entity->validate();
|
||||
$this->assertCount(0, $violations);
|
||||
if ($label) {
|
||||
$this->assertEquals($title, $entity->label());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use Drupal\Core\Access\AccessibleInterface;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Session\AnonymousUserSession;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\entity_test\Entity\EntityTestStringId;
|
||||
use Drupal\entity_test\Entity\EntityTestDefaultAccess;
|
||||
use Drupal\entity_test\Entity\EntityTestNoUuid;
|
||||
use Drupal\entity_test\Entity\EntityTestLabel;
|
||||
@@ -18,6 +19,7 @@ use Drupal\user\Entity\User;
|
||||
/**
|
||||
* Tests the entity access control handler.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\EntityAccessControlHandler
|
||||
* @group Entity
|
||||
*/
|
||||
class EntityAccessControlHandlerTest extends EntityLanguageTestBase {
|
||||
@@ -30,6 +32,7 @@ class EntityAccessControlHandlerTest extends EntityLanguageTestBase {
|
||||
|
||||
$this->installEntitySchema('entity_test_no_uuid');
|
||||
$this->installEntitySchema('entity_test_rev');
|
||||
$this->installEntitySchema('entity_test_string_id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,4 +296,73 @@ class EntityAccessControlHandlerTest extends EntityLanguageTestBase {
|
||||
$this->assertEqual($state->get('entity_test_entity_test_access'), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the default access handling for the ID and UUID fields.
|
||||
*
|
||||
* @covers ::fieldAccess
|
||||
* @dataProvider providerTestFieldAccess
|
||||
*/
|
||||
public function testFieldAccess($entity_class, array $entity_create_values, $expected_id_create_access) {
|
||||
// Set up a non-admin user that is allowed to create and update test
|
||||
// entities.
|
||||
\Drupal::currentUser()->setAccount($this->createUser(['uid' => 2], ['administer entity_test content']));
|
||||
|
||||
// Create the entity to test field access with.
|
||||
$entity = $entity_class::create($entity_create_values);
|
||||
|
||||
// On newly-created entities, field access must allow setting the UUID
|
||||
// field.
|
||||
$this->assertTrue($entity->get('uuid')->access('edit'));
|
||||
$this->assertTrue($entity->get('uuid')->access('edit', NULL, TRUE)->isAllowed());
|
||||
// On newly-created entities, field access will not allow setting the ID
|
||||
// field if the ID is of type serial. It will allow access if it is of type
|
||||
// string.
|
||||
$this->assertEquals($expected_id_create_access, $entity->get('id')->access('edit'));
|
||||
$this->assertEquals($expected_id_create_access, $entity->get('id')->access('edit', NULL, TRUE)->isAllowed());
|
||||
|
||||
// Save the entity and check that we can not update the ID or UUID fields
|
||||
// anymore.
|
||||
$entity->save();
|
||||
|
||||
// If the ID has been set as part of the create ensure it has been set
|
||||
// correctly.
|
||||
if (isset($entity_create_values['id'])) {
|
||||
$this->assertSame($entity_create_values['id'], $entity->id());
|
||||
}
|
||||
// The UUID is hard-coded by the data provider.
|
||||
$this->assertSame('60e3a179-79ed-4653-ad52-5e614c8e8fbe', $entity->uuid());
|
||||
$this->assertFalse($entity->get('uuid')->access('edit'));
|
||||
$access_result = $entity->get('uuid')->access('edit', NULL, TRUE);
|
||||
$this->assertTrue($access_result->isForbidden());
|
||||
$this->assertEquals('The entity UUID cannot be changed', $access_result->getReason());
|
||||
|
||||
// Ensure the ID is still not allowed to be edited.
|
||||
$this->assertFalse($entity->get('id')->access('edit'));
|
||||
$access_result = $entity->get('id')->access('edit', NULL, TRUE);
|
||||
$this->assertTrue($access_result->isForbidden());
|
||||
$this->assertEquals('The entity ID cannot be changed', $access_result->getReason());
|
||||
}
|
||||
|
||||
public function providerTestFieldAccess() {
|
||||
return [
|
||||
'serial ID entity' => [
|
||||
EntityTest::class,
|
||||
[
|
||||
'name' => 'A test entity',
|
||||
'uuid' => '60e3a179-79ed-4653-ad52-5e614c8e8fbe',
|
||||
],
|
||||
FALSE
|
||||
],
|
||||
'string ID entity' => [
|
||||
EntityTestStringId::class,
|
||||
[
|
||||
'id' => 'a_test_entity',
|
||||
'name' => 'A test entity',
|
||||
'uuid' => '60e3a179-79ed-4653-ad52-5e614c8e8fbe',
|
||||
],
|
||||
TRUE
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ class EntityBundleFieldTest extends EntityKernelTestBase {
|
||||
$entity->save();
|
||||
entity_test_delete_bundle('custom');
|
||||
|
||||
$table = $table_mapping->getDedicatedDataTableName($entity->getFieldDefinition('custom_bundle_field'));
|
||||
$table = $table_mapping->getDedicatedDataTableName($entity->getFieldDefinition('custom_bundle_field'), TRUE);
|
||||
$result = $this->database->select($table, 'f')
|
||||
->condition('f.entity_id', $entity->id())
|
||||
->condition('deleted', 1)
|
||||
@@ -105,9 +105,10 @@ class EntityBundleFieldTest extends EntityKernelTestBase {
|
||||
$field_map = \Drupal::entityManager()->getFieldMap();
|
||||
$this->assertFalse(isset($field_map['entity_test']['custom_bundle_field']));
|
||||
|
||||
// @todo Test field purge and table deletion once supported. See
|
||||
// https://www.drupal.org/node/2282119.
|
||||
// $this->assertFalse($this->database->schema()->tableExists($table), 'Custom field table was deleted');
|
||||
// Purge field data, and check that the storage definition has been
|
||||
// completely removed once the data is purged.
|
||||
field_purge_batch(10);
|
||||
$this->assertFalse($this->database->schema()->tableExists($table), 'Custom field table was deleted');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+591
@@ -0,0 +1,591 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
/**
|
||||
* Test decoupled translation revisions.
|
||||
*
|
||||
* @group entity
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\ContentEntityStorageBase
|
||||
*/
|
||||
class EntityDecoupledTranslationRevisionsTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'system',
|
||||
'entity_test',
|
||||
'language',
|
||||
];
|
||||
|
||||
/**
|
||||
* The entity type bundle info service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
|
||||
*/
|
||||
protected $bundleInfo;
|
||||
|
||||
/**
|
||||
* The entity storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\ContentEntityStorageInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* The translations of the test entity.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\ContentEntityInterface[]
|
||||
*/
|
||||
protected $translations;
|
||||
|
||||
/**
|
||||
* The previous revision identifiers for the various revision translations.
|
||||
*
|
||||
* @var int[]
|
||||
*/
|
||||
protected $previousRevisionId = [];
|
||||
|
||||
/**
|
||||
* The previous unstranslatable field value.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $previousUntranslatableFieldValue;
|
||||
|
||||
/**
|
||||
* The current edit sequence step index.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $stepIndex;
|
||||
|
||||
/**
|
||||
* The current edit sequence step info.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $stepInfo;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$entity_type_id = 'entity_test_mulrev';
|
||||
$this->installEntitySchema($entity_type_id);
|
||||
$this->storage = $this->container->get('entity_type.manager')
|
||||
->getStorage($entity_type_id);
|
||||
|
||||
$this->installConfig(['language']);
|
||||
$langcodes = ['it', 'fr'];
|
||||
foreach ($langcodes as $langcode) {
|
||||
ConfigurableLanguage::createFromLangcode($langcode)->save();
|
||||
}
|
||||
|
||||
$values = [
|
||||
'name' => $this->randomString(),
|
||||
'status' => 1,
|
||||
];
|
||||
User::create($values)->save();
|
||||
|
||||
// Make sure entity bundles are translatable.
|
||||
$this->state->set('entity_test.translation', TRUE);
|
||||
$this->bundleInfo = \Drupal::service('entity_type.bundle.info');
|
||||
$this->bundleInfo->clearCachedBundles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testDecoupledDefaultRevisions.
|
||||
*/
|
||||
public function dataTestDecoupledPendingRevisions() {
|
||||
$sets = [];
|
||||
|
||||
$sets['Intermixed languages - No initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
];
|
||||
|
||||
$sets['Intermixed languages - With initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
];
|
||||
|
||||
$sets['Alternate languages - No initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['en', FALSE],
|
||||
['en', FALSE],
|
||||
['en', TRUE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', FALSE],
|
||||
['it', FALSE],
|
||||
['it', TRUE],
|
||||
];
|
||||
|
||||
$sets['Alternate languages - With initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['en', TRUE],
|
||||
['en', FALSE],
|
||||
['en', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['it', FALSE],
|
||||
['it', FALSE],
|
||||
['it', TRUE],
|
||||
];
|
||||
|
||||
$sets['Multiple languages - No initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['it', FALSE],
|
||||
['fr', FALSE],
|
||||
['en', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', FALSE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['fr', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', TRUE],
|
||||
];
|
||||
|
||||
$sets['Multiple languages - With initial default translation'][] = [
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', TRUE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', FALSE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['fr', TRUE],
|
||||
['it', TRUE],
|
||||
['fr', TRUE],
|
||||
];
|
||||
|
||||
return $sets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test decoupled default revisions.
|
||||
*
|
||||
* @param array[] $sequence
|
||||
* An array with arrays of arguments for the ::doSaveNewRevision() method as
|
||||
* values. Every child array corresponds to a method invocation.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
*
|
||||
* @dataProvider dataTestDecoupledPendingRevisions
|
||||
*/
|
||||
public function testDecoupledPendingRevisions($sequence) {
|
||||
$revision_id = $this->doTestEditSequence($sequence);
|
||||
$this->assertEquals(count($sequence), $revision_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testUntranslatableFields.
|
||||
*/
|
||||
public function dataTestUntranslatableFields() {
|
||||
$sets = [];
|
||||
|
||||
$sets['Default behavior - Untranslatable fields affect all revisions'] = [
|
||||
[
|
||||
['en', TRUE, TRUE],
|
||||
['it', FALSE, TRUE, FALSE],
|
||||
['en', FALSE, TRUE, FALSE],
|
||||
['en', TRUE, TRUE],
|
||||
['it', TRUE, TRUE],
|
||||
['en', FALSE],
|
||||
['it', FALSE],
|
||||
['en', TRUE],
|
||||
['it', TRUE],
|
||||
],
|
||||
FALSE,
|
||||
];
|
||||
|
||||
$sets['Alternative behavior - Untranslatable fields affect only default translation'] = [
|
||||
[
|
||||
['en', TRUE, TRUE],
|
||||
['it', FALSE, TRUE, FALSE],
|
||||
['en', FALSE, TRUE],
|
||||
['it', TRUE, TRUE, FALSE],
|
||||
['it', FALSE],
|
||||
['it', TRUE],
|
||||
['en', TRUE, TRUE],
|
||||
['it', FALSE],
|
||||
['en', FALSE],
|
||||
['it', TRUE],
|
||||
['en', TRUE, TRUE],
|
||||
],
|
||||
TRUE,
|
||||
];
|
||||
|
||||
return $sets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that untranslatable fields are handled correctly.
|
||||
*
|
||||
* @param array[] $sequence
|
||||
* An array with arrays of arguments for the ::doSaveNewRevision() method as
|
||||
* values. Every child array corresponds to a method invocation.
|
||||
*
|
||||
* @param bool $default_translation_affected
|
||||
* Whether untranslatable field changes affect all revisions or only the
|
||||
* default revision.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
* @covers \Drupal\Core\Entity\Plugin\Validation\Constraint\EntityUntranslatableFieldsConstraintValidator::validate
|
||||
*
|
||||
* @dataProvider dataTestUntranslatableFields
|
||||
*/
|
||||
public function testUntranslatableFields($sequence, $default_translation_affected) {
|
||||
// Configure the untranslatable fields edit mode.
|
||||
$this->state->set('entity_test.untranslatable_fields.default_translation_affected', $default_translation_affected);
|
||||
$this->bundleInfo->clearCachedBundles();
|
||||
|
||||
// Test that a new entity is always valid.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->set('non_mul_field', 0);
|
||||
$violations = $entity->validate();
|
||||
$this->assertEmpty($violations);
|
||||
|
||||
// Test the specified sequence.
|
||||
$this->doTestEditSequence($sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually tests an edit step sequence.
|
||||
*
|
||||
* @param array[] $sequence
|
||||
* An array of sequence steps.
|
||||
*
|
||||
* @return int
|
||||
* The latest saved revision id.
|
||||
*/
|
||||
protected function doTestEditSequence($sequence) {
|
||||
$revision_id = NULL;
|
||||
foreach ($sequence as $index => $step) {
|
||||
$this->stepIndex = $index;
|
||||
$revision_id = call_user_func_array([$this, 'doEditStep'], $step);
|
||||
}
|
||||
return $revision_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a new revision of the test entity.
|
||||
*
|
||||
* @param string $active_langcode
|
||||
* The language of the translation for which a new revision will be saved.
|
||||
* @param bool $default_revision
|
||||
* Whether the revision should be flagged as the default revision.
|
||||
* @param bool $untranslatable_update
|
||||
* (optional) Whether an untranslatable field update should be performed.
|
||||
* Defaults to FALSE.
|
||||
* @param bool $valid
|
||||
* (optional) Whether entity validation is expected to succeed. Defaults to
|
||||
* TRUE.
|
||||
*
|
||||
* @return int
|
||||
* The new revision identifier.
|
||||
*
|
||||
* @throws \Drupal\Core\Entity\EntityStorageException
|
||||
*/
|
||||
protected function doEditStep($active_langcode, $default_revision, $untranslatable_update = FALSE, $valid = TRUE) {
|
||||
$this->stepInfo = [$active_langcode, $default_revision, $untranslatable_update, $valid];
|
||||
|
||||
// If changes to untranslatable fields affect only the default translation,
|
||||
// we can different values for untranslatable fields in the various
|
||||
// revision translations, so we need to track their previous value per
|
||||
// language.
|
||||
$all_translations_affected = !$this->state->get('entity_test.untranslatable_fields.default_translation_affected');
|
||||
$previous_untranslatable_field_langcode = $all_translations_affected ? LanguageInterface::LANGCODE_DEFAULT : $active_langcode;
|
||||
|
||||
// Initialize previous data tracking.
|
||||
if (!isset($this->translations)) {
|
||||
$this->translations[$active_langcode] = EntityTestMulRev::create();
|
||||
$this->previousRevisionId[$active_langcode] = 0;
|
||||
$this->previousUntranslatableFieldValue[$previous_untranslatable_field_langcode] = NULL;
|
||||
}
|
||||
if (!isset($this->translations[$active_langcode])) {
|
||||
$this->translations[$active_langcode] = reset($this->translations)->addTranslation($active_langcode);
|
||||
$this->previousRevisionId[$active_langcode] = 0;
|
||||
$this->previousUntranslatableFieldValue[$active_langcode] = NULL;
|
||||
}
|
||||
|
||||
// We want to update previous data only if we expect a valid result,
|
||||
// otherwise we would be just polluting it with invalid values.
|
||||
if ($valid) {
|
||||
$entity = &$this->translations[$active_langcode];
|
||||
$previous_revision_id = &$this->previousRevisionId[$active_langcode];
|
||||
$previous_untranslatable_field_value = &$this->previousUntranslatableFieldValue[$previous_untranslatable_field_langcode];
|
||||
}
|
||||
else {
|
||||
$entity = clone $this->translations[$active_langcode];
|
||||
$previous_revision_id = $this->previousRevisionId[$active_langcode];
|
||||
$previous_untranslatable_field_value = $this->previousUntranslatableFieldValue[$previous_untranslatable_field_langcode];
|
||||
}
|
||||
|
||||
// Check that after instantiating a new revision for the specified
|
||||
// translation, we are resuming work from where we left the last time. If
|
||||
// that is the case, the label generated for the previous revision should
|
||||
// match the stored one.
|
||||
if (!$entity->isNew()) {
|
||||
$previous_label = NULL;
|
||||
if (!$entity->isNewTranslation()) {
|
||||
$previous_label = $this->generateNewEntityLabel($entity, $previous_revision_id);
|
||||
$latest_affected_revision_id = $this->storage->getLatestTranslationAffectedRevisionId($entity->id(), $entity->language()->getId());
|
||||
}
|
||||
else {
|
||||
// Normally it would make sense to load the default revision in this
|
||||
// case, however that would mean simulating here the logic that we need
|
||||
// to test, thus "masking" possible flaws. To avoid that, we simply
|
||||
// pretend we are starting from an earlier non translated revision.
|
||||
// This ensures that the we can check that the merging logic is applied
|
||||
// also when adding a new translation.
|
||||
$latest_affected_revision_id = 1;
|
||||
}
|
||||
$previous_revision_id = (int) $entity->getLoadedRevisionId();
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $latest_affected_revision */
|
||||
$latest_affected_revision = $this->storage->loadRevision($latest_affected_revision_id);
|
||||
$translation = $latest_affected_revision->hasTranslation($active_langcode) ?
|
||||
$latest_affected_revision->getTranslation($active_langcode) : $latest_affected_revision->addTranslation($active_langcode);
|
||||
$entity = $this->storage->createRevision($translation, $default_revision);
|
||||
$this->assertEquals($default_revision, $entity->isDefaultRevision());
|
||||
$this->assertEquals($translation->getLoadedRevisionId(), $entity->getLoadedRevisionId());
|
||||
$this->assertEquals($previous_label, $entity->label(), $this->formatMessage('Loaded translatable field value does not match the previous one.'));
|
||||
}
|
||||
|
||||
// Check that the previous untranslatable field value is loaded in the new
|
||||
// revision as expected. When we are dealing with a non default translation
|
||||
// the expected value is always the one stored in the default revision, as
|
||||
// untranslatable fields can only be changed in the default translation or
|
||||
// in the default revision, depending on the configured mode.
|
||||
$value = $entity->get('non_mul_field')->value;
|
||||
if (isset($previous_untranslatable_field_value)) {
|
||||
$this->assertEquals($previous_untranslatable_field_value, $value, $this->formatMessage('Loaded untranslatable field value does not match the previous one.'));
|
||||
}
|
||||
elseif (!$entity->isDefaultTranslation()) {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $default_revision */
|
||||
$default_revision = $this->storage->loadUnchanged($entity->id());
|
||||
$expected_value = $default_revision->get('non_mul_field')->value;
|
||||
$this->assertEquals($expected_value, $value, $this->formatMessage('Loaded untranslatable field value does not match the previous one.'));
|
||||
}
|
||||
|
||||
// Perform a change and store it.
|
||||
$label = $this->generateNewEntityLabel($entity, $previous_revision_id, TRUE);
|
||||
$entity->set('name', $label);
|
||||
if ($untranslatable_update) {
|
||||
// Store the revision ID of the previous untranslatable fields update in
|
||||
// the new value, besides the upcoming revision ID. Useful to analyze test
|
||||
// failures.
|
||||
$prev = 0;
|
||||
if (isset($previous_untranslatable_field_value)) {
|
||||
preg_match('/^\d+ -> (\d+)$/', $previous_untranslatable_field_value, $matches);
|
||||
$prev = $matches[1];
|
||||
}
|
||||
$value = $prev . ' -> ' . ($entity->getLoadedRevisionId() + 1);
|
||||
$entity->set('non_mul_field', $value);
|
||||
$previous_untranslatable_field_value = $value;
|
||||
}
|
||||
|
||||
$violations = $entity->validate();
|
||||
$messages = [];
|
||||
foreach ($violations as $violation) {
|
||||
/** \Symfony\Component\Validator\ConstraintViolationInterface */
|
||||
$messages[] = $violation->getMessage();
|
||||
}
|
||||
$this->assertEquals($valid, !$violations->count(), $this->formatMessage('Validation does not match the expected result: %s', implode(', ', $messages)));
|
||||
|
||||
if ($valid) {
|
||||
$entity->save();
|
||||
|
||||
// Reload the current revision translation and the default revision to
|
||||
// make sure data was stored correctly.
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $this->storage->loadRevision($entity->getRevisionId());
|
||||
$entity = $entity->getTranslation($active_langcode);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $default_entity */
|
||||
$default_entity = $this->storage->loadUnchanged($entity->id());
|
||||
|
||||
// Verify that the values for the current revision translation match the
|
||||
// expected ones, while for the other translations they match the default
|
||||
// revision. We also need to verify that only the current revision
|
||||
// translation was marked as affected.
|
||||
foreach ($entity->getTranslationLanguages() as $langcode => $language) {
|
||||
$translation = $entity->getTranslation($langcode);
|
||||
$rta_expected = $langcode == $active_langcode || ($untranslatable_update && $all_translations_affected);
|
||||
$this->assertEquals($rta_expected, $translation->isRevisionTranslationAffected(), $this->formatMessage("'$langcode' translation incorrectly affected"));
|
||||
$label_expected = $label;
|
||||
if ($langcode !== $active_langcode) {
|
||||
$default_translation = $default_entity->hasTranslation($langcode) ? $default_entity->getTranslation($langcode) : $default_entity;
|
||||
$label_expected = $default_translation->label();
|
||||
}
|
||||
$this->assertEquals($label_expected, $translation->label(), $this->formatMessage("Incorrect '$langcode' translation label"));
|
||||
}
|
||||
}
|
||||
|
||||
return $entity->getRevisionId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new label for the specified revision.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\ContentEntityInterface $revision
|
||||
* An entity object.
|
||||
* @param int $previous_revision_id
|
||||
* The previous revision identifier for this revision translation.
|
||||
* @param bool $next
|
||||
* (optional) Whether the label describes the current revision or the one
|
||||
* to be created. Defaults to FALSE.
|
||||
*
|
||||
* @return string
|
||||
* A revision label.
|
||||
*/
|
||||
protected function generateNewEntityLabel(ContentEntityInterface $revision, $previous_revision_id, $next = FALSE) {
|
||||
$language_label = $revision->language()->getName();
|
||||
$revision_type = $revision->isDefaultRevision() ? 'Default' : 'Pending';
|
||||
$revision_id = $next ? $this->storage->getLatestRevisionId($revision->id()) + 1 : $revision->getLoadedRevisionId();
|
||||
return sprintf('%s (%s %d -> %d)', $language_label, $revision_type, $previous_revision_id, $revision_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an assertion message.
|
||||
*
|
||||
* @param string $message
|
||||
* The human-readable message.
|
||||
*
|
||||
* @return string
|
||||
* The formatted message.
|
||||
*/
|
||||
protected function formatMessage($message) {
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
$params = array_merge($args, $this->stepInfo);
|
||||
array_unshift($params, $this->stepIndex + 1);
|
||||
array_unshift($params, '[Step %d] ' . $message . ' (langcode: %s, default_revision: %d, untranslatable_update: %d, valid: %d)');
|
||||
return call_user_func_array('sprintf', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that changes to multiple translations are handled correctly.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
* @covers \Drupal\Core\Entity\Plugin\Validation\Constraint\EntityUntranslatableFieldsConstraintValidator::validate
|
||||
*/
|
||||
public function testMultipleTranslationChanges() {
|
||||
// Configure the untranslatable fields edit mode.
|
||||
$this->state->set('entity_test.untranslatable_fields.default_translation_affected', TRUE);
|
||||
$this->bundleInfo->clearCachedBundles();
|
||||
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->get('name')->value = 'Test 1.1 EN';
|
||||
$entity->get('non_mul_field')->value = 'Test 1.1';
|
||||
$this->storage->save($entity);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $revision */
|
||||
$revision = $this->storage->createRevision($entity->addTranslation('it'));
|
||||
$revision->get('name')->value = 'Test 1.2 IT';
|
||||
$this->storage->save($revision);
|
||||
|
||||
$revision = $this->storage->createRevision($revision->getTranslation('en'), FALSE);
|
||||
$revision->get('non_mul_field')->value = 'Test 1.3';
|
||||
$revision->getTranslation('it')->get('name')->value = 'Test 1.3 IT';
|
||||
$violations = $revision->validate();
|
||||
$this->assertCount(1, $violations);
|
||||
$this->assertEquals('Non-translatable fields can only be changed when updating the original language.', $violations[0]->getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that internal properties are preserved while creating a new revision.
|
||||
*/
|
||||
public function testInternalProperties() {
|
||||
$entity = EntityTestMulRev::create();
|
||||
$this->doTestInternalProperties($entity);
|
||||
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
$this->doTestInternalProperties($entity);
|
||||
|
||||
/** @var \Drupal\entity_test\Entity\EntityTestMulRev $translation */
|
||||
$translation = EntityTestMulRev::create()->addTranslation('it');
|
||||
$translation->save();
|
||||
$this->doTestInternalProperties($translation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that internal properties are preserved for the specified entity.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
||||
* An entity object.
|
||||
*/
|
||||
protected function doTestInternalProperties(ContentEntityInterface $entity) {
|
||||
$this->assertFalse($entity->isValidationRequired());
|
||||
$entity->setValidationRequired(TRUE);
|
||||
$this->assertTrue($entity->isValidationRequired());
|
||||
$new_revision = $this->storage->createRevision($entity);
|
||||
$this->assertTrue($new_revision->isValidationRequired());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that deleted translations are not accidentally restored.
|
||||
*
|
||||
* @covers ::createRevision
|
||||
*/
|
||||
public function testRemovedTranslations() {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = EntityTestMulRev::create(['name' => 'Test 1.1 EN']);
|
||||
$this->storage->save($entity);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $it_revision */
|
||||
$it_revision = $this->storage->createRevision($entity->addTranslation('it'));
|
||||
$it_revision->set('name', 'Test 1.2 IT');
|
||||
$this->storage->save($it_revision);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $en_revision */
|
||||
$en_revision = $this->storage->createRevision($it_revision->getUntranslated(), FALSE);
|
||||
$en_revision->set('name', 'Test 1.3 EN');
|
||||
$this->storage->save($en_revision);
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $en_revision */
|
||||
$it_revision = $this->storage->createRevision($it_revision);
|
||||
$en_revision = $it_revision->getUntranslated();
|
||||
$en_revision->removeTranslation('it');
|
||||
$this->storage->save($en_revision);
|
||||
|
||||
$revision_id = $this->storage->getLatestTranslationAffectedRevisionId($entity->id(), 'en');
|
||||
$en_revision = $this->storage->loadRevision($revision_id);
|
||||
$en_revision = $this->storage->createRevision($en_revision);
|
||||
$en_revision->set('name', 'Test 1.5 EN');
|
||||
$this->storage->save($en_revision);
|
||||
$en_revision = $this->storage->loadRevision($en_revision->getRevisionId());
|
||||
$this->assertFalse($en_revision->hasTranslation('it'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -113,6 +113,7 @@ class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
||||
// The revision key is now defined, so the revision field needs to be
|
||||
// created.
|
||||
t('The %field_name field needs to be installed.', ['%field_name' => 'Revision ID']),
|
||||
t('The %field_name field needs to be installed.', ['%field_name' => 'Default revision']),
|
||||
],
|
||||
];
|
||||
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
|
||||
@@ -389,53 +390,247 @@ class EntityDefinitionUpdateTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* Tests deleting a base field when it has existing data.
|
||||
*
|
||||
* @dataProvider baseFieldDeleteWithExistingDataTestCases
|
||||
*/
|
||||
public function testBaseFieldDeleteWithExistingData() {
|
||||
public function testBaseFieldDeleteWithExistingData($entity_type_id, $create_entity_revision, $base_field_revisionable) {
|
||||
/** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage($entity_type_id);
|
||||
$schema_handler = $this->database->schema();
|
||||
|
||||
// Create an entity without the base field, to ensure NULL values are not
|
||||
// added to the dedicated table storage to be purged.
|
||||
$entity = $storage->create();
|
||||
$entity->save();
|
||||
|
||||
// Add the base field and run the update.
|
||||
$this->addBaseField();
|
||||
$this->addBaseField('string', $entity_type_id, $base_field_revisionable);
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
||||
// Save an entity with the base field populated.
|
||||
$this->entityManager->getStorage('entity_test_update')->create(['new_base_field' => 'foo'])->save();
|
||||
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
|
||||
$table_mapping = $storage->getTableMapping();
|
||||
$storage_definition = $this->entityManager->getLastInstalledFieldStorageDefinitions($entity_type_id)['new_base_field'];
|
||||
|
||||
// Remove the base field and apply updates. It's expected to throw an
|
||||
// exception.
|
||||
// @todo Revisit that expectation once purging is implemented for
|
||||
// all fields: https://www.drupal.org/node/2282119.
|
||||
$this->removeBaseField();
|
||||
try {
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->fail('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
|
||||
// Save an entity with the base field populated.
|
||||
$entity = $storage->create(['new_base_field' => 'foo']);
|
||||
$entity->save();
|
||||
|
||||
if ($create_entity_revision) {
|
||||
$entity->setNewRevision(TRUE);
|
||||
$entity->new_base_field = 'bar';
|
||||
$entity->save();
|
||||
}
|
||||
catch (FieldStorageDefinitionUpdateForbiddenException $e) {
|
||||
$this->pass('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
|
||||
|
||||
// Remove the base field and apply updates.
|
||||
$this->removeBaseField($entity_type_id);
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
||||
// Check that the base field's column is deleted.
|
||||
$this->assertFalse($schema_handler->fieldExists($entity_type_id, 'new_base_field'), 'Column deleted from shared table for new_base_field.');
|
||||
|
||||
// Check that a dedicated 'deleted' table was created for the deleted base
|
||||
// field.
|
||||
$dedicated_deleted_table_name = $table_mapping->getDedicatedDataTableName($storage_definition, TRUE);
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_deleted_table_name), 'A dedicated table was created for the deleted new_base_field.');
|
||||
|
||||
// Check that the deleted field's data is preserved in the dedicated
|
||||
// 'deleted' table.
|
||||
$result = $this->database->select($dedicated_deleted_table_name, 't')
|
||||
->fields('t')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $result);
|
||||
|
||||
$expected = [
|
||||
'bundle' => $entity->bundle(),
|
||||
'deleted' => '1',
|
||||
'entity_id' => $entity->id(),
|
||||
'revision_id' => $create_entity_revision ? $entity->getRevisionId() : $entity->id(),
|
||||
'langcode' => $entity->language()->getId(),
|
||||
'delta' => '0',
|
||||
'new_base_field_value' => $entity->new_base_field->value,
|
||||
];
|
||||
// Use assertEquals and not assertSame here to prevent that a different
|
||||
// sequence of the columns in the table will affect the check.
|
||||
$this->assertEquals($expected, (array) $result[0]);
|
||||
|
||||
if ($create_entity_revision) {
|
||||
$dedicated_deleted_revision_table_name = $table_mapping->getDedicatedRevisionTableName($storage_definition, TRUE);
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_deleted_revision_table_name), 'A dedicated revision table was created for the deleted new_base_field.');
|
||||
|
||||
$result = $this->database->select($dedicated_deleted_revision_table_name, 't')
|
||||
->fields('t')
|
||||
->orderBy('revision_id', 'DESC')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
// Only one row will be created for non-revisionable base fields.
|
||||
$this->assertCount($base_field_revisionable ? 2 : 1, $result);
|
||||
|
||||
// Use assertEquals and not assertSame here to prevent that a different
|
||||
// sequence of the columns in the table will affect the check.
|
||||
$this->assertEquals([
|
||||
'bundle' => $entity->bundle(),
|
||||
'deleted' => '1',
|
||||
'entity_id' => $entity->id(),
|
||||
'revision_id' => '3',
|
||||
'langcode' => $entity->language()->getId(),
|
||||
'delta' => '0',
|
||||
'new_base_field_value' => 'bar',
|
||||
], (array) $result[0]);
|
||||
|
||||
// Two rows only exist if the base field is revisionable.
|
||||
if ($base_field_revisionable) {
|
||||
// Use assertEquals and not assertSame here to prevent that a different
|
||||
// sequence of the columns in the table will affect the check.
|
||||
$this->assertEquals([
|
||||
'bundle' => $entity->bundle(),
|
||||
'deleted' => '1',
|
||||
'entity_id' => $entity->id(),
|
||||
'revision_id' => '2',
|
||||
'langcode' => $entity->language()->getId(),
|
||||
'delta' => '0',
|
||||
'new_base_field_value' => 'foo',
|
||||
], (array) $result[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the field storage definition is marked for purging.
|
||||
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
|
||||
$this->assertArrayHasKey($storage_definition->getUniqueStorageIdentifier(), $deleted_storage_definitions, 'The base field is marked for purging.');
|
||||
|
||||
// Purge field data, and check that the storage definition has been
|
||||
// completely removed once the data is purged.
|
||||
field_purge_batch(10);
|
||||
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
|
||||
$this->assertEmpty($deleted_storage_definitions, 'The base field has been deleted.');
|
||||
$this->assertFalse($schema_handler->tableExists($dedicated_deleted_table_name), 'A dedicated field table was deleted after new_base_field was purged.');
|
||||
|
||||
if (isset($dedicated_deleted_revision_table_name)) {
|
||||
$this->assertFalse($schema_handler->tableExists($dedicated_deleted_revision_table_name), 'A dedicated field revision table was deleted after new_base_field was purged.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for ::testBaseFieldDeleteWithExistingData.
|
||||
*/
|
||||
public function baseFieldDeleteWithExistingDataTestCases() {
|
||||
return [
|
||||
'Non-revisionable entity type' => [
|
||||
'entity_test_update',
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
'Non-revisionable custom data table' => [
|
||||
'entity_test_mul',
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
'Non-revisionable entity type, revisionable base field' => [
|
||||
'entity_test_update',
|
||||
FALSE,
|
||||
TRUE,
|
||||
],
|
||||
'Non-revisionable custom data table, revisionable base field' => [
|
||||
'entity_test_mul',
|
||||
FALSE,
|
||||
TRUE,
|
||||
],
|
||||
'Revisionable entity type, non revisionable base field' => [
|
||||
'entity_test_mulrev',
|
||||
TRUE,
|
||||
FALSE,
|
||||
],
|
||||
'Revisionable entity type, revisionable base field' => [
|
||||
'entity_test_mulrev',
|
||||
TRUE,
|
||||
TRUE,
|
||||
],
|
||||
'Non-translatable revisionable entity type, revisionable base field' => [
|
||||
'entity_test_rev',
|
||||
TRUE,
|
||||
TRUE,
|
||||
],
|
||||
'Non-translatable revisionable entity type, non-revisionable base field' => [
|
||||
'entity_test_rev',
|
||||
TRUE,
|
||||
FALSE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a bundle field when it has existing data.
|
||||
*/
|
||||
public function testBundleFieldDeleteWithExistingData() {
|
||||
/** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage('entity_test_update');
|
||||
$schema_handler = $this->database->schema();
|
||||
|
||||
// Add the bundle field and run the update.
|
||||
$this->addBundleField();
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
||||
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
|
||||
$table_mapping = $storage->getTableMapping();
|
||||
$storage_definition = $this->entityManager->getLastInstalledFieldStorageDefinitions('entity_test_update')['new_bundle_field'];
|
||||
|
||||
// Check that the bundle field has a dedicated table.
|
||||
$dedicated_table_name = $table_mapping->getDedicatedDataTableName($storage_definition);
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_table_name), 'The bundle field uses a dedicated table.');
|
||||
|
||||
// Save an entity with the bundle field populated.
|
||||
entity_test_create_bundle('custom');
|
||||
$this->entityManager->getStorage('entity_test_update')->create(['type' => 'test_bundle', 'new_bundle_field' => 'foo'])->save();
|
||||
$entity = $storage->create(['type' => 'test_bundle', 'new_bundle_field' => 'foo']);
|
||||
$entity->save();
|
||||
|
||||
// Remove the bundle field and apply updates. It's expected to throw an
|
||||
// exception.
|
||||
// @todo Revisit that expectation once purging is implemented for
|
||||
// all fields: https://www.drupal.org/node/2282119.
|
||||
// Remove the bundle field and apply updates.
|
||||
$this->removeBundleField();
|
||||
try {
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->fail('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
|
||||
}
|
||||
catch (FieldStorageDefinitionUpdateForbiddenException $e) {
|
||||
$this->pass('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
|
||||
}
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
|
||||
// Check that the table of the bundle field has been renamed to use a
|
||||
// 'deleted' table name.
|
||||
$this->assertFalse($schema_handler->tableExists($dedicated_table_name), 'The dedicated table of the bundle field no longer exists.');
|
||||
|
||||
$dedicated_deleted_table_name = $table_mapping->getDedicatedDataTableName($storage_definition, TRUE);
|
||||
$this->assertTrue($schema_handler->tableExists($dedicated_deleted_table_name), 'The dedicated table of the bundle fields has been renamed to use the "deleted" name.');
|
||||
|
||||
// Check that the deleted field's data is preserved in the dedicated
|
||||
// 'deleted' table.
|
||||
$result = $this->database->select($dedicated_deleted_table_name, 't')
|
||||
->fields('t')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
$this->assertCount(1, $result);
|
||||
|
||||
$expected = [
|
||||
'bundle' => $entity->bundle(),
|
||||
'deleted' => '1',
|
||||
'entity_id' => $entity->id(),
|
||||
'revision_id' => $entity->id(),
|
||||
'langcode' => $entity->language()->getId(),
|
||||
'delta' => '0',
|
||||
'new_bundle_field_value' => $entity->new_bundle_field->value,
|
||||
];
|
||||
// Use assertEquals and not assertSame here to prevent that a different
|
||||
// sequence of the columns in the table will affect the check.
|
||||
$this->assertEquals($expected, (array) $result[0]);
|
||||
|
||||
// Check that the field definition is marked for purging.
|
||||
$deleted_field_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldDefinitions();
|
||||
$this->assertArrayHasKey($storage_definition->getUniqueIdentifier(), $deleted_field_definitions, 'The bundle field is marked for purging.');
|
||||
|
||||
// Check that the field storage definition is marked for purging.
|
||||
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
|
||||
$this->assertArrayHasKey($storage_definition->getUniqueStorageIdentifier(), $deleted_storage_definitions, 'The bundle field storage is marked for purging.');
|
||||
|
||||
// Purge field data, and check that the storage definition has been
|
||||
// completely removed once the data is purged.
|
||||
field_purge_batch(10);
|
||||
$deleted_field_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldDefinitions();
|
||||
$this->assertEmpty($deleted_field_definitions, 'The bundle field has been deleted.');
|
||||
$deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')->getFieldStorageDefinitions();
|
||||
$this->assertEmpty($deleted_storage_definitions, 'The bundle field storage has been deleted.');
|
||||
$this->assertFalse($schema_handler->tableExists($dedicated_deleted_table_name), 'The dedicated table of the bundle field has been removed.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTestMul;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
@@ -23,9 +24,11 @@ class EntityRevisionTranslationTest extends EntityKernelTestBase {
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Enable an additional language.
|
||||
// Enable some additional languages.
|
||||
ConfigurableLanguage::createFromLangcode('de')->save();
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
|
||||
$this->installEntitySchema('entity_test_mul');
|
||||
$this->installEntitySchema('entity_test_mulrev');
|
||||
}
|
||||
|
||||
@@ -157,4 +160,124 @@ class EntityRevisionTranslationTest extends EntityKernelTestBase {
|
||||
$this->assertFalse($translation->isDefaultRevision());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\Core\Entity\RevisionableInterface::setNewRevision
|
||||
*/
|
||||
public function testSetNewRevision() {
|
||||
$user = $this->createUser();
|
||||
|
||||
// All revisionable entity variations have to have the same results.
|
||||
foreach (entity_test_entity_types(ENTITY_TEST_TYPES_REVISABLE) as $entity_type) {
|
||||
$this->installEntitySchema($entity_type);
|
||||
|
||||
$entity = entity_create($entity_type, [
|
||||
'name' => 'foo',
|
||||
'user_id' => $user->id(),
|
||||
]);
|
||||
|
||||
$entity->save();
|
||||
$entity_id = $entity->id();
|
||||
$entity_rev_id = $entity->getRevisionId();
|
||||
$entity = entity_load($entity_type, $entity_id, TRUE);
|
||||
|
||||
$entity->setNewRevision(TRUE);
|
||||
$entity->setNewRevision(FALSE);
|
||||
$entity->save();
|
||||
$entity = entity_load($entity_type, $entity_id, TRUE);
|
||||
|
||||
$this->assertEquals($entity_rev_id, $entity->getRevisionId(), 'A new entity revision was not created.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that revision translations are correctly detected.
|
||||
*
|
||||
* @covers \Drupal\Core\Entity\ContentEntityStorageBase::isAnyStoredRevisionTranslated
|
||||
*/
|
||||
public function testIsAnyStoredRevisionTranslated() {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage('entity_test_mul');
|
||||
$method = new \ReflectionMethod(get_class($storage), 'isAnyStoredRevisionTranslated');
|
||||
$method->setAccessible(TRUE);
|
||||
|
||||
// Check that a non-revisionable new entity is handled correctly.
|
||||
$entity = EntityTestMul::create();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
$entity->addTranslation('it');
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that not yet stored translations are handled correctly.
|
||||
$entity = EntityTestMul::create();
|
||||
$entity->save();
|
||||
$entity->addTranslation('it');
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that removed translations are handled correctly.
|
||||
$entity->save();
|
||||
$entity->removeTranslation('it');
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertTrue($method->invoke($storage, $entity));
|
||||
$entity->save();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
$entity->addTranslation('de');
|
||||
$entity->removeTranslation('de');
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a non-revisionable not translated entity is handled correctly.
|
||||
$entity = EntityTestMul::create();
|
||||
$entity->save();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a non-revisionable translated entity is handled correctly.
|
||||
$entity->addTranslation('it');
|
||||
$entity->save();
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertTrue($method->invoke($storage, $entity));
|
||||
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage('entity_test_mulrev');
|
||||
|
||||
// Check that a revisionable new entity is handled correctly.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
$entity->addTranslation('it');
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a revisionable not translated entity is handled correctly.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertFalse($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a revisionable translated pending revision is handled
|
||||
// correctly.
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $new_revision */
|
||||
$new_revision = $storage->createRevision($entity, FALSE);
|
||||
$new_revision->addTranslation('it');
|
||||
$new_revision->save();
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $storage->loadUnchanged($entity->id());
|
||||
$this->assertEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertNotEmpty($new_revision->getTranslationLanguages(FALSE));
|
||||
$this->assertTrue($method->invoke($storage, $entity));
|
||||
|
||||
// Check that a revisionable translated default revision is handled
|
||||
// correctly.
|
||||
$new_revision->isDefaultRevision(TRUE);
|
||||
$new_revision->save();
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $storage->loadUnchanged($entity->id());
|
||||
$this->assertNotEmpty($entity->getTranslationLanguages(FALSE));
|
||||
$this->assertNotEmpty($new_revision->getTranslationLanguages(FALSE));
|
||||
$this->assertTrue($method->invoke($storage, $entity));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+95
-1
@@ -8,9 +8,11 @@ use Drupal\language\Entity\ConfigurableLanguage;
|
||||
/**
|
||||
* Tests the loaded Revision of an entity.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Entity\ContentEntityBase
|
||||
*
|
||||
* @group entity
|
||||
*/
|
||||
class EntityLoadedRevisionTest extends EntityKernelTestBase {
|
||||
class EntityRevisionsTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
@@ -164,7 +166,99 @@ class EntityLoadedRevisionTest extends EntityKernelTestBase {
|
||||
$loadedRevisionId = \Drupal::state()->get('entity_test.loadedRevisionId');
|
||||
$this->assertEquals($entity->getLoadedRevisionId(), $loadedRevisionId);
|
||||
$this->assertEquals($entity->getRevisionId(), $entity->getLoadedRevisionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that latest revisions are working as expected.
|
||||
*
|
||||
* @covers ::isLatestRevision
|
||||
*/
|
||||
public function testIsLatestRevision() {
|
||||
// Create a basic EntityTestMulRev entity and save it.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
$this->assertTrue($entity->isLatestRevision());
|
||||
|
||||
// Load the created entity and create a new pending revision.
|
||||
$pending_revision = EntityTestMulRev::load($entity->id());
|
||||
$pending_revision->setNewRevision(TRUE);
|
||||
$pending_revision->isDefaultRevision(FALSE);
|
||||
|
||||
// The pending revision should still be marked as the latest one before it
|
||||
// is saved.
|
||||
$this->assertTrue($pending_revision->isLatestRevision());
|
||||
$pending_revision->save();
|
||||
$this->assertTrue($pending_revision->isLatestRevision());
|
||||
|
||||
// Load the default revision and check that it is not marked as the latest
|
||||
// revision.
|
||||
$default_revision = EntityTestMulRev::load($entity->id());
|
||||
$this->assertFalse($default_revision->isLatestRevision());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that latest affected revisions are working as expected.
|
||||
*
|
||||
* The latest revision affecting a particular translation behaves as the
|
||||
* latest revision for monolingual entities.
|
||||
*
|
||||
* @covers ::isLatestTranslationAffectedRevision
|
||||
* @covers \Drupal\Core\Entity\ContentEntityStorageBase::getLatestRevisionId
|
||||
* @covers \Drupal\Core\Entity\ContentEntityStorageBase::getLatestTranslationAffectedRevisionId
|
||||
*/
|
||||
public function testIsLatestAffectedRevisionTranslation() {
|
||||
ConfigurableLanguage::createFromLangcode('it')->save();
|
||||
|
||||
// Create a basic EntityTestMulRev entity and save it.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->setName($this->randomString());
|
||||
$entity->save();
|
||||
$this->assertTrue($entity->isLatestTranslationAffectedRevision());
|
||||
|
||||
// Load the created entity and create a new pending revision.
|
||||
$pending_revision = EntityTestMulRev::load($entity->id());
|
||||
$pending_revision->setName($this->randomString());
|
||||
$pending_revision->setNewRevision(TRUE);
|
||||
$pending_revision->isDefaultRevision(FALSE);
|
||||
|
||||
// Check that no revision affecting Italian is available, given that no
|
||||
// Italian translation has been created yet.
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $this->entityManager->getStorage($entity->getEntityTypeId());
|
||||
$this->assertNull($storage->getLatestTranslationAffectedRevisionId($entity->id(), 'it'));
|
||||
$this->assertEquals($pending_revision->getLoadedRevisionId(), $storage->getLatestRevisionId($entity->id()));
|
||||
|
||||
// The pending revision should still be marked as the latest affected one
|
||||
// before it is saved.
|
||||
$this->assertTrue($pending_revision->isLatestTranslationAffectedRevision());
|
||||
$pending_revision->save();
|
||||
$this->assertTrue($pending_revision->isLatestTranslationAffectedRevision());
|
||||
|
||||
// Load the default revision and check that it is not marked as the latest
|
||||
// (translation-affected) revision.
|
||||
$default_revision = EntityTestMulRev::load($entity->id());
|
||||
$this->assertFalse($default_revision->isLatestRevision());
|
||||
$this->assertFalse($default_revision->isLatestTranslationAffectedRevision());
|
||||
|
||||
// Add a translation in a new pending revision and verify that both the
|
||||
// English and Italian revision translations are the latest affected
|
||||
// revisions for their respective languages, while the English revision is
|
||||
// not the latest revision.
|
||||
/** @var \Drupal\entity_test\Entity\EntityTestMulRev $en_revision */
|
||||
$en_revision = clone $pending_revision;
|
||||
/** @var \Drupal\entity_test\Entity\EntityTestMulRev $it_revision */
|
||||
$it_revision = $pending_revision->addTranslation('it');
|
||||
$it_revision->setName($this->randomString());
|
||||
$it_revision->setNewRevision(TRUE);
|
||||
$it_revision->isDefaultRevision(FALSE);
|
||||
// @todo Remove this once the "original" property works with revisions. See
|
||||
// https://www.drupal.org/project/drupal/issues/2859042.
|
||||
$it_revision->original = $storage->loadRevision($it_revision->getLoadedRevisionId());
|
||||
$it_revision->save();
|
||||
$this->assertTrue($it_revision->isLatestRevision());
|
||||
$this->assertTrue($it_revision->isLatestTranslationAffectedRevision());
|
||||
$this->assertFalse($en_revision->isLatestRevision());
|
||||
$this->assertTrue($en_revision->isLatestTranslationAffectedRevision());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,11 @@ class EntityTypeConstraintsTest extends EntityKernelTestBase {
|
||||
// Test reading the annotation. There should be two constraints, the defined
|
||||
// constraint and the automatically added EntityChanged constraint.
|
||||
$entity_type = $this->entityManager->getDefinition('entity_test_constraints');
|
||||
$default_constraints = ['NotNull' => [], 'EntityChanged' => NULL];
|
||||
$default_constraints = [
|
||||
'NotNull' => [],
|
||||
'EntityChanged' => NULL,
|
||||
'EntityUntranslatableFields' => NULL,
|
||||
];
|
||||
$this->assertEqual($default_constraints, $entity_type->getConstraints());
|
||||
|
||||
// Enable our test module and test extending constraints.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Drupal\KernelTests\Core\Entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\TypedData\EntityDataDefinition;
|
||||
use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
@@ -11,6 +13,7 @@ use Drupal\Core\TypedData\DataReferenceDefinition;
|
||||
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
|
||||
use Drupal\Core\TypedData\ListDataDefinitionInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
|
||||
/**
|
||||
* Tests deriving metadata of entity and field data types.
|
||||
@@ -31,10 +34,16 @@ class EntityTypedDataDefinitionTest extends KernelTestBase {
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['filter', 'text', 'node', 'user'];
|
||||
public static $modules = ['system', 'filter', 'text', 'node', 'user'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setup();
|
||||
|
||||
NodeType::create([
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
])->save();
|
||||
|
||||
$this->typedDataManager = $this->container->get('typed_data_manager');
|
||||
}
|
||||
|
||||
@@ -82,10 +91,15 @@ class EntityTypedDataDefinitionTest extends KernelTestBase {
|
||||
*/
|
||||
public function testEntities() {
|
||||
$entity_definition = EntityDataDefinition::create('node');
|
||||
$bundle_definition = EntityDataDefinition::create('node', 'article');
|
||||
// Entities are complex data.
|
||||
$this->assertFalse($entity_definition instanceof ListDataDefinitionInterface);
|
||||
$this->assertTrue($entity_definition instanceof ComplexDataDefinitionInterface);
|
||||
|
||||
// Entity definitions should inherit their labels from the entity type.
|
||||
$this->assertEquals('Content', $entity_definition->getLabel());
|
||||
$this->assertEquals('Article', $bundle_definition->getLabel());
|
||||
|
||||
$field_definitions = $entity_definition->getPropertyDefinitions();
|
||||
// Comparison should ignore the internal static cache, so compare the
|
||||
// serialized objects instead.
|
||||
@@ -126,4 +140,36 @@ class EntityTypedDataDefinitionTest extends KernelTestBase {
|
||||
$this->assertEqual(serialize($reference_definition2), serialize($reference_definition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an entity annotation can mark the data definition as internal.
|
||||
*
|
||||
* @dataProvider entityDefinitionIsInternalProvider
|
||||
*/
|
||||
public function testEntityDefinitionIsInternal($internal, $expected) {
|
||||
$entity_type_id = $this->randomMachineName();
|
||||
|
||||
$entity_type = $this->prophesize(EntityTypeInterface::class);
|
||||
$entity_type->getLabel()->willReturn($this->randomString());
|
||||
$entity_type->getConstraints()->willReturn([]);
|
||||
$entity_type->isInternal()->willReturn($internal);
|
||||
|
||||
$entity_manager = $this->prophesize(EntityManagerInterface::class);
|
||||
$entity_manager->getDefinitions()->willReturn([$entity_type_id => $entity_type->reveal()]);
|
||||
$this->container->set('entity.manager', $entity_manager->reveal());
|
||||
|
||||
$entity_data_definition = EntityDataDefinition::create($entity_type_id);
|
||||
$this->assertSame($expected, $entity_data_definition->isInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test cases for testEntityDefinitionIsInternal.
|
||||
*/
|
||||
public function entityDefinitionIsInternalProvider() {
|
||||
return [
|
||||
'internal' => [TRUE, TRUE],
|
||||
'external' => [FALSE, FALSE],
|
||||
'undefined' => [NULL, FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ use Drupal\KernelTests\KernelTestBase;
|
||||
*/
|
||||
class FieldWidgetConstraintValidatorTest extends KernelTestBase {
|
||||
|
||||
public static $modules = ['entity_test', 'field', 'user', 'system'];
|
||||
public static $modules = ['entity_test', 'field', 'field_test', 'user', 'system'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -54,7 +54,8 @@ class FieldWidgetConstraintValidatorTest extends KernelTestBase {
|
||||
$display->validateFormValues($entity, $form, $form_state);
|
||||
|
||||
$errors = $form_state->getErrors();
|
||||
$this->assertEqual($errors['name'], 'Widget constraint has failed.', 'Constraint violation is generated correctly');
|
||||
$this->assertEqual($errors['name'], 'Widget constraint has failed.', 'Constraint violation at the field items list level is generated correctly');
|
||||
$this->assertEqual($errors['test_field'], 'Widget constraint has failed.', 'Constraint violation at the field items list level is generated correctly for an advanced widget');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace Drupal\KernelTests\Core\Entity;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\entity_test_revlog\Entity\EntityTestMulWithRevisionLog;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
@@ -13,7 +12,7 @@ use Drupal\user\UserInterface;
|
||||
* @coversDefaultClass \Drupal\Core\Entity\RevisionableContentEntityBase
|
||||
* @group Entity
|
||||
*/
|
||||
class RevisionableContentEntityBaseTest extends KernelTestBase {
|
||||
class RevisionableContentEntityBaseTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -25,10 +24,7 @@ class RevisionableContentEntityBaseTest extends KernelTestBase {
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('entity_test_mul_revlog');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('system', 'sequences');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,6 +85,74 @@ class RevisionableContentEntityBaseTest extends KernelTestBase {
|
||||
$this->assertItemsTableCount(3, $definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of the "revision_default" flag.
|
||||
*
|
||||
* @covers \Drupal\Core\Entity\ContentEntityBase::wasDefaultRevision
|
||||
*/
|
||||
public function testWasDefaultRevision() {
|
||||
$entity_type_id = 'entity_test_mul_revlog';
|
||||
$entity = EntityTestMulWithRevisionLog::create([
|
||||
'type' => $entity_type_id,
|
||||
]);
|
||||
|
||||
// Checks that in a new entity ::wasDefaultRevision() always matches
|
||||
// ::isDefaultRevision().
|
||||
$this->assertEquals($entity->isDefaultRevision(), $entity->wasDefaultRevision());
|
||||
$entity->isDefaultRevision(FALSE);
|
||||
$this->assertEquals($entity->isDefaultRevision(), $entity->wasDefaultRevision());
|
||||
|
||||
// Check that a new entity is always flagged as a default revision on save,
|
||||
// regardless of its default revision status.
|
||||
$entity->save();
|
||||
$this->assertTrue($entity->wasDefaultRevision());
|
||||
|
||||
// Check that a pending revision is not flagged as default.
|
||||
$entity->setNewRevision();
|
||||
$entity->isDefaultRevision(FALSE);
|
||||
$entity->save();
|
||||
$this->assertFalse($entity->wasDefaultRevision());
|
||||
|
||||
// Check that a default revision is flagged as such.
|
||||
$entity->setNewRevision();
|
||||
$entity->isDefaultRevision(TRUE);
|
||||
$entity->save();
|
||||
$this->assertTrue($entity->wasDefaultRevision());
|
||||
|
||||
// Check that a manually set value for the "revision_default" flag is
|
||||
// ignored on save.
|
||||
$entity->setNewRevision();
|
||||
$entity->isDefaultRevision(FALSE);
|
||||
$entity->set('revision_default', TRUE);
|
||||
$this->assertTrue($entity->wasDefaultRevision());
|
||||
$entity->save();
|
||||
$this->assertFalse($entity->wasDefaultRevision());
|
||||
|
||||
// Check that the default revision status was stored correctly.
|
||||
$storage = $this->entityManager->getStorage($entity_type_id);
|
||||
foreach ([TRUE, FALSE, TRUE, FALSE] as $index => $expected) {
|
||||
/** @var \Drupal\entity_test_revlog\Entity\EntityTestMulWithRevisionLog $revision */
|
||||
$revision = $storage->loadRevision($index + 1);
|
||||
$this->assertEquals($expected, $revision->wasDefaultRevision());
|
||||
}
|
||||
|
||||
// Check that the default revision is flagged correctly.
|
||||
/** @var \Drupal\entity_test_revlog\Entity\EntityTestMulWithRevisionLog $entity */
|
||||
$entity = $storage->loadUnchanged($entity->id());
|
||||
$this->assertTrue($entity->wasDefaultRevision());
|
||||
|
||||
// Check that the "revision_default" flag cannot be changed once set.
|
||||
/** @var \Drupal\entity_test_revlog\Entity\EntityTestMulWithRevisionLog $entity2 */
|
||||
$entity2 = EntityTestMulWithRevisionLog::create([
|
||||
'type' => $entity_type_id,
|
||||
]);
|
||||
$entity2->save();
|
||||
$this->assertTrue($entity2->wasDefaultRevision());
|
||||
$entity2->isDefaultRevision(FALSE);
|
||||
$entity2->save();
|
||||
$this->assertTrue($entity2->wasDefaultRevision());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the ammount of items on entity related tables.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Extension;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Test whether deprecated hook invocations trigger errors.
|
||||
*
|
||||
* @group Extension
|
||||
* @group legacy
|
||||
*
|
||||
* @coversDefaultClass Drupal\Core\Extension\ModuleHandler
|
||||
*/
|
||||
class ModuleHandlerDeprecatedHookTest extends KernelTestBase {
|
||||
|
||||
protected static $modules = ['deprecation_test'];
|
||||
|
||||
/**
|
||||
* @covers ::invokeDeprecated
|
||||
* @expectedDeprecation The deprecated hook hook_deprecated_hook() is implemented in these functions: deprecation_test_deprecated_hook(). Use something else.
|
||||
*/
|
||||
public function testInvokeDeprecated() {
|
||||
/* @var $module_handler \Drupal\Core\Extension\ModuleHandlerInterface */
|
||||
$module_handler = $this->container->get('module_handler');
|
||||
$arg = 'an_arg';
|
||||
$this->assertEqual(
|
||||
$arg,
|
||||
$module_handler->invokeDeprecated('Use something else.', 'deprecation_test', 'deprecated_hook', [$arg])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::invokeAllDeprecated
|
||||
* @expectedDeprecation The deprecated hook hook_deprecated_hook() is implemented in these functions: deprecation_test_deprecated_hook(). Use something else.
|
||||
*/
|
||||
public function testInvokeAllDeprecated() {
|
||||
/* @var $module_handler \Drupal\Core\Extension\ModuleHandlerInterface */
|
||||
$module_handler = $this->container->get('module_handler');
|
||||
$arg = 'an_arg';
|
||||
$this->assertEqual(
|
||||
[$arg],
|
||||
$module_handler->invokeAllDeprecated('Use something else.', 'deprecated_hook', [$arg])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::alterDeprecated
|
||||
* @expectedDeprecation The deprecated alter hook hook_deprecated_alter_alter() is implemented in these functions: deprecation_test_deprecated_alter_alter. Alter something else.
|
||||
*/
|
||||
public function testAlterDeprecated() {
|
||||
/* @var $module_handler \Drupal\Core\Extension\ModuleHandlerInterface */
|
||||
$module_handler = $this->container->get('module_handler');
|
||||
$data = [];
|
||||
$context1 = 'test1';
|
||||
$context2 = 'test2';
|
||||
$module_handler->alterDeprecated('Alter something else.', 'deprecated_alter', $data, $context1, $context2);
|
||||
$this->assertEqual([$context1, $context2], $data);
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Extension;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Test whether unimplemented deprecated hook invocations trigger errors.
|
||||
*
|
||||
* @group Extension
|
||||
*
|
||||
* @coversDefaultClass Drupal\Core\Extension\ModuleHandler
|
||||
*/
|
||||
class ModuleHandlerDeprecatedHookUnimplementedTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* @covers ::alterDeprecated
|
||||
* @covers ::invokeAllDeprecated
|
||||
* @covers ::invokeDeprecated
|
||||
*/
|
||||
public function testUnimplementedHooks() {
|
||||
$unimplemented_hook_name = 'unimplemented_hook_name';
|
||||
|
||||
/* @var $module_handler \Drupal\Core\Extension\ModuleHandlerInterface */
|
||||
$module_handler = $this->container->get('module_handler');
|
||||
|
||||
$module_handler->invokeDeprecated('Use something else.', 'deprecation_test', $unimplemented_hook_name);
|
||||
$module_handler->invokeAllDeprecated('Use something else.', $unimplemented_hook_name);
|
||||
$data = [];
|
||||
$module_handler->alterDeprecated('Alter something else.', $unimplemented_hook_name, $data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -85,4 +85,13 @@ class ModuleInstallerTest extends KernelTestBase {
|
||||
$this->assertFalse($schema->tableExists($table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that rebuilding the container in hook_install() works.
|
||||
*/
|
||||
public function testKernelRebuildDuringHookInstall() {
|
||||
\Drupal::state()->set('module_test_install:rebuild_container', TRUE);
|
||||
$module_installer = $this->container->get('module_installer');
|
||||
$this->assertTrue($module_installer->install(['module_test']));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Field;
|
||||
|
||||
use Drupal\Core\Extension\ModuleUninstallValidatorException;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\entity_test\FieldStorageDefinition;
|
||||
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests FieldModuleUninstallValidator functionality.
|
||||
*
|
||||
* @group Field
|
||||
*/
|
||||
class FieldModuleUninstallValidatorTest extends EntityKernelTestBase {
|
||||
|
||||
/**
|
||||
* The entity definition update manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface
|
||||
*/
|
||||
protected $entityDefinitionUpdateManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('user', 'users_data');
|
||||
$this->entityDefinitionUpdateManager = $this->container->get('entity.definition_update_manager');
|
||||
|
||||
// Setup some fields for entity_test_extra to create.
|
||||
$definitions['extra_base_field'] = BaseFieldDefinition::create('string')
|
||||
->setName('extra_base_field')
|
||||
->setTargetEntityTypeId('entity_test')
|
||||
->setTargetBundle('entity_test');
|
||||
$this->state->set('entity_test.additional_base_field_definitions', $definitions);
|
||||
$definitions['extra_bundle_field'] = FieldStorageDefinition::create('string')
|
||||
->setName('extra_bundle_field')
|
||||
->setTargetEntityTypeId('entity_test')
|
||||
->setTargetBundle('entity_test');
|
||||
$this->state->set('entity_test.additional_field_storage_definitions', $definitions);
|
||||
$this->state->set('entity_test.entity_test.additional_bundle_field_definitions', $definitions);
|
||||
$this->entityManager->clearCachedDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests uninstall entity_test module with and without content for the field.
|
||||
*/
|
||||
public function testUninstallingModule() {
|
||||
// Test uninstall works fine without content.
|
||||
$this->assertModuleInstallUninstall('entity_test_extra');
|
||||
|
||||
// Test uninstalling works fine with content having no field values.
|
||||
$entity = $this->entityManager->getStorage('entity_test')->create([
|
||||
'name' => $this->randomString(),
|
||||
]);
|
||||
$entity->save();
|
||||
$this->assertModuleInstallUninstall('entity_test_extra');
|
||||
$entity->delete();
|
||||
|
||||
// Verify uninstall works fine without content again.
|
||||
$this->assertModuleInstallUninstall('entity_test_extra');
|
||||
// Verify uninstalling entity_test is not possible when there is content for
|
||||
// the base field.
|
||||
$this->enableModules(['entity_test_extra']);
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$entity = $this->entityManager->getStorage('entity_test')->create([
|
||||
'name' => $this->randomString(),
|
||||
'extra_base_field' => $this->randomString(),
|
||||
]);
|
||||
$entity->save();
|
||||
|
||||
try {
|
||||
$message = 'Module uninstallation fails as the module provides a base field which has content.';
|
||||
$this->getModuleInstaller()->uninstall(['entity_test_extra']);
|
||||
$this->fail($message);
|
||||
}
|
||||
catch (ModuleUninstallValidatorException $e) {
|
||||
$this->pass($message);
|
||||
$this->assertEqual($e->getMessage(), 'The following reasons prevent the modules from being uninstalled: There is data for the field extra_base_field on entity type Test entity');
|
||||
}
|
||||
|
||||
// Verify uninstalling entity_test is not possible when there is content for
|
||||
// the bundle field.
|
||||
$entity->delete();
|
||||
$this->assertModuleInstallUninstall('entity_test_extra');
|
||||
$this->enableModules(['entity_test_extra']);
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$entity = $this->entityManager->getStorage('entity_test')->create([
|
||||
'name' => $this->randomString(),
|
||||
'extra_bundle_field' => $this->randomString(),
|
||||
]);
|
||||
$entity->save();
|
||||
try {
|
||||
$this->getModuleInstaller()->uninstall(['entity_test_extra']);
|
||||
$this->fail('Module uninstallation fails as the module provides a bundle field which has content.');
|
||||
}
|
||||
catch (ModuleUninstallValidatorException $e) {
|
||||
$this->pass('Module uninstallation fails as the module provides a bundle field which has content.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the given module can be installed and uninstalled.
|
||||
*
|
||||
* @param string $module_name
|
||||
* The module to install and uninstall.
|
||||
*/
|
||||
protected function assertModuleInstallUninstall($module_name) {
|
||||
// Install the module if it is not installed yet.
|
||||
if (!\Drupal::moduleHandler()->moduleExists($module_name)) {
|
||||
$this->enableModules([$module_name]);
|
||||
}
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertTrue($this->getModuleHandler()->moduleExists($module_name), $module_name . ' module is enabled.');
|
||||
$this->getModuleInstaller()->uninstall([$module_name]);
|
||||
$this->entityDefinitionUpdateManager->applyUpdates();
|
||||
$this->assertFalse($this->getModuleHandler()->moduleExists($module_name), $module_name . ' module is disabled.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ModuleHandler.
|
||||
*
|
||||
* @return \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected function getModuleHandler() {
|
||||
return $this->container->get('module_handler');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ModuleInstaller.
|
||||
*
|
||||
* @return \Drupal\Core\Extension\ModuleInstallerInterface
|
||||
*/
|
||||
protected function getModuleInstaller() {
|
||||
return $this->container->get('module_installer');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,6 +46,34 @@ class FieldSettingsTest extends EntityKernelTestBase {
|
||||
$this->assertEqual($base_field->getSettings(), $expected_settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the base field settings on a cloned base field definition object.
|
||||
*/
|
||||
public function testBaseFieldSettingsOnClone() {
|
||||
$base_field = BaseFieldDefinition::create('test_field');
|
||||
|
||||
// Check that the default settings have been populated.
|
||||
$expected_settings = [
|
||||
'test_field_storage_setting' => 'dummy test string',
|
||||
'changeable' => 'a changeable field storage setting',
|
||||
'unchangeable' => 'an unchangeable field storage setting',
|
||||
'translatable_storage_setting' => 'a translatable field storage setting',
|
||||
'test_field_setting' => 'dummy test string',
|
||||
'translatable_field_setting' => 'a translatable field setting',
|
||||
];
|
||||
$this->assertEquals($expected_settings, $base_field->getSettings());
|
||||
|
||||
// Clone the base field object and change one single setting using
|
||||
// setSettings() on the cloned base field and check that it has been
|
||||
// changed only on the cloned object.
|
||||
$clone_base_field = clone $base_field;
|
||||
$expected_settings_clone = $expected_settings;
|
||||
$expected_settings_clone['changeable'] = $expected_settings['changeable'] . ' (clone)';
|
||||
$clone_base_field->setSetting('changeable', $expected_settings_clone['changeable']);
|
||||
$this->assertEquals($expected_settings, $base_field->getSettings());
|
||||
$this->assertEquals($expected_settings_clone, $clone_base_field->getSettings());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\field\Entity\FieldStorageConfig::getSettings
|
||||
* @covers \Drupal\field\Entity\FieldStorageConfig::setSettings
|
||||
|
||||
@@ -45,7 +45,7 @@ class DirectoryTest extends FileTestBase {
|
||||
$this->assertDirectoryPermissions($directory, $old_mode);
|
||||
|
||||
// Check creating a directory using an absolute path.
|
||||
$absolute_path = drupal_realpath($directory) . DIRECTORY_SEPARATOR . $this->randomMachineName() . DIRECTORY_SEPARATOR . $this->randomMachineName();
|
||||
$absolute_path = \Drupal::service('file_system')->realpath($directory) . DIRECTORY_SEPARATOR . $this->randomMachineName() . DIRECTORY_SEPARATOR . $this->randomMachineName();
|
||||
$this->assertTrue(drupal_mkdir($absolute_path, 0775, TRUE), 'No error reported when creating new absolute directories.', 'File');
|
||||
$this->assertDirectoryPermissions($absolute_path, 0775);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Layout;
|
||||
|
||||
use Drupal\Core\Layout\Icon\SvgIconBuilder;
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Layout\Icon\SvgIconBuilder
|
||||
* @group Layout
|
||||
*/
|
||||
class IconBuilderTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* @covers ::build
|
||||
* @covers ::buildRenderArray
|
||||
* @covers ::calculateSvgValues
|
||||
* @covers ::getLength
|
||||
* @covers ::getOffset
|
||||
*
|
||||
* @dataProvider providerTestBuild
|
||||
*/
|
||||
public function testBuild(SvgIconBuilder $icon_builder, $icon_map, $expected) {
|
||||
$renderer = $this->container->get('renderer');
|
||||
|
||||
$build = $icon_builder->build($icon_map);
|
||||
|
||||
$output = (string) $renderer->executeInRenderContext(new RenderContext(), function () use ($build, $renderer) {
|
||||
return $renderer->render($build);
|
||||
});
|
||||
$this->assertSame($expected, $output);
|
||||
}
|
||||
|
||||
public function providerTestBuild() {
|
||||
$data = [];
|
||||
$data['empty'][] = (new SvgIconBuilder());
|
||||
$data['empty'][] = [];
|
||||
$data['empty'][] = <<<'EOD'
|
||||
<svg width="125" height="150" class="layout-icon"></svg>
|
||||
|
||||
EOD;
|
||||
|
||||
$data['two_column'][] = (new SvgIconBuilder())
|
||||
->setId('two_column')
|
||||
->setLabel('Two Column')
|
||||
->setWidth(250)
|
||||
->setHeight(300)
|
||||
->setStrokeWidth(2);
|
||||
$data['two_column'][] = [['left', 'right']];
|
||||
$data['two_column'][] = <<<'EOD'
|
||||
<svg width="250" height="300" class="layout-icon layout-icon--two-column"><title>Two Column</title>
|
||||
<g><title>left</title>
|
||||
<rect x="1" y="1" width="121" height="298" stroke-width="2" class="layout-icon__region layout-icon__region--left" />
|
||||
</g>
|
||||
<g><title>right</title>
|
||||
<rect x="128" y="1" width="121" height="298" stroke-width="2" class="layout-icon__region layout-icon__region--right" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
EOD;
|
||||
|
||||
$data['two_column_no_stroke'][] = (new SvgIconBuilder())
|
||||
->setWidth(250)
|
||||
->setHeight(300)
|
||||
->setStrokeWidth(NULL);
|
||||
$data['two_column_no_stroke'][] = [['left', 'right']];
|
||||
$data['two_column_no_stroke'][] = <<<'EOD'
|
||||
<svg width="250" height="300" class="layout-icon"><g><title>left</title>
|
||||
<rect x="0" y="0" width="123" height="300" class="layout-icon__region layout-icon__region--left" />
|
||||
</g>
|
||||
<g><title>right</title>
|
||||
<rect x="127" y="0" width="123" height="300" class="layout-icon__region layout-icon__region--right" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
EOD;
|
||||
|
||||
$data['two_column_border_collapse'][] = (new SvgIconBuilder())
|
||||
->setWidth(250)
|
||||
->setHeight(300)
|
||||
->setStrokeWidth(2)
|
||||
->setPadding(-2);
|
||||
$data['two_column_border_collapse'][] = [['left', 'right']];
|
||||
$data['two_column_border_collapse'][] = <<<'EOD'
|
||||
<svg width="250" height="300" class="layout-icon"><g><title>left</title>
|
||||
<rect x="1" y="1" width="124" height="298" stroke-width="2" class="layout-icon__region layout-icon__region--left" />
|
||||
</g>
|
||||
<g><title>right</title>
|
||||
<rect x="125" y="1" width="124" height="298" stroke-width="2" class="layout-icon__region layout-icon__region--right" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
EOD;
|
||||
|
||||
$data['stacked'][] = (new SvgIconBuilder())
|
||||
->setStrokeWidth(2);
|
||||
$data['stacked'][] = [
|
||||
['sidebar', 'top', 'top'],
|
||||
['sidebar', 'left', 'right'],
|
||||
['sidebar', 'middle', 'middle'],
|
||||
['footer_left', 'footer_right'],
|
||||
['footer_full'],
|
||||
];
|
||||
$data['stacked'][] = <<<'EOD'
|
||||
<svg width="125" height="150" class="layout-icon"><g><title>sidebar</title>
|
||||
<rect x="1" y="1" width="37" height="86.4" stroke-width="2" class="layout-icon__region layout-icon__region--sidebar" />
|
||||
</g>
|
||||
<g><title>top</title>
|
||||
<rect x="44" y="1" width="80" height="24.8" stroke-width="2" class="layout-icon__region layout-icon__region--top" />
|
||||
</g>
|
||||
<g><title>left</title>
|
||||
<rect x="44" y="31.8" width="37" height="24.8" stroke-width="2" class="layout-icon__region layout-icon__region--left" />
|
||||
</g>
|
||||
<g><title>right</title>
|
||||
<rect x="87" y="31.8" width="37" height="24.8" stroke-width="2" class="layout-icon__region layout-icon__region--right" />
|
||||
</g>
|
||||
<g><title>middle</title>
|
||||
<rect x="44" y="62.6" width="80" height="24.8" stroke-width="2" class="layout-icon__region layout-icon__region--middle" />
|
||||
</g>
|
||||
<g><title>footer_left</title>
|
||||
<rect x="1" y="93.4" width="58.5" height="24.8" stroke-width="2" class="layout-icon__region layout-icon__region--footer-left" />
|
||||
</g>
|
||||
<g><title>footer_right</title>
|
||||
<rect x="65.5" y="93.4" width="58.5" height="24.8" stroke-width="2" class="layout-icon__region layout-icon__region--footer-right" />
|
||||
</g>
|
||||
<g><title>footer_full</title>
|
||||
<rect x="1" y="124.2" width="123" height="24.8" stroke-width="2" class="layout-icon__region layout-icon__region--footer-full" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
EOD;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Messenger;
|
||||
|
||||
use Drupal\Core\Messenger\LegacyMessenger;
|
||||
use Drupal\Core\Messenger\Messenger;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* @group Messenger
|
||||
* @coversDefaultClass \Drupal\Core\Messenger\LegacyMessenger
|
||||
*
|
||||
* Note: The Symphony PHPUnit Bridge automatically treats any test class that
|
||||
* starts with "Legacy" as a deprecation. To subvert that, reverse it here.
|
||||
*
|
||||
* @see http://symfony.com/blog/new-in-symfony-2-7-phpunit-bridge
|
||||
* @see https://www.drupal.org/node/2931598#comment-12395743
|
||||
*/
|
||||
class MessengerLegacyTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Retrieves the Messenger service from LegacyMessenger.
|
||||
*
|
||||
* @param \Drupal\Core\Messenger\LegacyMessenger $legacy_messenger
|
||||
* The legacy messenger.
|
||||
*
|
||||
* @return \Drupal\Core\Messenger\MessengerInterface|null
|
||||
* A messenger implementation.
|
||||
*/
|
||||
protected function getMessengerService(LegacyMessenger $legacy_messenger) {
|
||||
$method = new \ReflectionMethod($legacy_messenger, 'getMessengerService');
|
||||
$method->setAccessible(TRUE);
|
||||
return $method->invoke($legacy_messenger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal::messenger
|
||||
* @covers ::getMessengerService
|
||||
* @covers ::all
|
||||
* @covers ::addMessage
|
||||
* @covers ::addError
|
||||
* @covers ::addStatus
|
||||
* @covers ::addWarning
|
||||
*/
|
||||
public function testMessages() {
|
||||
// Save the current container for later use.
|
||||
$container = \Drupal::getContainer();
|
||||
|
||||
// Unset the container to mimic not having one.
|
||||
\Drupal::unsetContainer();
|
||||
|
||||
/** @var \Drupal\Core\Messenger\LegacyMessenger $messenger */
|
||||
// Verify that the Messenger service doesn't exists.
|
||||
$messenger = \Drupal::messenger();
|
||||
$this->assertNull($this->getMessengerService($messenger));
|
||||
|
||||
// Add messages.
|
||||
$messenger->addMessage('Foobar', 'custom');
|
||||
$messenger->addMessage('Foobar', 'custom', TRUE);
|
||||
$messenger->addError('Foo');
|
||||
$messenger->addError('Foo', TRUE);
|
||||
|
||||
// Verify that retrieving another instance and adding more messages works.
|
||||
$messenger = \Drupal::messenger();
|
||||
$messenger->addStatus('Bar');
|
||||
$messenger->addStatus('Bar', TRUE);
|
||||
$messenger->addWarning('Fiz');
|
||||
$messenger->addWarning('Fiz', TRUE);
|
||||
|
||||
// Restore the container.
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
// Verify that the Messenger service exists.
|
||||
$messenger = \Drupal::messenger();
|
||||
$this->assertInstanceOf(Messenger::class, $this->getMessengerService($messenger));
|
||||
|
||||
// Add more messages.
|
||||
$messenger->addMessage('Platypus', 'custom');
|
||||
$messenger->addMessage('Platypus', 'custom', TRUE);
|
||||
$messenger->addError('Rhinoceros');
|
||||
$messenger->addError('Rhinoceros', TRUE);
|
||||
$messenger->addStatus('Giraffe');
|
||||
$messenger->addStatus('Giraffe', TRUE);
|
||||
$messenger->addWarning('Cheetah');
|
||||
$messenger->addWarning('Cheetah', TRUE);
|
||||
|
||||
// Verify all messages added via LegacyMessenger are accounted for.
|
||||
$messages = $messenger->all();
|
||||
$this->assertContains('Foobar', $messages['custom']);
|
||||
$this->assertContains('Foo', $messages[MessengerInterface::TYPE_ERROR]);
|
||||
$this->assertContains('Bar', $messages[MessengerInterface::TYPE_STATUS]);
|
||||
$this->assertContains('Fiz', $messages[MessengerInterface::TYPE_WARNING]);
|
||||
|
||||
// Verify all messages added via Messenger service are accounted for.
|
||||
$this->assertContains('Platypus', $messages['custom']);
|
||||
$this->assertContains('Rhinoceros', $messages[MessengerInterface::TYPE_ERROR]);
|
||||
$this->assertContains('Giraffe', $messages[MessengerInterface::TYPE_STATUS]);
|
||||
$this->assertContains('Cheetah', $messages[MessengerInterface::TYPE_WARNING]);
|
||||
|
||||
// Verify repeat counts.
|
||||
$this->assertCount(4, $messages['custom']);
|
||||
$this->assertCount(4, $messages[MessengerInterface::TYPE_STATUS]);
|
||||
$this->assertCount(4, $messages[MessengerInterface::TYPE_WARNING]);
|
||||
$this->assertCount(4, $messages[MessengerInterface::TYPE_ERROR]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Messenger;
|
||||
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\Render\Markup;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* @group Messenger
|
||||
* @coversDefaultClass \Drupal\Core\Messenger\Messenger
|
||||
*/
|
||||
class MessengerTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* The messenger under test.
|
||||
*
|
||||
* @var \Drupal\Core\Messenger\MessengerInterface
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->messenger = \Drupal::service('messenger');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addStatus
|
||||
* @covers ::deleteByType
|
||||
* @covers ::messagesByType
|
||||
*/
|
||||
public function testRemoveSingleMessage() {
|
||||
|
||||
// Set two messages.
|
||||
$this->messenger->addStatus('First message (removed).');
|
||||
$this->messenger->addStatus(t('Second message with <em>markup!</em> (not removed).'));
|
||||
$messages = $this->messenger->deleteByType(MessengerInterface::TYPE_STATUS);
|
||||
// Remove the first.
|
||||
unset($messages[0]);
|
||||
|
||||
// Re-add the second.
|
||||
foreach ($messages as $message) {
|
||||
$this->messenger->addStatus($message);
|
||||
}
|
||||
|
||||
// Check we only have the second one.
|
||||
$this->assertCount(1, $this->messenger->messagesByType(MessengerInterface::TYPE_STATUS));
|
||||
$this->assertContains('Second message with <em>markup!</em> (not removed).', $this->messenger->deleteByType(MessengerInterface::TYPE_STATUS));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests we don't add duplicates.
|
||||
*
|
||||
* @covers ::all
|
||||
* @covers ::addStatus
|
||||
* @covers ::addWarning
|
||||
* @covers ::addError
|
||||
* @covers ::deleteByType
|
||||
* @covers ::deleteAll
|
||||
*/
|
||||
public function testAddNoDuplicates() {
|
||||
|
||||
$this->messenger->addStatus('Non Duplicated status message');
|
||||
$this->messenger->addStatus('Non Duplicated status message');
|
||||
|
||||
$this->assertCount(1, $this->messenger->messagesByType(MessengerInterface::TYPE_STATUS));
|
||||
|
||||
$this->messenger->addWarning('Non Duplicated warning message');
|
||||
$this->messenger->addWarning('Non Duplicated warning message');
|
||||
|
||||
$this->assertCount(1, $this->messenger->messagesByType(MessengerInterface::TYPE_WARNING));
|
||||
|
||||
$this->messenger->addError('Non Duplicated error message');
|
||||
$this->messenger->addError('Non Duplicated error message');
|
||||
|
||||
$messages = $this->messenger->messagesByType(MessengerInterface::TYPE_ERROR);
|
||||
$this->assertCount(1, $messages);
|
||||
|
||||
// Check getting all messages.
|
||||
$messages = $this->messenger->all();
|
||||
$this->assertCount(3, $messages);
|
||||
$this->assertArrayHasKey(MessengerInterface::TYPE_STATUS, $messages);
|
||||
$this->assertArrayHasKey(MessengerInterface::TYPE_WARNING, $messages);
|
||||
$this->assertArrayHasKey(MessengerInterface::TYPE_ERROR, $messages);
|
||||
|
||||
// Check deletion.
|
||||
$this->messenger->deleteAll();
|
||||
$this->assertCount(0, $this->messenger->messagesByType(MessengerInterface::TYPE_STATUS));
|
||||
$this->assertCount(0, $this->messenger->messagesByType(MessengerInterface::TYPE_WARNING));
|
||||
$this->assertCount(0, $this->messenger->messagesByType(MessengerInterface::TYPE_ERROR));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests we do add duplicates with repeat flag.
|
||||
*
|
||||
* @covers ::addStatus
|
||||
* @covers ::addWarning
|
||||
* @covers ::addError
|
||||
* @covers ::deleteByType
|
||||
*/
|
||||
public function testAddWithDuplicates() {
|
||||
|
||||
$this->messenger->addStatus('Duplicated status message', TRUE);
|
||||
$this->messenger->addStatus('Duplicated status message', TRUE);
|
||||
|
||||
$this->assertCount(2, $this->messenger->deleteByType(MessengerInterface::TYPE_STATUS));
|
||||
|
||||
$this->messenger->addWarning('Duplicated warning message', TRUE);
|
||||
$this->messenger->addWarning('Duplicated warning message', TRUE);
|
||||
|
||||
$this->assertCount(2, $this->messenger->deleteByType(MessengerInterface::TYPE_WARNING));
|
||||
|
||||
$this->messenger->addError('Duplicated error message', TRUE);
|
||||
$this->messenger->addError('Duplicated error message', TRUE);
|
||||
|
||||
$this->assertCount(2, $this->messenger->deleteByType(MessengerInterface::TYPE_ERROR));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding markup.
|
||||
*
|
||||
* @covers ::addStatus
|
||||
* @covers ::deleteByType
|
||||
* @covers ::messagesByType
|
||||
*/
|
||||
public function testAddMarkup() {
|
||||
|
||||
// Add a Markup message.
|
||||
$this->messenger->addStatus(Markup::create('Markup with <em>markup!</em>'));
|
||||
// Test duplicate Markup messages.
|
||||
$this->messenger->addStatus(Markup::create('Markup with <em>markup!</em>'));
|
||||
|
||||
$this->assertCount(1, $this->messenger->messagesByType(MessengerInterface::TYPE_STATUS));
|
||||
|
||||
// Ensure that multiple Markup messages work.
|
||||
$this->messenger->addStatus(Markup::create('Markup2 with <em>markup!</em>'));
|
||||
|
||||
$this->assertCount(2, $this->messenger->deleteByType(MessengerInterface::TYPE_STATUS));
|
||||
|
||||
// Test mixing of types.
|
||||
$this->messenger->addStatus(Markup::create('Non duplicate Markup / string.'));
|
||||
$this->messenger->addStatus('Non duplicate Markup / string.');
|
||||
$this->messenger->addStatus(Markup::create('Duplicate Markup / string.'), TRUE);
|
||||
$this->messenger->addStatus('Duplicate Markup / string.', TRUE);
|
||||
|
||||
$this->assertCount(3, $this->messenger->deleteByType(MessengerInterface::TYPE_STATUS));
|
||||
|
||||
$this->messenger->deleteAll();
|
||||
|
||||
// Check translatable string is converted to Markup.
|
||||
$this->messenger->addStatus(new TranslatableMarkup('Translatable message'));
|
||||
$messages = $this->messenger->deleteByType(MessengerInterface::TYPE_STATUS);
|
||||
|
||||
$this->assertInstanceOf(Markup::class, $messages[0]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\ParamConverter;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\entity_test\Entity\EntityTestMulRev;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests the entity converter when the "load_latest_revision" flag is set.
|
||||
*
|
||||
* @group ParamConverter
|
||||
* @coversDefaultClass \Drupal\Core\ParamConverter\EntityConverter
|
||||
*/
|
||||
class EntityConverterLatestRevisionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'entity_test',
|
||||
'user',
|
||||
'language',
|
||||
'system',
|
||||
];
|
||||
|
||||
/**
|
||||
* The entity converter service.
|
||||
*
|
||||
* @var \Drupal\Core\ParamConverter\EntityConverter
|
||||
*/
|
||||
protected $converter;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('entity_test_mulrev');
|
||||
$this->installEntitySchema('entity_test');
|
||||
$this->installConfig(['system', 'language']);
|
||||
|
||||
$this->converter = $this->container->get('paramconverter.entity');
|
||||
|
||||
ConfigurableLanguage::createFromLangcode('de')->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with no matching entity.
|
||||
*/
|
||||
public function testNoEntity() {
|
||||
$converted = $this->converter->convert(1, [
|
||||
'load_latest_revision' => TRUE,
|
||||
'type' => 'entity:entity_test_mulrev',
|
||||
], 'foo', []);
|
||||
$this->assertEquals(NULL, $converted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with no pending revision.
|
||||
*/
|
||||
public function testEntityNoPendingRevision() {
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
|
||||
$converted = $this->converter->convert(1, [
|
||||
'load_latest_revision' => TRUE,
|
||||
'type' => 'entity:entity_test_mulrev',
|
||||
], 'foo', []);
|
||||
$this->assertEquals($entity->getLoadedRevisionId(), $converted->getLoadedRevisionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with a pending revision.
|
||||
*/
|
||||
public function testEntityWithPendingRevision() {
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
|
||||
$entity->isDefaultRevision(FALSE);
|
||||
$entity->setNewRevision(TRUE);
|
||||
$entity->save();
|
||||
|
||||
$converted = $this->converter->convert(1, [
|
||||
'load_latest_revision' => TRUE,
|
||||
'type' => 'entity:entity_test_mulrev',
|
||||
], 'foo', []);
|
||||
|
||||
$this->assertEquals($entity->getLoadedRevisionId(), $converted->getLoadedRevisionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with a translated pending revision.
|
||||
*/
|
||||
public function testWithTranslatedPendingRevision() {
|
||||
// Enable translation for test entities.
|
||||
$this->container->get('state')->set('entity_test.translation', TRUE);
|
||||
$this->container->get('entity_type.bundle.info')->clearCachedBundles();
|
||||
|
||||
// Create a new English entity.
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
|
||||
// Create a translated pending revision.
|
||||
$entity_type_id = 'entity_test_mulrev';
|
||||
/** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage($entity_type_id);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $translated_entity */
|
||||
$translated_entity = $storage->createRevision($entity->addTranslation('de'), FALSE);
|
||||
$translated_entity->save();
|
||||
|
||||
// Change the site language so the converters will attempt to load entities
|
||||
// with language 'de'.
|
||||
$this->config('system.site')->set('default_langcode', 'de')->save();
|
||||
|
||||
// The default loaded language is still 'en'.
|
||||
EntityTestMulRev::load($entity->id());
|
||||
$this->assertEquals('en', $entity->language()->getId());
|
||||
|
||||
// The converter will load the latest revision in the correct language.
|
||||
$converted = $this->converter->convert(1, [
|
||||
'load_latest_revision' => TRUE,
|
||||
'type' => 'entity:entity_test_mulrev',
|
||||
], 'foo', []);
|
||||
$this->assertEquals('de', $converted->language()->getId());
|
||||
$this->assertEquals($translated_entity->getLoadedRevisionId(), $converted->getLoadedRevisionId());
|
||||
|
||||
// Revert back to English as default language.
|
||||
$this->config('system.site')->set('default_langcode', 'en')->save();
|
||||
|
||||
// The converter will load the latest revision in the correct language.
|
||||
$converted = $this->converter->convert(1, [
|
||||
'load_latest_revision' => TRUE,
|
||||
'type' => 'entity:entity_test_mulrev',
|
||||
], 'foo', []);
|
||||
$this->assertEquals('en', $converted->language()->getId());
|
||||
$this->assertEquals($entity->getLoadedRevisionId(), $converted->getLoadedRevisionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that pending revisions are loaded only when needed.
|
||||
*/
|
||||
public function testOptimizedConvert() {
|
||||
$entity = EntityTestMulRev::create();
|
||||
$entity->save();
|
||||
|
||||
// Populate static cache for the current entity.
|
||||
$entity = EntityTestMulRev::load($entity->id());
|
||||
|
||||
// Delete the base table entry for the current entity, however, since the
|
||||
// storage will query the revision table to get the latest revision, the
|
||||
// logic handling pending revisions will work correctly anyway.
|
||||
/** @var \Drupal\Core\Database\Connection $database */
|
||||
$database = $this->container->get('database');
|
||||
$database->delete('entity_test_mulrev')
|
||||
->condition('id', $entity->id())
|
||||
->execute();
|
||||
|
||||
// If optimization works, converting a default revision should not trigger
|
||||
// a storage load, thus making the following assertion pass.
|
||||
$converted = $this->converter->convert(1, [
|
||||
'load_latest_revision' => TRUE,
|
||||
'type' => 'entity:entity_test_mulrev',
|
||||
], 'foo', []);
|
||||
$this->assertEquals($entity->getLoadedRevisionId(), $converted->getLoadedRevisionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the latest revision flag and non-revisionable entities.
|
||||
*/
|
||||
public function testConvertNonRevisionableEntityType() {
|
||||
$entity = EntityTest::create();
|
||||
$entity->save();
|
||||
|
||||
$converted = $this->converter->convert(1, [
|
||||
'load_latest_revision' => TRUE,
|
||||
'type' => 'entity:entity_test',
|
||||
], 'foo', []);
|
||||
|
||||
$this->assertEquals($entity->id(), $converted->id());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class PathValidatorTest extends KernelTestBase {
|
||||
$url = $pathValidator->getUrlIfValidWithoutAccessCheck($entity->toUrl()->toString(TRUE)->getGeneratedUrl());
|
||||
$this->assertEquals($method, $requestContext->getMethod());
|
||||
$this->assertInstanceOf(Url::class, $url);
|
||||
$this->assertSame($url->getRouteParameters(), ['entity_test' => $entity->id()]);
|
||||
$this->assertSame(['entity_test' => $entity->id()], $url->getRouteParameters());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ use Drupal\Core\Routing\MatcherDumper;
|
||||
use Drupal\Core\Routing\RouteProvider;
|
||||
use Drupal\Core\State\State;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Tests\Core\Routing\RoutingFixtures;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
@@ -36,7 +37,7 @@ class RouteProviderTest extends KernelTestBase {
|
||||
/**
|
||||
* Modules to enable.
|
||||
*/
|
||||
public static $modules = ['url_alter_test', 'system'];
|
||||
public static $modules = ['url_alter_test', 'system', 'language'];
|
||||
|
||||
/**
|
||||
* A collection of shared fixture data for tests.
|
||||
@@ -544,7 +545,8 @@ class RouteProviderTest extends KernelTestBase {
|
||||
*/
|
||||
public function testRouteCaching() {
|
||||
$connection = Database::getConnection();
|
||||
$provider = new RouteProvider($connection, $this->state, $this->currentPath, $this->cache, $this->pathProcessor, $this->cacheTagsInvalidator, 'test_routes');
|
||||
$language_manager = \Drupal::languageManager();
|
||||
$provider = new RouteProvider($connection, $this->state, $this->currentPath, $this->cache, $this->pathProcessor, $this->cacheTagsInvalidator, 'test_routes', $language_manager);
|
||||
|
||||
$this->fixtures->createTables($connection);
|
||||
|
||||
@@ -558,7 +560,7 @@ class RouteProviderTest extends KernelTestBase {
|
||||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:/path/add/one:');
|
||||
$cache = $this->cache->get('route:en:/path/add/one:');
|
||||
$this->assertEqual('/path/add/one', $cache->data['path']);
|
||||
$this->assertEqual([], $cache->data['query']);
|
||||
$this->assertEqual(3, count($cache->data['routes']));
|
||||
@@ -568,7 +570,7 @@ class RouteProviderTest extends KernelTestBase {
|
||||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:/path/add/one:foo=bar');
|
||||
$cache = $this->cache->get('route:en:/path/add/one:foo=bar');
|
||||
$this->assertEqual('/path/add/one', $cache->data['path']);
|
||||
$this->assertEqual(['foo' => 'bar'], $cache->data['query']);
|
||||
$this->assertEqual(3, count($cache->data['routes']));
|
||||
@@ -578,7 +580,7 @@ class RouteProviderTest extends KernelTestBase {
|
||||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:/path/1/one:');
|
||||
$cache = $this->cache->get('route:en:/path/1/one:');
|
||||
$this->assertEqual('/path/1/one', $cache->data['path']);
|
||||
$this->assertEqual([], $cache->data['query']);
|
||||
$this->assertEqual(2, count($cache->data['routes']));
|
||||
@@ -595,10 +597,25 @@ class RouteProviderTest extends KernelTestBase {
|
||||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:/path/add-one:');
|
||||
$cache = $this->cache->get('route:en:/path/add-one:');
|
||||
$this->assertEqual('/path/add/one', $cache->data['path']);
|
||||
$this->assertEqual([], $cache->data['query']);
|
||||
$this->assertEqual(3, count($cache->data['routes']));
|
||||
|
||||
// Test with a different current language by switching out the default
|
||||
// language.
|
||||
$swiss = ConfigurableLanguage::createFromLangcode('gsw-berne');
|
||||
$language_manager->reset();
|
||||
\Drupal::service('language.default')->set($swiss);
|
||||
|
||||
$path = '/path/add-one';
|
||||
$request = Request::create($path, 'GET');
|
||||
$provider->getRouteCollectionForRequest($request);
|
||||
|
||||
$cache = $this->cache->get('route:gsw-berne:/path/add-one:');
|
||||
$this->assertEquals('/path/add/one', $cache->data['path']);
|
||||
$this->assertEquals([], $cache->data['query']);
|
||||
$this->assertEquals(3, count($cache->data['routes']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\TempStore;
|
||||
|
||||
use Drupal\Core\KeyValueStore\KeyValueExpirableFactory;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Core\TempStore\SharedTempStoreFactory;
|
||||
use Drupal\Core\Lock\DatabaseLockBackend;
|
||||
use Drupal\Core\Database\Database;
|
||||
|
||||
/**
|
||||
* Tests the temporary object storage system.
|
||||
*
|
||||
* @group TempStore
|
||||
* @see \Drupal\Core\TempStore\SharedTempStore
|
||||
*/
|
||||
class TempStoreDatabaseTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['system'];
|
||||
|
||||
/**
|
||||
* A key/value store factory.
|
||||
*
|
||||
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
|
||||
*/
|
||||
protected $storeFactory;
|
||||
|
||||
/**
|
||||
* The name of the key/value collection to set and retrieve.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* An array of random stdClass objects.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $objects = [];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Install system tables to test the key/value storage without installing a
|
||||
// full Drupal environment.
|
||||
$this->installSchema('system', ['key_value_expire']);
|
||||
|
||||
// Create several objects for testing.
|
||||
for ($i = 0; $i <= 3; $i++) {
|
||||
$this->objects[$i] = $this->randomObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the SharedTempStore API.
|
||||
*/
|
||||
public function testSharedTempStore() {
|
||||
// Create a key/value collection.
|
||||
$factory = new SharedTempStoreFactory(new KeyValueExpirableFactory(\Drupal::getContainer()), new DatabaseLockBackend(Database::getConnection()), $this->container->get('request_stack'));
|
||||
$collection = $this->randomMachineName();
|
||||
|
||||
// Create two mock users.
|
||||
for ($i = 0; $i <= 1; $i++) {
|
||||
$users[$i] = mt_rand(500, 5000000);
|
||||
|
||||
// Storing the SharedTempStore objects in a class member variable causes a
|
||||
// fatal exception, because in that situation garbage collection is not
|
||||
// triggered until the test class itself is destructed, after tearDown()
|
||||
// has deleted the database tables. Store the objects locally instead.
|
||||
$stores[$i] = $factory->get($collection, $users[$i]);
|
||||
}
|
||||
|
||||
$key = $this->randomMachineName();
|
||||
// Test that setIfNotExists() succeeds only the first time.
|
||||
for ($i = 0; $i <= 1; $i++) {
|
||||
// setIfNotExists() should be TRUE the first time (when $i is 0) and
|
||||
// FALSE the second time (when $i is 1).
|
||||
$this->assertEqual(!$i, $stores[0]->setIfNotExists($key, $this->objects[$i]));
|
||||
$metadata = $stores[0]->getMetadata($key);
|
||||
$this->assertEqual($users[0], $metadata->owner);
|
||||
$this->assertIdenticalObject($this->objects[0], $stores[0]->get($key));
|
||||
// Another user should get the same result.
|
||||
$metadata = $stores[1]->getMetadata($key);
|
||||
$this->assertEqual($users[0], $metadata->owner);
|
||||
$this->assertIdenticalObject($this->objects[0], $stores[1]->get($key));
|
||||
}
|
||||
|
||||
// Remove the item and try to set it again.
|
||||
$stores[0]->delete($key);
|
||||
$stores[0]->setIfNotExists($key, $this->objects[1]);
|
||||
// This time it should succeed.
|
||||
$this->assertIdenticalObject($this->objects[1], $stores[0]->get($key));
|
||||
|
||||
// This user can update the object.
|
||||
$stores[0]->set($key, $this->objects[2]);
|
||||
$this->assertIdenticalObject($this->objects[2], $stores[0]->get($key));
|
||||
// The object is the same when another user loads it.
|
||||
$this->assertIdenticalObject($this->objects[2], $stores[1]->get($key));
|
||||
|
||||
// This user should be allowed to get, update, delete.
|
||||
$this->assertTrue($stores[0]->getIfOwner($key) instanceof \stdClass);
|
||||
$this->assertTrue($stores[0]->setIfOwner($key, $this->objects[1]));
|
||||
$this->assertTrue($stores[0]->deleteIfOwner($key));
|
||||
|
||||
// Another user can update the object and become the owner.
|
||||
$stores[1]->set($key, $this->objects[3]);
|
||||
$this->assertIdenticalObject($this->objects[3], $stores[0]->get($key));
|
||||
$this->assertIdenticalObject($this->objects[3], $stores[1]->get($key));
|
||||
$metadata = $stores[1]->getMetadata($key);
|
||||
$this->assertEqual($users[1], $metadata->owner);
|
||||
|
||||
// The first user should be informed that the second now owns the data.
|
||||
$metadata = $stores[0]->getMetadata($key);
|
||||
$this->assertEqual($users[1], $metadata->owner);
|
||||
|
||||
// The first user should no longer be allowed to get, update, delete.
|
||||
$this->assertNull($stores[0]->getIfOwner($key));
|
||||
$this->assertFalse($stores[0]->setIfOwner($key, $this->objects[1]));
|
||||
$this->assertFalse($stores[0]->deleteIfOwner($key));
|
||||
|
||||
// Now manually expire the item (this is not exposed by the API) and then
|
||||
// assert it is no longer accessible.
|
||||
db_update('key_value_expire')
|
||||
->fields(['expire' => REQUEST_TIME - 1])
|
||||
->condition('collection', "tempstore.shared.$collection")
|
||||
->condition('name', $key)
|
||||
->execute();
|
||||
$this->assertFalse($stores[0]->get($key));
|
||||
$this->assertFalse($stores[1]->get($key));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\KernelTests\Core\Test;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass;
|
||||
|
||||
/**
|
||||
* Test how kernel tests interact with deprecation errors.
|
||||
*
|
||||
* @group Test
|
||||
* @group legacy
|
||||
*/
|
||||
class PhpUnitBridgeTest extends KernelTestBase {
|
||||
|
||||
public static $modules = ['deprecation_test'];
|
||||
|
||||
/**
|
||||
* @expectedDeprecation Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass is deprecated.
|
||||
*/
|
||||
public function testDeprecatedClass() {
|
||||
$deprecated = new FixtureDeprecatedClass();
|
||||
$this->assertEquals('test', $deprecated->testFunction());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation This is the deprecation message for deprecation_test_function().
|
||||
*/
|
||||
public function testDeprecatedFunction() {
|
||||
$this->assertEquals('known_return_value', \deprecation_test_function());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -192,4 +192,23 @@ class RegistryTest extends KernelTestBase {
|
||||
], $suggestions, 'Found expected page node suggestions.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests theme-provided templates that are registered by modules.
|
||||
*/
|
||||
public function testThemeTemplatesRegisteredByModules() {
|
||||
$theme_handler = \Drupal::service('theme_handler');
|
||||
$theme_handler->install(['test_theme']);
|
||||
|
||||
$registry_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_theme');
|
||||
$registry_theme->setThemeManager(\Drupal::theme());
|
||||
|
||||
$expected = [
|
||||
'template_preprocess',
|
||||
'template_preprocess_container',
|
||||
'template_preprocess_theme_test_registered_by_module'
|
||||
];
|
||||
$registry = $registry_theme->get();
|
||||
$this->assertEquals($expected, array_values($registry['theme_test_registered_by_module']['preprocess functions']));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ class StableTemplateOverrideTest extends KernelTestBase {
|
||||
*/
|
||||
protected $templatesToSkip = [
|
||||
'views-form-views-form',
|
||||
'entity-moderation-form'
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,7 +57,7 @@ class TwigMarkupInterfaceTest extends KernelTestBase {
|
||||
'empty GeneratedLink' => ['', new GeneratedLink()],
|
||||
'non-empty GeneratedLink' => ['<span><a hef="http://www.example.com">test</a></span>', (new GeneratedLink())->setGeneratedLink('<a hef="http://www.example.com">test</a>')],
|
||||
// Test objects that do not implement \Countable.
|
||||
'empty SafeMarkupTestMarkup' => ['<span></span>', SafeMarkupTestMarkup::create('')],
|
||||
'empty SafeMarkupTestMarkup' => ['', SafeMarkupTestMarkup::create('')],
|
||||
'non-empty SafeMarkupTestMarkup' => ['<span>test</span>', SafeMarkupTestMarkup::create('test')],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class UpdaterTest extends KernelTestBase {
|
||||
* @see https://drupal.org/node/2409515
|
||||
*/
|
||||
public function testGetProjectTitleWithChild() {
|
||||
// Get the project title from it's directory. If it can't find the title
|
||||
// Get the project title from its directory. If it can't find the title
|
||||
// it will choose the first project title in the directory.
|
||||
$directory = \Drupal::root() . '/core/modules/system/tests/modules/module_handler_test_multiple';
|
||||
$title = Updater::getProjectTitle($directory);
|
||||
|
||||
@@ -251,7 +251,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
|
||||
* Should not be called by tests. Only visible for DrupalKernel integration
|
||||
* tests.
|
||||
*
|
||||
* @see \Drupal\system\Tests\DrupalKernel\DrupalKernelTest
|
||||
* @see \Drupal\KernelTests\Core\DrupalKernel\DrupalKernelTest
|
||||
* @internal
|
||||
*/
|
||||
protected function bootEnvironment() {
|
||||
|
||||
@@ -137,6 +137,10 @@ class KernelTestBaseTest extends KernelTestBase {
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Request', $new_request);
|
||||
$this->assertSame($new_request, \Drupal::request());
|
||||
$this->assertSame($request, $new_request);
|
||||
|
||||
// Ensure getting the router.route_provider does not trigger a deprecation
|
||||
// message that errors.
|
||||
$this->container->get('router.route_provider');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -345,12 +345,12 @@ abstract class BrowserTestBase extends TestCase {
|
||||
* When provided default Mink driver class can't be instantiated.
|
||||
*/
|
||||
protected function getDefaultDriverInstance() {
|
||||
// Get default driver params from environment if availables.
|
||||
if ($arg_json = getenv('MINK_DRIVER_ARGS')) {
|
||||
// Get default driver params from environment if available.
|
||||
if ($arg_json = $this->getMinkDriverArgs()) {
|
||||
$this->minkDefaultDriverArgs = json_decode($arg_json, TRUE);
|
||||
}
|
||||
|
||||
// Get and check default driver class from environment if availables.
|
||||
// Get and check default driver class from environment if available.
|
||||
if ($minkDriverClass = getenv('MINK_DRIVER_CLASS')) {
|
||||
if (class_exists($minkDriverClass)) {
|
||||
$this->minkDefaultDriverClass = $minkDriverClass;
|
||||
@@ -395,6 +395,18 @@ abstract class BrowserTestBase extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Mink driver args from an environment variable, if it is set. Can
|
||||
* be overridden in a derived class so it is possible to use a different
|
||||
* value for a subset of tests, e.g. the JavaScript tests.
|
||||
*
|
||||
* @return string|false
|
||||
* The JSON-encoded argument string. False if it is not set.
|
||||
*/
|
||||
protected function getMinkDriverArgs() {
|
||||
return getenv('MINK_DRIVER_ARGS');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a Guzzle middleware handler to log every response received.
|
||||
*
|
||||
@@ -485,6 +497,11 @@ abstract class BrowserTestBase extends TestCase {
|
||||
if ($disable_gc) {
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
// Ensure that the test is not marked as risky because of no assertions. In
|
||||
// PHPUnit 6 tests that only make assertions using $this->assertSession()
|
||||
// can be marked as risky.
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery;
|
||||
use Drupal\Component\FileCache\FileCacheFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery
|
||||
* @group Annotation
|
||||
*/
|
||||
class AnnotatedClassDiscoveryCachedTest extends TestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Ensure FileCacheFactory::DISABLE_CACHE is *not* set, since we're testing
|
||||
// integration with the file cache.
|
||||
FileCacheFactory::setConfiguration([]);
|
||||
// Ensure that FileCacheFactory has a prefix.
|
||||
FileCacheFactory::setPrefix('prefix');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getDefinitions() retrieves the file cache correctly.
|
||||
*
|
||||
* @covers ::getDefinitions
|
||||
*/
|
||||
public function testGetDefinitions() {
|
||||
// Path to the classes which we'll discover and parse annotation.
|
||||
$discovery_path = __DIR__ . '/Fixtures';
|
||||
// File path that should be discovered within that directory.
|
||||
$file_path = $discovery_path . '/PluginNamespace/DiscoveryTest1.php';
|
||||
|
||||
$discovery = new AnnotatedClassDiscovery(['com\example' => [$discovery_path]]);
|
||||
$this->assertEquals([
|
||||
'discovery_test_1' => [
|
||||
'id' => 'discovery_test_1',
|
||||
'class' => 'com\example\PluginNamespace\DiscoveryTest1',
|
||||
],
|
||||
], $discovery->getDefinitions());
|
||||
|
||||
// Gain access to the file cache so we can change it.
|
||||
$ref_file_cache = new \ReflectionProperty($discovery, 'fileCache');
|
||||
$ref_file_cache->setAccessible(TRUE);
|
||||
/* @var $file_cache \Drupal\Component\FileCache\FileCacheInterface */
|
||||
$file_cache = $ref_file_cache->getValue($discovery);
|
||||
// The file cache is keyed by the file path, and we'll add some known
|
||||
// content to test against.
|
||||
$file_cache->set($file_path, [
|
||||
'id' => 'wrong_id',
|
||||
'content' => serialize(['an' => 'array']),
|
||||
]);
|
||||
|
||||
// Now perform the same query and check for the cached results.
|
||||
$this->assertEquals([
|
||||
'wrong_id' => [
|
||||
'an' => 'array',
|
||||
],
|
||||
], $discovery->getDefinitions());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
use Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery;
|
||||
use Drupal\Component\FileCache\FileCacheFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery
|
||||
* @group Annotation
|
||||
*/
|
||||
class AnnotatedClassDiscoveryTest extends TestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Ensure the file cache is disabled.
|
||||
FileCacheFactory::setConfiguration([FileCacheFactory::DISABLE_CACHE => TRUE]);
|
||||
// Ensure that FileCacheFactory has a prefix.
|
||||
FileCacheFactory::setPrefix('prefix');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getPluginNamespaces
|
||||
*/
|
||||
public function testGetPluginNamespaces() {
|
||||
$discovery = new AnnotatedClassDiscovery(['com/example' => [__DIR__]]);
|
||||
|
||||
$reflection = new \ReflectionMethod($discovery, 'getPluginNamespaces');
|
||||
$reflection->setAccessible(TRUE);
|
||||
|
||||
$result = $reflection->invoke($discovery);
|
||||
$this->assertEquals(['com/example' => [__DIR__]], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getDefinitions
|
||||
* @covers ::prepareAnnotationDefinition
|
||||
* @covers ::getAnnotationReader
|
||||
*/
|
||||
public function testGetDefinitions() {
|
||||
$discovery = new AnnotatedClassDiscovery(['com\example' => [__DIR__ . '/Fixtures']]);
|
||||
$this->assertEquals([
|
||||
'discovery_test_1' => [
|
||||
'id' => 'discovery_test_1',
|
||||
'class' => 'com\example\PluginNamespace\DiscoveryTest1',
|
||||
],
|
||||
], $discovery->getDefinitions());
|
||||
|
||||
$custom_annotation_discovery = new AnnotatedClassDiscovery(['com\example' => [__DIR__ . '/Fixtures']], CustomPlugin::class, ['Drupal\Tests\Component\Annotation']);
|
||||
$this->assertEquals([
|
||||
'discovery_test_1' => [
|
||||
'id' => 'discovery_test_1',
|
||||
'class' => 'com\example\PluginNamespace\DiscoveryTest1',
|
||||
'title' => 'Discovery test plugin',
|
||||
],
|
||||
], $custom_annotation_discovery->getDefinitions());
|
||||
|
||||
$empty_discovery = new AnnotatedClassDiscovery(['com\example' => [__DIR__ . '/Fixtures']], CustomPlugin2::class, ['Drupal\Tests\Component\Annotation']);
|
||||
$this->assertEquals([], $empty_discovery->getDefinitions());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom plugin annotation.
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class CustomPlugin extends Plugin {
|
||||
|
||||
/**
|
||||
* The plugin ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The plugin title.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @ingroup plugin_translatable
|
||||
*/
|
||||
public $title = '';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom plugin annotation.
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class CustomPlugin2 extends Plugin {}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\AnnotationBase;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Annotation\AnnotationBase
|
||||
* @group Annotation
|
||||
*/
|
||||
class AnnotationBaseTest extends TestCase {
|
||||
|
||||
/**
|
||||
* @covers ::getProvider
|
||||
* @covers ::setProvider
|
||||
*/
|
||||
public function testSetProvider() {
|
||||
$plugin = new AnnotationBaseStub();
|
||||
$plugin->setProvider('example');
|
||||
$this->assertEquals('example', $plugin->getProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getId
|
||||
*/
|
||||
public function testGetId() {
|
||||
$plugin = new AnnotationBaseStub();
|
||||
// Doctrine sets the public prop directly.
|
||||
$plugin->id = 'example';
|
||||
$this->assertEquals('example', $plugin->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getClass
|
||||
* @covers ::setClass
|
||||
*/
|
||||
public function testSetClass() {
|
||||
$plugin = new AnnotationBaseStub();
|
||||
$plugin->setClass('example');
|
||||
$this->assertEquals('example', $plugin->getClass());
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class AnnotationBaseStub extends AnnotationBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get() {}
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace com\example\PluginNamespace;
|
||||
|
||||
/**
|
||||
* Provides a custom test plugin.
|
||||
*
|
||||
* @Plugin(
|
||||
* id = "discovery_test_1"
|
||||
* )
|
||||
* @CustomPlugin(
|
||||
* id = "discovery_test_1",
|
||||
* title = "Discovery test plugin"
|
||||
* )
|
||||
*/
|
||||
class DiscoveryTest1 {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
# This should not be loaded by our annotated class discovery.
|
||||
id:discovery_test_2
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Reflection\MockFileFinder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Annotation\Reflection\MockFileFinder
|
||||
* @group Annotation
|
||||
*/
|
||||
class MockFileFinderTest extends TestCase {
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @covers ::findFile
|
||||
*/
|
||||
public function testFindFile() {
|
||||
$tmp = MockFileFinder::create('testfilename.txt');
|
||||
$this->assertEquals('testfilename.txt', $tmp->findFile('n/a'));
|
||||
$this->assertEquals('testfilename.txt', $tmp->findFile('someclass'));
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -35,6 +35,9 @@ class AnnotationBridgeDecoratorTest extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class TestAnnotation extends Plugin {
|
||||
|
||||
/**
|
||||
@@ -45,12 +48,17 @@ class TestAnnotation extends Plugin {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class ObjectDefinition extends PluginDefinition {
|
||||
|
||||
/**
|
||||
* ObjectDefinition constructor.
|
||||
*
|
||||
* @param array $definition
|
||||
* An array of definition values.
|
||||
*/
|
||||
public function __construct(array $definition) {
|
||||
foreach ($definition as $property => $value) {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\PluginID;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Annotation\PluginId
|
||||
* @group Annotation
|
||||
*/
|
||||
class PluginIdTest extends TestCase {
|
||||
|
||||
/**
|
||||
* @covers ::get
|
||||
*/
|
||||
public function testGet() {
|
||||
// Assert plugin starts empty regardless of constructor.
|
||||
$plugin = new PluginID([
|
||||
'foo' => 'bar',
|
||||
'biz' => [
|
||||
'baz' => 'boom',
|
||||
],
|
||||
'nestedAnnotation' => new PluginID([
|
||||
'foo' => 'bar',
|
||||
]),
|
||||
'value' => 'biz',
|
||||
]);
|
||||
$this->assertEquals([
|
||||
'id' => NULL,
|
||||
'class' => NULL,
|
||||
'provider' => NULL,
|
||||
], $plugin->get());
|
||||
|
||||
// Set values and ensure we can retrieve them.
|
||||
$plugin->value = 'foo';
|
||||
$plugin->setClass('bar');
|
||||
$plugin->setProvider('baz');
|
||||
$this->assertEquals([
|
||||
'id' => 'foo',
|
||||
'class' => 'bar',
|
||||
'provider' => 'baz',
|
||||
], $plugin->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getId
|
||||
*/
|
||||
public function testGetId() {
|
||||
$plugin = new PluginID([]);
|
||||
$plugin->value = 'example';
|
||||
$this->assertEquals('example', $plugin->getId());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Annotation\Plugin
|
||||
* @group Annotation
|
||||
*/
|
||||
class PluginTest extends TestCase {
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::parse
|
||||
* @covers ::get
|
||||
*/
|
||||
public function testGet() {
|
||||
// Assert all values are accepted through constructor and default value is
|
||||
// used for non existent but defined property.
|
||||
$plugin = new PluginStub([
|
||||
'foo' => 'bar',
|
||||
'biz' => [
|
||||
'baz' => 'boom',
|
||||
],
|
||||
'nestedAnnotation' => new Plugin([
|
||||
'foo' => 'bar',
|
||||
]),
|
||||
]);
|
||||
$this->assertEquals([
|
||||
// This property wasn't in our definition but is defined as a property on
|
||||
// our plugin class.
|
||||
'defaultProperty' => 'testvalue',
|
||||
'foo' => 'bar',
|
||||
'biz' => [
|
||||
'baz' => 'boom',
|
||||
],
|
||||
'nestedAnnotation' => [
|
||||
'foo' => 'bar',
|
||||
],
|
||||
], $plugin->get());
|
||||
|
||||
// Without default properties, we get a completely empty plugin definition.
|
||||
$plugin = new Plugin([]);
|
||||
$this->assertEquals([], $plugin->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getProvider
|
||||
*/
|
||||
public function testGetProvider() {
|
||||
$plugin = new Plugin(['provider' => 'example']);
|
||||
$this->assertEquals('example', $plugin->getProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setProvider
|
||||
*/
|
||||
public function testSetProvider() {
|
||||
$plugin = new Plugin([]);
|
||||
$plugin->setProvider('example');
|
||||
$this->assertEquals('example', $plugin->getProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getId
|
||||
*/
|
||||
public function testGetId() {
|
||||
$plugin = new Plugin(['id' => 'example']);
|
||||
$this->assertEquals('example', $plugin->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getClass
|
||||
*/
|
||||
public function testGetClass() {
|
||||
$plugin = new Plugin(['class' => 'example']);
|
||||
$this->assertEquals('example', $plugin->getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setClass
|
||||
*/
|
||||
public function testSetClass() {
|
||||
$plugin = new Plugin([]);
|
||||
$plugin->setClass('example');
|
||||
$this->assertEquals('example', $plugin->getClass());
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class PluginStub extends Plugin {
|
||||
protected $defaultProperty = 'testvalue';
|
||||
|
||||
}
|
||||
@@ -87,7 +87,13 @@ class DateTimePlusTest extends TestCase {
|
||||
* @dataProvider providerTestInvalidDateDiff
|
||||
*/
|
||||
public function testInvalidDateDiff($input1, $input2, $absolute) {
|
||||
$this->setExpectedException(\BadMethodCallException::class, 'Method Drupal\Component\Datetime\DateTimePlus::diff expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\BadMethodCallException::class);
|
||||
$this->expectExceptionMessage('Method Drupal\Component\Datetime\DateTimePlus::diff expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\BadMethodCallException::class, 'Method Drupal\Component\Datetime\DateTimePlus::diff expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object');
|
||||
}
|
||||
$interval = $input1->diff($input2, $absolute);
|
||||
}
|
||||
|
||||
@@ -104,7 +110,12 @@ class DateTimePlusTest extends TestCase {
|
||||
* @dataProvider providerTestInvalidDateArrays
|
||||
*/
|
||||
public function testInvalidDateArrays($input, $timezone, $class) {
|
||||
$this->setExpectedException($class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException($class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException($class);
|
||||
}
|
||||
$this->assertInstanceOf(
|
||||
'\Drupal\Component\DateTimePlus',
|
||||
DateTimePlus::createFromArray($input, $timezone)
|
||||
@@ -242,7 +253,12 @@ class DateTimePlusTest extends TestCase {
|
||||
* @dataProvider providerTestInvalidDates
|
||||
*/
|
||||
public function testInvalidDates($input, $timezone, $format, $message, $class) {
|
||||
$this->setExpectedException($class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException($class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException($class);
|
||||
}
|
||||
DateTimePlus::createFromFormat($format, $input, $timezone);
|
||||
}
|
||||
|
||||
@@ -800,10 +816,27 @@ class DateTimePlusTest extends TestCase {
|
||||
|
||||
// Parse the same date with ['validate_format' => TRUE] and make sure we
|
||||
// get the expected exception.
|
||||
$this->setExpectedException(\UnexpectedValueException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\UnexpectedValueException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\UnexpectedValueException::class);
|
||||
}
|
||||
$date = DateTimePlus::createFromFormat('Y-m-d H:i:s', '11-03-31 17:44:00', 'UTC', ['validate_format' => TRUE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests setting the default time for date-only objects.
|
||||
*/
|
||||
public function testDefaultDateTime() {
|
||||
$utc = new \DateTimeZone('UTC');
|
||||
|
||||
$date = DateTimePlus::createFromFormat('Y-m-d H:i:s', '2017-05-23 22:58:00', $utc);
|
||||
$this->assertEquals('22:58:00', $date->format('H:i:s'));
|
||||
$date->setDefaultDateTime();
|
||||
$this->assertEquals('12:00:00', $date->format('H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that object methods are chainable.
|
||||
*
|
||||
@@ -847,7 +880,13 @@ class DateTimePlusTest extends TestCase {
|
||||
* @covers ::__call
|
||||
*/
|
||||
public function testChainableNonCallable() {
|
||||
$this->setExpectedException(\BadMethodCallException::class, 'Call to undefined method Drupal\Component\Datetime\DateTimePlus::nonexistent()');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\BadMethodCallException::class);
|
||||
$this->expectExceptionMessage('Call to undefined method Drupal\Component\Datetime\DateTimePlus::nonexistent()');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\BadMethodCallException::class, 'Call to undefined method Drupal\Component\Datetime\DateTimePlus::nonexistent()');
|
||||
}
|
||||
$date = new DateTimePlus('now', 'Australia/Sydney');
|
||||
$date->setTimezone(new \DateTimeZone('America/New_York'))->nonexistent();
|
||||
}
|
||||
|
||||
@@ -37,8 +37,7 @@ class TimeTest extends TestCase {
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack');
|
||||
|
||||
$this->requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock();
|
||||
$this->time = new Time($this->requestStack);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,12 @@ class ContainerTest extends TestCase {
|
||||
public function testConstruct() {
|
||||
$container_definition = $this->getMockContainerDefinition();
|
||||
$container_definition['machine_format'] = !$this->machineFormat;
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
}
|
||||
$container = new $this->containerClass($container_definition);
|
||||
}
|
||||
|
||||
@@ -93,7 +98,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::getAlternatives
|
||||
*/
|
||||
public function testGetParameterIfNotFound() {
|
||||
$this->setExpectedException(ParameterNotFoundException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(ParameterNotFoundException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(ParameterNotFoundException::class);
|
||||
}
|
||||
$this->container->getParameter('parameter_that_does_not_exist');
|
||||
}
|
||||
|
||||
@@ -103,7 +113,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::getParameter
|
||||
*/
|
||||
public function testGetParameterIfNotFoundBecauseNull() {
|
||||
$this->setExpectedException(ParameterNotFoundException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(ParameterNotFoundException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(ParameterNotFoundException::class);
|
||||
}
|
||||
$this->container->getParameter(NULL);
|
||||
}
|
||||
|
||||
@@ -137,7 +152,12 @@ class ContainerTest extends TestCase {
|
||||
*/
|
||||
public function testSetParameterWithFrozenContainer() {
|
||||
$this->container = new $this->containerClass($this->containerDefinition);
|
||||
$this->setExpectedException(LogicException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(LogicException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(LogicException::class);
|
||||
}
|
||||
$this->container->setParameter('some_config', 'new_value');
|
||||
}
|
||||
|
||||
@@ -242,7 +262,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::createService
|
||||
*/
|
||||
public function testGetForCircularServices() {
|
||||
$this->setExpectedException(ServiceCircularReferenceException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(ServiceCircularReferenceException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(ServiceCircularReferenceException::class);
|
||||
}
|
||||
$this->container->get('circular_dependency');
|
||||
}
|
||||
|
||||
@@ -255,7 +280,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::getServiceAlternatives
|
||||
*/
|
||||
public function testGetForNonExistantService() {
|
||||
$this->setExpectedException(ServiceNotFoundException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(ServiceNotFoundException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(ServiceNotFoundException::class);
|
||||
}
|
||||
$this->container->get('service_not_exists');
|
||||
}
|
||||
|
||||
@@ -304,7 +334,12 @@ class ContainerTest extends TestCase {
|
||||
|
||||
// Reset the service.
|
||||
$this->container->set('service_parameter_not_exists', NULL);
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
}
|
||||
$this->container->get('service_parameter_not_exists');
|
||||
}
|
||||
|
||||
@@ -316,7 +351,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::resolveServicesAndParameters
|
||||
*/
|
||||
public function testGetForNonExistantParameterDependencyWithException() {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
}
|
||||
$this->container->get('service_parameter_not_exists');
|
||||
}
|
||||
|
||||
@@ -341,7 +381,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::getAlternatives
|
||||
*/
|
||||
public function testGetForNonExistantServiceDependencyWithException() {
|
||||
$this->setExpectedException(ServiceNotFoundException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(ServiceNotFoundException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(ServiceNotFoundException::class);
|
||||
}
|
||||
$this->container->get('service_dependency_not_exists');
|
||||
}
|
||||
|
||||
@@ -361,7 +406,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::createService
|
||||
*/
|
||||
public function testGetForNonExistantNULLService() {
|
||||
$this->setExpectedException(ServiceNotFoundException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(ServiceNotFoundException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(ServiceNotFoundException::class);
|
||||
}
|
||||
$this->container->get(NULL);
|
||||
}
|
||||
|
||||
@@ -387,7 +437,12 @@ class ContainerTest extends TestCase {
|
||||
*/
|
||||
public function testGetForNonExistantServiceWithExceptionOnSecondCall() {
|
||||
$this->assertNull($this->container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE), 'Not found service does nto throw exception.');
|
||||
$this->setExpectedException(ServiceNotFoundException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(ServiceNotFoundException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(ServiceNotFoundException::class);
|
||||
}
|
||||
$this->container->get('service_not_exists');
|
||||
}
|
||||
|
||||
@@ -423,7 +478,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::createService
|
||||
*/
|
||||
public function testGetForSyntheticServiceWithException() {
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(RuntimeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
}
|
||||
$this->container->get('synthetic');
|
||||
}
|
||||
|
||||
@@ -462,7 +522,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::createService
|
||||
*/
|
||||
public function testGetForWrongFactory() {
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(RuntimeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
}
|
||||
$this->container->get('wrong_factory');
|
||||
}
|
||||
|
||||
@@ -500,7 +565,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::createService
|
||||
*/
|
||||
public function testGetForConfiguratorWithException() {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
}
|
||||
$this->container->get('configurable_service_exception');
|
||||
}
|
||||
|
||||
@@ -598,7 +668,12 @@ class ContainerTest extends TestCase {
|
||||
* @covers ::resolveServicesAndParameters
|
||||
*/
|
||||
public function testResolveServicesAndParametersForInvalidArgument() {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
}
|
||||
$this->container->get('invalid_argument_service');
|
||||
}
|
||||
|
||||
@@ -612,7 +687,12 @@ class ContainerTest extends TestCase {
|
||||
public function testResolveServicesAndParametersForInvalidArguments() {
|
||||
// In case the machine-optimized format is not used, we need to simulate the
|
||||
// test failure.
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
}
|
||||
if (!$this->machineFormat) {
|
||||
throw new InvalidArgumentException('Simulating the test failure.');
|
||||
}
|
||||
|
||||
+26
-6
@@ -68,7 +68,7 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper {
|
||||
$this->containerBuilder->getAliases()->willReturn([]);
|
||||
$this->containerBuilder->getParameterBag()->willReturn(new ParameterBag());
|
||||
$this->containerBuilder->getDefinitions()->willReturn(NULL);
|
||||
$this->containerBuilder->isFrozen()->willReturn(TRUE);
|
||||
$this->containerBuilder->isCompiled()->willReturn(TRUE);
|
||||
|
||||
$definition = [];
|
||||
$definition['aliases'] = [];
|
||||
@@ -147,7 +147,7 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper {
|
||||
|
||||
$parameter_bag = new ParameterBag($parameters);
|
||||
$this->containerBuilder->getParameterBag()->willReturn($parameter_bag);
|
||||
$this->containerBuilder->isFrozen()->willReturn($is_frozen);
|
||||
$this->containerBuilder->isCompiled()->willReturn($is_frozen);
|
||||
|
||||
if (isset($parameters['reference'])) {
|
||||
$definition = new Definition('\stdClass');
|
||||
@@ -545,7 +545,12 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper {
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidArgumentException::class);
|
||||
}
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
@@ -562,7 +567,12 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper {
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(RuntimeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
}
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
@@ -579,7 +589,12 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper {
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(RuntimeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
}
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
@@ -596,7 +611,12 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper {
|
||||
$services['bar'] = $bar_definition;
|
||||
|
||||
$this->containerBuilder->getDefinitions()->willReturn($services);
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(RuntimeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
}
|
||||
$this->dumper->getArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,4 +86,21 @@ class DiffEngineTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that two files can be successfully diffed.
|
||||
*
|
||||
* @covers ::diff
|
||||
*/
|
||||
public function testDiffInfiniteLoop() {
|
||||
$from = explode("\n", file_get_contents(__DIR__ . '/fixtures/file1.txt'));
|
||||
$to = explode("\n", file_get_contents(__DIR__ . '/fixtures/file2.txt'));
|
||||
$diff_engine = new DiffEngine();
|
||||
$diff = $diff_engine->diff($from, $to);
|
||||
$this->assertCount(4, $diff);
|
||||
$this->assertEquals($diff[0], new DiffOpDelete([' - image.style.max_650x650']));
|
||||
$this->assertEquals($diff[1], new DiffOpCopy([' - image.style.max_325x325']));
|
||||
$this->assertEquals($diff[2], new DiffOpAdd([' - image.style.max_650x650', '_core:', ' default_config_hash: 3mjM9p-kQ8syzH7N8T0L9OnCJDSPvHAZoi3q6jcXJKM']));
|
||||
$this->assertEquals($diff[3], new DiffOpCopy(['fallback_image_style: max_325x325', '']));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Drupal\Tests\Component\Diff\Engine;
|
||||
|
||||
use Drupal\Component\Diff\Engine\DiffOp;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Framework\Error\Error;
|
||||
|
||||
/**
|
||||
* Test DiffOp base class.
|
||||
@@ -24,7 +25,12 @@ class DiffOpTest extends TestCase {
|
||||
* @covers ::reverse
|
||||
*/
|
||||
public function testReverse() {
|
||||
$this->setExpectedException(\PHPUnit_Framework_Error::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(Error::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\PHPUnit_Framework_Error::class);
|
||||
}
|
||||
$op = new DiffOp();
|
||||
$result = $op->reverse();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
- image.style.max_650x650
|
||||
- image.style.max_325x325
|
||||
fallback_image_style: max_325x325
|
||||
@@ -0,0 +1,5 @@
|
||||
- image.style.max_325x325
|
||||
- image.style.max_650x650
|
||||
_core:
|
||||
default_config_hash: 3mjM9p-kQ8syzH7N8T0L9OnCJDSPvHAZoi3q6jcXJKM
|
||||
fallback_image_style: max_325x325
|
||||
@@ -124,7 +124,13 @@ class YamlDirectoryDiscoveryTest extends TestCase {
|
||||
* @covers ::getIdentifier
|
||||
*/
|
||||
public function testDiscoveryNoIdException() {
|
||||
$this->setExpectedException(DiscoveryException::class, 'The vfs://modules/test_1/item_1.test.yml contains no data in the identifier key \'id\'');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(DiscoveryException::class);
|
||||
$this->expectExceptionMessage('The vfs://modules/test_1/item_1.test.yml contains no data in the identifier key \'id\'');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(DiscoveryException::class, 'The vfs://modules/test_1/item_1.test.yml contains no data in the identifier key \'id\'');
|
||||
}
|
||||
vfsStream::setup('modules', NULL, [
|
||||
'test_1' => [
|
||||
'item_1.test.yml' => "",
|
||||
@@ -144,7 +150,13 @@ class YamlDirectoryDiscoveryTest extends TestCase {
|
||||
* @covers ::findAll
|
||||
*/
|
||||
public function testDiscoveryInvalidYamlException() {
|
||||
$this->setExpectedException(DiscoveryException::class, 'The vfs://modules/test_1/item_1.test.yml contains invalid YAML');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(DiscoveryException::class);
|
||||
$this->expectExceptionMessage('The vfs://modules/test_1/item_1.test.yml contains invalid YAML');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(DiscoveryException::class, 'The vfs://modules/test_1/item_1.test.yml contains invalid YAML');
|
||||
}
|
||||
vfsStream::setup('modules', NULL, [
|
||||
'test_1' => [
|
||||
'item_1.test.yml' => "id: invalid\nfoo : [bar}",
|
||||
|
||||
@@ -32,6 +32,34 @@ class DrupalComponentTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests LICENSE.txt is present and has the correct content.
|
||||
*
|
||||
* @param $component_path
|
||||
* The path to the component.
|
||||
* @dataProvider \Drupal\Tests\Component\DrupalComponentTest::getComponents
|
||||
*/
|
||||
public function testComponentLicence($component_path) {
|
||||
$this->assertFileExists($component_path . DIRECTORY_SEPARATOR . 'LICENSE.txt');
|
||||
$this->assertSame('e84dac1d9fbb5a4a69e38654ce644cea769aa76b', hash_file('sha1', $component_path . DIRECTORY_SEPARATOR . 'LICENSE.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getComponents() {
|
||||
$root_component_path = dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))) . '/lib/Drupal/Component';
|
||||
$component_paths = [];
|
||||
foreach (new \DirectoryIterator($root_component_path) as $file) {
|
||||
if ($file->isDir() && !$file->isDot()) {
|
||||
$component_paths[$file->getBasename()] = [$file->getPathname()];
|
||||
}
|
||||
}
|
||||
return $component_paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches a directory recursively for PHP classes.
|
||||
*
|
||||
|
||||
+57
-2
@@ -38,7 +38,7 @@ class ContainerAwareEventDispatcherTest extends SymfonyContainerAwareEventDispat
|
||||
// When passing in callables exclusively as listeners into the event
|
||||
// dispatcher constructor, the event dispatcher must not attempt to
|
||||
// resolve any services.
|
||||
$container = $this->getMock(ContainerInterface::class);
|
||||
$container = $this->getMockBuilder(ContainerInterface::class)->getMock();
|
||||
$container->expects($this->never())->method($this->anything());
|
||||
|
||||
$firstListener = new CallableClass();
|
||||
@@ -73,7 +73,7 @@ class ContainerAwareEventDispatcherTest extends SymfonyContainerAwareEventDispat
|
||||
// When passing in callables exclusively as listeners into the event
|
||||
// dispatcher constructor, the event dispatcher must not attempt to
|
||||
// resolve any services.
|
||||
$container = $this->getMock(ContainerInterface::class);
|
||||
$container = $this->getMockBuilder(ContainerInterface::class)->getMock();
|
||||
$container->expects($this->never())->method($this->anything());
|
||||
|
||||
$firstListener = new CallableClass();
|
||||
@@ -193,4 +193,59 @@ class ContainerAwareEventDispatcherTest extends SymfonyContainerAwareEventDispat
|
||||
$this->assertSame(5, $actualPriority);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.
|
||||
* @group legacy
|
||||
*/
|
||||
public function testAddAListenerService() {
|
||||
parent::testAddAListenerService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.
|
||||
* @group legacy
|
||||
*/
|
||||
public function testPreventDuplicateListenerService() {
|
||||
parent::testPreventDuplicateListenerService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.
|
||||
* @group legacy
|
||||
*/
|
||||
public function testAddASubscriberService() {
|
||||
parent::testAddASubscriberService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.
|
||||
* @group legacy
|
||||
*/
|
||||
public function testHasListenersOnLazyLoad() {
|
||||
parent::testHasListenersOnLazyLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.
|
||||
* @group legacy
|
||||
*/
|
||||
public function testGetListenersOnLazyLoad() {
|
||||
parent::testGetListenersOnLazyLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.
|
||||
* @group legacy
|
||||
*/
|
||||
public function testRemoveAfterDispatch() {
|
||||
parent::testRemoveAfterDispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation The Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.
|
||||
* @group legacy
|
||||
*/
|
||||
public function testRemoveBeforeDispatch() {
|
||||
parent::testRemoveBeforeDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,13 @@ class FileCacheFactoryTest extends TestCase {
|
||||
*/
|
||||
public function testGetNoPrefix() {
|
||||
FileCacheFactory::setPrefix(NULL);
|
||||
$this->setExpectedException(\InvalidArgumentException::class, 'Required prefix configuration is missing');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Required prefix configuration is missing');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, 'Required prefix configuration is missing');
|
||||
}
|
||||
FileCacheFactory::get('test_foo_settings', []);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Gettext;
|
||||
|
||||
use Drupal\Component\Gettext\PoItem;
|
||||
use Drupal\Component\Gettext\PoStreamWriter;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use org\bovigo\vfs\vfsStreamFile;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\Gettext\PoStreamWriter
|
||||
* @group Gettext
|
||||
*/
|
||||
class PoStreamWriterTest extends TestCase {
|
||||
|
||||
/**
|
||||
* The PO writer object under test.
|
||||
*
|
||||
* @var \Drupal\Component\Gettext\PoStreamWriter
|
||||
*/
|
||||
protected $poWriter;
|
||||
|
||||
/**
|
||||
* The mock po file.
|
||||
*
|
||||
* @var \org\bovigo\vfs\vfsStreamFile
|
||||
*/
|
||||
protected $poFile;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->poWriter = new PoStreamWriter();
|
||||
|
||||
$root = vfsStream::setup();
|
||||
$this->poFile = new vfsStreamFile('powriter.po');
|
||||
$root->addChild($this->poFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getURI
|
||||
*/
|
||||
public function testGetUriException() {
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\Exception::class, 'No URI set.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\Exception::class, 'No URI set.');
|
||||
}
|
||||
|
||||
$this->poWriter->getURI();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::writeItem
|
||||
* @dataProvider providerWriteData
|
||||
*/
|
||||
public function testWriteItem($poContent, $expected, $long) {
|
||||
if ($long) {
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\Exception::class, 'Unable to write data:');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\Exception::class, 'Unable to write data:');
|
||||
}
|
||||
}
|
||||
|
||||
// Limit the file system quota to make the write fail on long strings.
|
||||
vfsStream::setQuota(10);
|
||||
|
||||
$this->poWriter->setURI($this->poFile->url());
|
||||
$this->poWriter->open();
|
||||
|
||||
$poItem = $this->prophesize(PoItem::class);
|
||||
$poItem->__toString()->willReturn($poContent);
|
||||
|
||||
$this->poWriter->writeItem($poItem->reveal());
|
||||
$this->poWriter->close();
|
||||
$this->assertEquals(file_get_contents($this->poFile->url()), $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* - Content to write.
|
||||
* - Written content.
|
||||
* - Content longer than 10 bytes.
|
||||
*/
|
||||
public function providerWriteData() {
|
||||
return [
|
||||
['', '', FALSE],
|
||||
["\r\n", "\r\n", FALSE],
|
||||
['write this if you can', 'write this', TRUE],
|
||||
['éáíó>&', 'éáíó>&', FALSE],
|
||||
['éáíó>&<', 'éáíó>&', TRUE],
|
||||
['中文 890', '中文 890', FALSE],
|
||||
['中文 89012', '中文 890', TRUE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::close
|
||||
*/
|
||||
public function testCloseException() {
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\Exception::class, 'Cannot close stream that is not open.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\Exception::class, 'Cannot close stream that is not open.');
|
||||
}
|
||||
|
||||
$this->poWriter->close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,14 +63,14 @@ class FileStorageReadOnlyTest extends PhpStorageTestBase {
|
||||
// Write out a PHP file and ensure it's successfully loaded.
|
||||
$code = "<?php\n\$GLOBALS[$random] = TRUE;";
|
||||
$success = $php->save($name, $code);
|
||||
$this->assertSame($success, TRUE);
|
||||
$this->assertSame(TRUE, $success);
|
||||
$php_read = new FileReadOnlyStorage($this->readonlyStorage);
|
||||
$php_read->load($name);
|
||||
$this->assertTrue($GLOBALS[$random]);
|
||||
|
||||
// If the file was successfully loaded, it must also exist, but ensure the
|
||||
// exists() method returns that correctly.
|
||||
$this->assertSame($php_read->exists($name), TRUE);
|
||||
$this->assertSame(TRUE, $php_read->exists($name));
|
||||
// Saving and deleting should always fail.
|
||||
$this->assertFalse($php_read->save($name, $code));
|
||||
$this->assertFalse($php_read->delete($name));
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Drupal\Tests\Component\PhpStorage;
|
||||
use Drupal\Component\PhpStorage\FileStorage;
|
||||
use Drupal\Component\Utility\Random;
|
||||
use org\bovigo\vfs\vfsStreamDirectory;
|
||||
use PHPUnit_Framework_Error_Warning;
|
||||
use PHPUnit\Framework\Error\Warning;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Component\PhpStorage\FileStorage
|
||||
@@ -99,7 +99,13 @@ class FileStorageTest extends PhpStorageTestBase {
|
||||
'bin' => 'test',
|
||||
]);
|
||||
$code = "<?php\n echo 'here';";
|
||||
$this->setExpectedException(PHPUnit_Framework_Error_Warning::class, 'mkdir(): Permission Denied');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(Warning::class);
|
||||
$this->expectExceptionMessage('mkdir(): Permission Denied');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\PHPUnit_Framework_Error_Warning::class, 'mkdir(): Permission Denied');
|
||||
}
|
||||
$storage->save('subdirectory/foo.php', $code);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,8 +89,8 @@ abstract class MTimeProtectedFileStorageBase extends PhpStorageTestBase {
|
||||
// minimal permissions. fileperms() can return high bits unrelated to
|
||||
// permissions, so mask with 0777.
|
||||
$this->assertTrue(file_exists($expected_filename));
|
||||
$this->assertSame(fileperms($expected_filename) & 0777, 0444);
|
||||
$this->assertSame(fileperms($expected_directory) & 0777, 0777);
|
||||
$this->assertSame(0444, fileperms($expected_filename) & 0777);
|
||||
$this->assertSame(0777, fileperms($expected_directory) & 0777);
|
||||
|
||||
// Ensure the root directory for the bin has a .htaccess file denying web
|
||||
// access.
|
||||
@@ -121,9 +121,9 @@ abstract class MTimeProtectedFileStorageBase extends PhpStorageTestBase {
|
||||
chmod($expected_filename, 0400);
|
||||
chmod($expected_directory, 0100);
|
||||
$this->assertSame(file_get_contents($expected_filename), $untrusted_code);
|
||||
$this->assertSame($php->exists($name), $this->expected[$i]);
|
||||
$this->assertSame($php->load($name), $this->expected[$i]);
|
||||
$this->assertSame($GLOBALS['hacked'], $this->expected[$i]);
|
||||
$this->assertSame($this->expected[$i], $php->exists($name));
|
||||
$this->assertSame($this->expected[$i], $php->load($name));
|
||||
$this->assertSame($this->expected[$i], $GLOBALS['hacked']);
|
||||
}
|
||||
unset($GLOBALS['hacked']);
|
||||
}
|
||||
|
||||
@@ -71,10 +71,16 @@ class ContextTest extends TestCase {
|
||||
|
||||
// Set expectation for exception.
|
||||
if ($is_required) {
|
||||
$this->setExpectedException(
|
||||
'Drupal\Component\Plugin\Exception\ContextException',
|
||||
sprintf("The %s context is required and not present.", $data_type)
|
||||
);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException('Drupal\Component\Plugin\Exception\ContextException');
|
||||
$this->expectExceptionMessage(sprintf("The %s context is required and not present.", $data_type));
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(
|
||||
'Drupal\Component\Plugin\Exception\ContextException',
|
||||
sprintf("The %s context is required and not present.", $data_type)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Exercise getContextValue().
|
||||
|
||||
@@ -5,9 +5,9 @@ namespace Drupal\Tests\Component\Plugin;
|
||||
use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
|
||||
use Drupal\Component\Plugin\Exception\PluginException;
|
||||
use Drupal\Component\Plugin\Factory\DefaultFactory;
|
||||
use Drupal\plugin_test\Plugin\plugin_test\fruit\Cherry;
|
||||
use Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface;
|
||||
use Drupal\plugin_test\Plugin\plugin_test\fruit\Kale;
|
||||
use Drupal\Tests\Component\Plugin\Fixtures\vegetable\Broccoli;
|
||||
use Drupal\Tests\Component\Plugin\Fixtures\vegetable\Corn;
|
||||
use Drupal\Tests\Component\Plugin\Fixtures\vegetable\VegetableInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@@ -22,8 +22,8 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithValidArrayPluginDefinition() {
|
||||
$plugin_class = Cherry::class;
|
||||
$class = DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class]);
|
||||
$plugin_class = Corn::class;
|
||||
$class = DefaultFactory::getPluginClass('corn', ['class' => $plugin_class]);
|
||||
|
||||
$this->assertEquals($plugin_class, $class);
|
||||
}
|
||||
@@ -34,12 +34,12 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithValidObjectPluginDefinition() {
|
||||
$plugin_class = Cherry::class;
|
||||
$plugin_definition = $this->getMock(PluginDefinitionInterface::class);
|
||||
$plugin_class = Corn::class;
|
||||
$plugin_definition = $this->getMockBuilder(PluginDefinitionInterface::class)->getMock();
|
||||
$plugin_definition->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->willReturn($plugin_class);
|
||||
$class = DefaultFactory::getPluginClass('cherry', $plugin_definition);
|
||||
$class = DefaultFactory::getPluginClass('corn', $plugin_definition);
|
||||
|
||||
$this->assertEquals($plugin_class, $class);
|
||||
}
|
||||
@@ -50,8 +50,14 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithMissingClassWithArrayPluginDefinition() {
|
||||
$this->setExpectedException(PluginException::class, 'The plugin (cherry) did not specify an instance class.');
|
||||
DefaultFactory::getPluginClass('cherry', []);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(PluginException::class);
|
||||
$this->expectExceptionMessage('The plugin (corn) did not specify an instance class.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(PluginException::class, 'The plugin (corn) did not specify an instance class.');
|
||||
}
|
||||
DefaultFactory::getPluginClass('corn', []);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,9 +66,15 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithMissingClassWithObjectPluginDefinition() {
|
||||
$plugin_definition = $this->getMock(PluginDefinitionInterface::class);
|
||||
$this->setExpectedException(PluginException::class, 'The plugin (cherry) did not specify an instance class.');
|
||||
DefaultFactory::getPluginClass('cherry', $plugin_definition);
|
||||
$plugin_definition = $this->getMockBuilder(PluginDefinitionInterface::class)->getMock();
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(PluginException::class);
|
||||
$this->expectExceptionMessage('The plugin (corn) did not specify an instance class.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(PluginException::class, 'The plugin (corn) did not specify an instance class.');
|
||||
}
|
||||
DefaultFactory::getPluginClass('corn', $plugin_definition);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,8 +83,14 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithNotExistingClassWithArrayPluginDefinition() {
|
||||
$this->setExpectedException(PluginException::class, 'Plugin (kiwifruit) instance class "\Drupal\plugin_test\Plugin\plugin_test\fruit\Kiwifruit" does not exist.');
|
||||
DefaultFactory::getPluginClass('kiwifruit', ['class' => '\Drupal\plugin_test\Plugin\plugin_test\fruit\Kiwifruit']);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(PluginException::class);
|
||||
$this->expectExceptionMessage('Plugin (carrot) instance class "Drupal\Tests\Component\Plugin\Fixtures\vegetable\Carrot" does not exist.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(PluginException::class, 'Plugin (carrot) instance class "Drupal\Tests\Component\Plugin\Fixtures\vegetable\Carrot" does not exist.');
|
||||
}
|
||||
DefaultFactory::getPluginClass('carrot', ['class' => 'Drupal\Tests\Component\Plugin\Fixtures\vegetable\Carrot']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,13 +99,18 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithNotExistingClassWithObjectPluginDefinition() {
|
||||
$plugin_class = '\Drupal\plugin_test\Plugin\plugin_test\fruit\Kiwifruit';
|
||||
$plugin_definition = $this->getMock(PluginDefinitionInterface::class);
|
||||
$plugin_class = 'Drupal\Tests\Component\Plugin\Fixtures\vegetable\Carrot';
|
||||
$plugin_definition = $this->getMockBuilder(PluginDefinitionInterface::class)->getMock();
|
||||
$plugin_definition->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->willReturn($plugin_class);
|
||||
$this->setExpectedException(PluginException::class);
|
||||
DefaultFactory::getPluginClass('kiwifruit', $plugin_definition);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(PluginException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(PluginException::class);
|
||||
}
|
||||
DefaultFactory::getPluginClass('carrot', $plugin_definition);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,8 +119,8 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithInterfaceWithArrayPluginDefinition() {
|
||||
$plugin_class = Cherry::class;
|
||||
$class = DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class], FruitInterface::class);
|
||||
$plugin_class = Corn::class;
|
||||
$class = DefaultFactory::getPluginClass('corn', ['class' => $plugin_class], VegetableInterface::class);
|
||||
|
||||
$this->assertEquals($plugin_class, $class);
|
||||
}
|
||||
@@ -108,12 +131,12 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithInterfaceWithObjectPluginDefinition() {
|
||||
$plugin_class = Cherry::class;
|
||||
$plugin_definition = $this->getMock(PluginDefinitionInterface::class);
|
||||
$plugin_class = Corn::class;
|
||||
$plugin_definition = $this->getMockBuilder(PluginDefinitionInterface::class)->getMock();
|
||||
$plugin_definition->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->willReturn($plugin_class);
|
||||
$class = DefaultFactory::getPluginClass('cherry', $plugin_definition, FruitInterface::class);
|
||||
$class = DefaultFactory::getPluginClass('corn', $plugin_definition, VegetableInterface::class);
|
||||
|
||||
$this->assertEquals($plugin_class, $class);
|
||||
}
|
||||
@@ -124,9 +147,14 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithInterfaceAndInvalidClassWithArrayPluginDefinition() {
|
||||
$plugin_class = Kale::class;
|
||||
$this->setExpectedException(PluginException::class, 'Plugin "cherry" (Drupal\plugin_test\Plugin\plugin_test\fruit\Kale) must implement interface Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface.');
|
||||
DefaultFactory::getPluginClass('cherry', ['class' => $plugin_class, 'provider' => 'core'], FruitInterface::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(PluginException::class);
|
||||
$this->expectExceptionMessage('Plugin "corn" (Drupal\Tests\Component\Plugin\Fixtures\vegetable\Broccoli) must implement interface Drupal\Tests\Component\Plugin\Fixtures\vegetable\VegetableInterface.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(PluginException::class, 'Plugin "corn" (Drupal\Tests\Component\Plugin\Fixtures\vegetable\Broccoli) must implement interface Drupal\Tests\Component\Plugin\Fixtures\vegetable\VegetableInterface.');
|
||||
}
|
||||
DefaultFactory::getPluginClass('corn', ['class' => Broccoli::class], VegetableInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,13 +163,18 @@ class DefaultFactoryTest extends TestCase {
|
||||
* @covers ::getPluginClass
|
||||
*/
|
||||
public function testGetPluginClassWithInterfaceAndInvalidClassWithObjectPluginDefinition() {
|
||||
$plugin_class = Kale::class;
|
||||
$plugin_definition = $this->getMock(PluginDefinitionInterface::class);
|
||||
$plugin_class = Broccoli::class;
|
||||
$plugin_definition = $this->getMockBuilder(PluginDefinitionInterface::class)->getMock();
|
||||
$plugin_definition->expects($this->atLeastOnce())
|
||||
->method('getClass')
|
||||
->willReturn($plugin_class);
|
||||
$this->setExpectedException(PluginException::class);
|
||||
DefaultFactory::getPluginClass('cherry', $plugin_definition, FruitInterface::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(PluginException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(PluginException::class);
|
||||
}
|
||||
DefaultFactory::getPluginClass('corn', $plugin_definition, VegetableInterface::class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -69,7 +69,12 @@ class DiscoveryTraitTest extends TestCase {
|
||||
$method_ref = new \ReflectionMethod($trait, 'doGetDefinition');
|
||||
$method_ref->setAccessible(TRUE);
|
||||
// Call doGetDefinition, with $exception_on_invalid always TRUE.
|
||||
$this->setExpectedException(PluginNotFoundException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(PluginNotFoundException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(PluginNotFoundException::class);
|
||||
}
|
||||
$method_ref->invoke($trait, $definitions, $plugin_id, TRUE);
|
||||
}
|
||||
|
||||
@@ -106,7 +111,12 @@ class DiscoveryTraitTest extends TestCase {
|
||||
->method('getDefinitions')
|
||||
->willReturn($definitions);
|
||||
// Call getDefinition(), with $exception_on_invalid always TRUE.
|
||||
$this->setExpectedException(PluginNotFoundException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(PluginNotFoundException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(PluginNotFoundException::class);
|
||||
}
|
||||
$trait->getDefinition($plugin_id, TRUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,12 @@ class StaticDiscoveryDecoratorTest extends TestCase {
|
||||
$ref_decorated->setValue($mock_decorator, $mock_decorated);
|
||||
|
||||
if ($exception_on_invalid) {
|
||||
$this->setExpectedException('Drupal\Component\Plugin\Exception\PluginNotFoundException');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException('Drupal\Component\Plugin\Exception\PluginNotFoundException');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException('Drupal\Component\Plugin\Exception\PluginNotFoundException');
|
||||
}
|
||||
}
|
||||
|
||||
// Exercise getDefinition(). It calls parent::getDefinition().
|
||||
|
||||
@@ -123,7 +123,12 @@ class ReflectionFactoryTest extends TestCase {
|
||||
// us to use one data set for this test method as well as
|
||||
// testCreateInstance().
|
||||
if ($plugin_id == 'arguments_no_constructor') {
|
||||
$this->setExpectedException('\ReflectionException');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException('\ReflectionException');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException('\ReflectionException');
|
||||
}
|
||||
}
|
||||
|
||||
// Finally invoke getInstanceArguments() on our mocked factory.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Plugin\Fixtures\vegetable;
|
||||
|
||||
/**
|
||||
* @Plugin(
|
||||
* id = "broccoli",
|
||||
* label = "Broccoli",
|
||||
* color = "green"
|
||||
* )
|
||||
*/
|
||||
class Broccoli {}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Plugin\Fixtures\vegetable;
|
||||
|
||||
/**
|
||||
* @Plugin(
|
||||
* id = "corn",
|
||||
* label = "Corn",
|
||||
* color = "yellow"
|
||||
* )
|
||||
*/
|
||||
class Corn implements VegetableInterface {}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\Component\Plugin\Fixtures\vegetable;
|
||||
|
||||
/**
|
||||
* Provides an interface for test plugins.
|
||||
*/
|
||||
interface VegetableInterface {}
|
||||
@@ -58,7 +58,7 @@ class JsonTest extends TestCase {
|
||||
*/
|
||||
public function testEncodingAscii() {
|
||||
// Verify there aren't character encoding problems with the source string.
|
||||
$this->assertSame(strlen($this->string), 127, 'A string with the full ASCII table has the correct length.');
|
||||
$this->assertSame(127, strlen($this->string), 'A string with the full ASCII table has the correct length.');
|
||||
foreach ($this->htmlUnsafe as $char) {
|
||||
$this->assertTrue(strpos($this->string, $char) > 0, sprintf('A string with the full ASCII table includes %s.', $char));
|
||||
}
|
||||
|
||||
@@ -87,7 +87,12 @@ foo:
|
||||
* @covers ::errorHandler
|
||||
*/
|
||||
public function testError() {
|
||||
$this->setExpectedException(InvalidDataTypeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidDataTypeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidDataTypeException::class);
|
||||
}
|
||||
YamlPecl::decode('foo: [ads');
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,12 @@ class YamlSymfonyTest extends YamlTestBase {
|
||||
* @covers ::decode
|
||||
*/
|
||||
public function testError() {
|
||||
$this->setExpectedException(InvalidDataTypeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidDataTypeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidDataTypeException::class);
|
||||
}
|
||||
YamlSymfony::decode('foo: [ads');
|
||||
}
|
||||
|
||||
@@ -69,7 +74,13 @@ class YamlSymfonyTest extends YamlTestBase {
|
||||
* @covers ::encode
|
||||
*/
|
||||
public function testObjectSupportDisabled() {
|
||||
$this->setExpectedException(InvalidDataTypeException::class, 'Object support when dumping a YAML file has been disabled.');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(InvalidDataTypeException::class);
|
||||
$this->expectExceptionMessage('Object support when dumping a YAML file has been disabled.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(InvalidDataTypeException::class, 'Object support when dumping a YAML file has been disabled.');
|
||||
}
|
||||
$object = new \stdClass();
|
||||
$object->foo = 'bar';
|
||||
YamlSymfony::encode([$object]);
|
||||
|
||||
@@ -77,20 +77,46 @@ class YamlTest extends TestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that decoding php objects is similar for PECL and Symfony.
|
||||
* Ensures that decoding php objects does not work in PECL.
|
||||
*
|
||||
* @requires extension yaml
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Serialization\YamlTest::testObjectSupportDisabledSymfony()
|
||||
*/
|
||||
public function testObjectSupportDisabled() {
|
||||
public function testObjectSupportDisabledPecl() {
|
||||
$object = new \stdClass();
|
||||
$object->foo = 'bar';
|
||||
// In core all Yaml encoding is done via Symfony and it does not support
|
||||
// objects so in order to encode an object we hace to use the PECL
|
||||
// objects so in order to encode an object we have to use the PECL
|
||||
// extension.
|
||||
// @see \Drupal\Component\Serialization\Yaml::encode()
|
||||
$yaml = YamlPecl::encode([$object]);
|
||||
$this->assertEquals(['O:8:"stdClass":1:{s:3:"foo";s:3:"bar";}'], YamlPecl::decode($yaml));
|
||||
$this->assertEquals(['!php/object "O:8:\"stdClass\":1:{s:3:\"foo\";s:3:\"bar\";}"'], YamlSymfony::decode($yaml));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that decoding php objects does not work in Symfony.
|
||||
*
|
||||
* @requires extension yaml
|
||||
*
|
||||
* @see \Drupal\Tests\Component\Serialization\YamlTest::testObjectSupportDisabledPecl()
|
||||
*/
|
||||
public function testObjectSupportDisabledSymfony() {
|
||||
if (method_exists($this, 'setExpectedExceptionRegExp')) {
|
||||
$this->setExpectedExceptionRegExp(InvalidDataTypeException::class, '/^Object support when parsing a YAML file has been disabled/');
|
||||
}
|
||||
else {
|
||||
$this->expectException(InvalidDataTypeException::class);
|
||||
$this->expectExceptionMessageRegExp('/^Object support when parsing a YAML file has been disabled/');
|
||||
}
|
||||
$object = new \stdClass();
|
||||
$object->foo = 'bar';
|
||||
// In core all Yaml encoding is done via Symfony and it does not support
|
||||
// objects so in order to encode an object we have to use the PECL
|
||||
// extension.
|
||||
// @see \Drupal\Component\Serialization\Yaml::encode()
|
||||
$yaml = YamlPecl::encode([$object]);
|
||||
YamlSymfony::decode($yaml);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,8 +127,8 @@ class YamlTest extends TestCase {
|
||||
$dirs = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(__DIR__ . '/../../../../../', \RecursiveDirectoryIterator::FOLLOW_SYMLINKS));
|
||||
foreach ($dirs as $dir) {
|
||||
$pathname = $dir->getPathname();
|
||||
// Exclude vendor.
|
||||
if ($dir->getExtension() == 'yml' && strpos($pathname, '/../../../../../vendor') === FALSE) {
|
||||
// Exclude core/node_modules.
|
||||
if ($dir->getExtension() == 'yml' && strpos($pathname, '/../../../../../node_modules') === FALSE) {
|
||||
if (strpos($dir->getRealPath(), 'invalid_file') !== FALSE) {
|
||||
// There are some intentionally invalid files provided for testing
|
||||
// library API behaviours, ignore them.
|
||||
|
||||
@@ -182,7 +182,7 @@ class PhpTransliterationTest extends TestCase {
|
||||
]);
|
||||
$transliteration = new PhpTransliteration(vfsStream::url('transliteration/dir'));
|
||||
$transliterated = $transliteration->transliterate(chr(0xC2) . chr(0x82), '../index');
|
||||
$this->assertSame($transliterated, 'safe');
|
||||
$this->assertSame('safe', $transliterated);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,9 +96,9 @@ class ArgumentsResolverTest extends TestCase {
|
||||
* Tests getArgument() with a Route, Request, and Account object.
|
||||
*/
|
||||
public function testGetArgumentOrder() {
|
||||
$a1 = $this->getMock('\Drupal\Tests\Component\Utility\Test1Interface');
|
||||
$a2 = $this->getMock('\Drupal\Tests\Component\Utility\TestClass');
|
||||
$a3 = $this->getMock('\Drupal\Tests\Component\Utility\Test2Interface');
|
||||
$a1 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test1Interface')->getMock();
|
||||
$a2 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\TestClass')->getMock();
|
||||
$a3 = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test2Interface')->getMock();
|
||||
|
||||
$objects = [
|
||||
't1' => $a1,
|
||||
@@ -123,12 +123,18 @@ class ArgumentsResolverTest extends TestCase {
|
||||
* Without the typehint, the wildcard object will not be passed to the callable.
|
||||
*/
|
||||
public function testGetWildcardArgumentNoTypehint() {
|
||||
$a = $this->getMock('\Drupal\Tests\Component\Utility\Test1Interface');
|
||||
$a = $this->getMockBuilder('\Drupal\Tests\Component\Utility\Test1Interface')->getMock();
|
||||
$wildcards = [$a];
|
||||
$resolver = new ArgumentsResolver([], [], $wildcards);
|
||||
|
||||
$callable = function ($route) {};
|
||||
$this->setExpectedException(\RuntimeException::class, 'requires a value for the "$route" argument.');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('requires a value for the "$route" argument.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\RuntimeException::class, 'requires a value for the "$route" argument.');
|
||||
}
|
||||
$resolver->getArguments($callable);
|
||||
}
|
||||
|
||||
@@ -156,7 +162,13 @@ class ArgumentsResolverTest extends TestCase {
|
||||
$resolver = new ArgumentsResolver($scalars, $objects, []);
|
||||
|
||||
$callable = function (\stdClass $foo) {};
|
||||
$this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('requires a value for the "$foo" argument.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.');
|
||||
}
|
||||
$resolver->getArguments($callable);
|
||||
}
|
||||
|
||||
@@ -167,7 +179,13 @@ class ArgumentsResolverTest extends TestCase {
|
||||
*/
|
||||
public function testHandleUnresolvedArgument($callable) {
|
||||
$resolver = new ArgumentsResolver([], [], []);
|
||||
$this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('requires a value for the "$foo" argument.');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\RuntimeException::class, 'requires a value for the "$foo" argument.');
|
||||
}
|
||||
$resolver->getArguments($callable);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,12 @@ class ColorTest extends TestCase {
|
||||
*/
|
||||
public function testHexToRgb($value, $expected, $invalid = FALSE) {
|
||||
if ($invalid) {
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException('InvalidArgumentException');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
}
|
||||
}
|
||||
$this->assertSame($expected, Color::hexToRgb($value));
|
||||
}
|
||||
@@ -118,4 +123,42 @@ class ColorTest extends TestCase {
|
||||
return $tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testNormalizeHexLength().
|
||||
*
|
||||
* @see testNormalizeHexLength()
|
||||
*
|
||||
* @return array
|
||||
* An array of arrays containing:
|
||||
* - The hex color value.
|
||||
* - The 6 character length hex color value.
|
||||
*/
|
||||
public function providerTestNormalizeHexLength() {
|
||||
$data = [
|
||||
['#000', '#000000'],
|
||||
['#FFF', '#FFFFFF'],
|
||||
['#abc', '#aabbcc'],
|
||||
['cba', '#ccbbaa'],
|
||||
['#000000', '#000000'],
|
||||
['ffffff', '#ffffff'],
|
||||
['#010203', '#010203'],
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Color::normalizeHexLength().
|
||||
*
|
||||
* @param string $value
|
||||
* The input hex color value.
|
||||
* @param string $expected
|
||||
* The expected normalized hex color value.
|
||||
*
|
||||
* @dataProvider providerTestNormalizeHexLength
|
||||
*/
|
||||
public function testNormalizeHexLength($value, $expected) {
|
||||
$this->assertSame($expected, Color::normalizeHexLength($value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -77,7 +77,12 @@ class CryptTest extends TestCase {
|
||||
* Key to use in hashing process.
|
||||
*/
|
||||
public function testHmacBase64Invalid($data, $key) {
|
||||
$this->setExpectedException(\InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException('InvalidArgumentException');
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
}
|
||||
Crypt::hmacBase64($data, $key);
|
||||
}
|
||||
|
||||
|
||||
@@ -343,7 +343,12 @@ class HtmlTest extends TestCase {
|
||||
* @dataProvider providerTestTransformRootRelativeUrlsToAbsoluteAssertion
|
||||
*/
|
||||
public function testTransformRootRelativeUrlsToAbsoluteAssertion($scheme_and_host) {
|
||||
$this->setExpectedException(\AssertionError::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\AssertionError::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\AssertionError::class);
|
||||
}
|
||||
Html::transformRootRelativeUrlsToAbsolute('', $scheme_and_host);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,12 @@ class RandomTest extends TestCase {
|
||||
// There are fewer than 100 possibilities so an exception should occur to
|
||||
// prevent infinite loops.
|
||||
$random = new Random();
|
||||
$this->setExpectedException(\RuntimeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\RuntimeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\RuntimeException::class);
|
||||
}
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$str = $random->name(1, TRUE);
|
||||
$names[$str] = TRUE;
|
||||
@@ -78,7 +83,12 @@ class RandomTest extends TestCase {
|
||||
// There are fewer than 100 possibilities so an exception should occur to
|
||||
// prevent infinite loops.
|
||||
$random = new Random();
|
||||
$this->setExpectedException(\RuntimeException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\RuntimeException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\RuntimeException::class);
|
||||
}
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$str = $random->string(1, TRUE);
|
||||
$names[$str] = TRUE;
|
||||
|
||||
@@ -17,7 +17,12 @@ class RectangleTest extends TestCase {
|
||||
* @covers ::rotate
|
||||
*/
|
||||
public function testWrongWidth() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\InvalidArgumentException::class);
|
||||
}
|
||||
$rect = new Rectangle(-40, 20);
|
||||
}
|
||||
|
||||
@@ -27,7 +32,12 @@ class RectangleTest extends TestCase {
|
||||
* @covers ::rotate
|
||||
*/
|
||||
public function testWrongHeight() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class);
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
}
|
||||
else {
|
||||
$this->setExpectedException(\InvalidArgumentException::class);
|
||||
}
|
||||
$rect = new Rectangle(40, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class SafeMarkupTest extends TestCase {
|
||||
* @covers ::isSafe
|
||||
*/
|
||||
public function testIsSafe() {
|
||||
$safe_string = $this->getMock('\Drupal\Component\Render\MarkupInterface');
|
||||
$safe_string = $this->getMockBuilder('\Drupal\Component\Render\MarkupInterface')->getMock();
|
||||
$this->assertTrue(SafeMarkup::isSafe($safe_string));
|
||||
$string_object = new SafeMarkupTestString('test');
|
||||
$this->assertFalse(SafeMarkup::isSafe($string_object));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user