Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663

This commit is contained in:
Greg Anderson 2015-10-08 11:40:12 -07:00
parent eb34d130a8
commit f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions

View file

@ -99,7 +99,7 @@ class ActionUnitTest extends KernelTestBase {
'user',
),
);
$this->assertIdentical($expected, $action->calculateDependencies());
$this->assertIdentical($expected, $action->calculateDependencies()->getDependencies());
}
}

View file

@ -49,7 +49,7 @@ class AjaxFormCacheTest extends AjaxTestBase {
$this->drupalLogin($this->rootUser);
$this->drupalPlaceBlock('search_form_block', ['weight' => -5]);
$this->drupalPlaceBlock('ajax_forms_test_block', ['cache' => ['max_age' => 0]]);
$this->drupalPlaceBlock('ajax_forms_test_block');
$this->drupalGet('');
$this->drupalPostAjaxForm(NULL, ['test1' => 'option1'], 'test1');
@ -66,7 +66,7 @@ class AjaxFormCacheTest extends AjaxTestBase {
$this->container->get('module_installer')->install(['block']);
$this->drupalLogin($this->rootUser);
$this->drupalPlaceBlock('ajax_forms_test_block', ['cache' => ['max_age' => 0]]);
$this->drupalPlaceBlock('ajax_forms_test_block');
$url = Url::fromRoute('entity.user.canonical', ['user' => $this->rootUser->id()], ['query' => ['foo' => 'bar']]);
$this->drupalGet($url);

View file

@ -7,39 +7,289 @@
namespace Drupal\system\Tests\Asset;
use Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException;
use Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException;
use Drupal\simpletest\KernelTestBase;
/**
* Tests the element info.
* Tests the library discovery and library discovery parser.
*
* @group Render
*/
class LibraryDiscoveryIntegrationTest extends KernelTestBase {
/**
* The library discovery service.
*
* @var \Drupal\Core\Asset\LibraryDiscoveryInterface
*/
protected $libraryDiscovery;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->container->get('theme_handler')->install(['test_theme', 'classy']);
$this->container->get('theme_installer')->install(['test_theme', 'classy']);
$this->libraryDiscovery = $this->container->get('library.discovery');
}
/**
* Ensures that the element info can be altered by themes.
*/
public function testElementInfoByTheme() {
$this->activateTheme('test_theme');
$this->assertTrue($this->libraryDiscovery->getLibraryByName('test_theme', 'kitten'));
}
/**
* Tests that libraries-override are applied to library definitions.
*/
public function testLibrariesOverride() {
// Assert some classy libraries that will be overridden or removed.
$this->activateTheme('classy');
$this->assertAssetInLibrary('core/themes/classy/css/components/button.css', 'classy', 'base', 'css');
$this->assertAssetInLibrary('core/themes/classy/css/components/collapse-processed.css', 'classy', 'base', 'css');
$this->assertAssetInLibrary('core/themes/classy/css/components/container-inline.css', 'classy', 'base', 'css');
$this->assertAssetInLibrary('core/themes/classy/css/components/details.css', 'classy', 'base', 'css');
$this->assertAssetInLibrary('core/themes/classy/css/components/dialog.css', 'classy', 'dialog', 'css');
// Confirmatory assert on core library to be removed.
$this->assertTrue($this->libraryDiscovery->getLibraryByName('core', 'drupal.progress'), 'Confirmatory test on "core/drupal.progress"');
// Activate test theme that defines libraries overrides.
$this->activateTheme('test_theme');
// Assert that entire library was correctly overridden.
$this->assertEqual($this->libraryDiscovery->getLibraryByName('core', 'drupal.collapse'), $this->libraryDiscovery->getLibraryByName('test_theme', 'collapse'), 'Entire library correctly overridden.');
// Assert that classy library assets were correctly overridden or removed.
$this->assertNoAssetInLibrary('core/themes/classy/css/components/button.css', 'classy', 'base', 'css');
$this->assertNoAssetInLibrary('core/themes/classy/css/components/collapse-processed.css', 'classy', 'base', 'css');
$this->assertNoAssetInLibrary('core/themes/classy/css/components/container-inline.css', 'classy', 'base', 'css');
$this->assertNoAssetInLibrary('core/themes/classy/css/components/details.css', 'classy', 'base', 'css');
$this->assertNoAssetInLibrary('core/themes/classy/css/components/dialog.css', 'classy', 'dialog', 'css');
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme/css/my-button.css', 'classy', 'base', 'css');
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme/css/my-collapse-processed.css', 'classy', 'base', 'css');
$this->assertAssetInLibrary('themes/my_theme/css/my-container-inline.css', 'classy', 'base', 'css');
$this->assertAssetInLibrary('themes/my_theme/css/my-details.css', 'classy', 'base', 'css');
// Assert that entire library was correctly removed.
$this->assertFalse($this->libraryDiscovery->getLibraryByName('core', 'drupal.progress'), 'Entire library correctly removed.');
// Assert that overridden library asset still retains attributes.
$library = $this->libraryDiscovery->getLibraryByName('core', 'jquery');
foreach ($library['js'] as $definition) {
if ($definition['data'] == 'core/modules/system/tests/themes/test_theme/js/collapse.js') {
$this->assertTrue($definition['minified'] && $definition['weight'] == -20, 'Previous attributes retained');
break;
}
}
}
/**
* Tests libraries-override on drupalSettings.
*/
public function testLibrariesOverrideDrupalSettings() {
// Activate test theme that attempts to override drupalSettings.
$this->activateTheme('test_theme_libraries_override_with_drupal_settings');
// Assert that drupalSettings cannot be overridden and throws an exception.
try {
$this->libraryDiscovery->getLibraryByName('core', 'drupal.ajax');
$this->fail('Throw Exception when trying to override drupalSettings');
}
catch (InvalidLibrariesOverrideSpecificationException $e) {
$expected_message = 'drupalSettings may not be overridden in libraries-override. Trying to override core/drupal.ajax/drupalSettings. Use hook_library_info_alter() instead.';
$this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when trying to override drupalSettings');
}
}
/**
* Tests libraries-override on malformed assets.
*/
public function testLibrariesOverrideMalformedAsset() {
// Activate test theme that overrides with a malformed asset.
$this->activateTheme('test_theme_libraries_override_with_invalid_asset');
// Assert that improperly formed asset "specs" throw an exception.
try {
$this->libraryDiscovery->getLibraryByName('core', 'drupal.dialog');
$this->fail('Throw Exception when specifying invalid override');
}
catch (InvalidLibrariesOverrideSpecificationException $e) {
$expected_message = 'Library asset core/drupal.dialog/css is not correctly specified. It should be in the form "extension/library_name/sub_key/path/to/asset.js".';
$this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when specifying invalid override');
}
}
/**
* Tests library assets with other ways for specifying paths.
*/
public function testLibrariesOverrideOtherAssetLibraryNames() {
// Activate a test theme that defines libraries overrides on other types of
// assets.
$this->activateTheme('test_theme');
// Assert Drupal-relative paths.
$this->assertAssetInLibrary('themes/my_theme/css/dropbutton.css', 'core', 'drupal.dropbutton', 'css');
// Assert stream wrapper paths.
$this->assertAssetInLibrary('public://my_css/vertical-tabs.css', 'core', 'drupal.vertical-tabs', 'css');
// Assert a protocol-relative URI.
$this->assertAssetInLibrary('//my-server/my_theme/css/jquery_ui.css', 'core', 'jquery.ui', 'css');
// Assert an absolute URI.
$this->assertAssetInLibrary('http://example.com/my_theme/css/farbtastic.css', 'core', 'jquery.farbtastic', 'css');
}
/**
* Tests that base theme libraries-override still apply in sub themes.
*/
public function testBaseThemeLibrariesOverrideInSubTheme() {
// Activate a test theme that has subthemes.
$this->activateTheme('test_subtheme');
// Assert that libraries-override specified in the base theme still applies
// in the sub theme.
$this->assertNoAssetInLibrary('core/misc/dialog/dialog.js', 'core', 'drupal.dialog', 'js');
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_basetheme/css/farbtastic.css', 'core', 'jquery.farbtastic', 'css');
}
/**
* Tests libraries-extend.
*/
public function testLibrariesExtend() {
// Activate classy themes and verify the libraries are not extended.
$this->activateTheme('classy');
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_1.css', 'classy', 'book-navigation', 'css');
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/js/extend_1.js', 'classy', 'book-navigation', 'js');
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_2.css', 'classy', 'book-navigation', 'css');
// Activate the theme that extends the book-navigation library in classy.
$this->activateTheme('test_theme_libraries_extend');
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_1.css', 'classy', 'book-navigation', 'css');
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/js/extend_1.js', 'classy', 'book-navigation', 'js');
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_2.css', 'classy', 'book-navigation', 'css');
// Activate a sub theme and confirm that it inherits the library assets
// extended in the base theme as well as its own.
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_basetheme/css/base-libraries-extend.css', 'classy', 'base', 'css');
$this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_subtheme/css/sub-libraries-extend.css', 'classy', 'base', 'css');
$this->activateTheme('test_subtheme');
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_basetheme/css/base-libraries-extend.css', 'classy', 'base', 'css');
$this->assertAssetInLibrary('core/modules/system/tests/themes/test_subtheme/css/sub-libraries-extend.css', 'classy', 'base', 'css');
// Activate test theme that extends with a non-existent library. An
// exception should be thrown.
$this->activateTheme('test_theme_libraries_extend');
try {
$this->libraryDiscovery->getLibraryByName('core', 'drupal.dialog');
$this->fail('Throw Exception when specifying non-existent libraries-extend.');
}
catch (InvalidLibrariesExtendSpecificationException $e) {
$expected_message = 'The specified library "test_theme_libraries_extend/non_existent_library" does not exist.';
$this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when specifying non-existent libraries-extend.');
}
// Also, test non-string libraries-extend. An exception should be thrown.
$this->container->get('theme_installer')->install(['test_theme']);
try {
$this->libraryDiscovery->getLibraryByName('test_theme', 'collapse');
$this->fail('Throw Exception when specifying non-string libraries-extend.');
}
catch (InvalidLibrariesExtendSpecificationException $e) {
$expected_message = 'The libraries-extend specification for each library must be a list of strings.';
$this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when specifying non-string libraries-extend.');
}
}
/**
* Activates a specified theme.
*
* Installs the theme if not already installed and makes it the active theme.
*
* @param string $theme_name
* The name of the theme to be activated.
*/
protected function activateTheme($theme_name) {
$this->container->get('theme_installer')->install([$theme_name]);
/** @var \Drupal\Core\Theme\ThemeInitializationInterface $theme_initializer */
$theme_initializer = $this->container->get('theme.initialization');
/** @var \Drupal\Core\Theme\ThemeManagerInterface $theme_manager */
$theme_manager = $this->container->get('theme.manager');
/** @var \Drupal\Core\Render\ElementInfoManagerInterface $element_info */
$library_discovery = $this->container->get('library.discovery');
$theme_manager->setActiveTheme($theme_initializer->getActiveThemeByName($theme_name));
$theme_manager->setActiveTheme($theme_initializer->getActiveThemeByName('test_theme'));
$this->assertTrue($library_discovery->getLibraryByName('test_theme', 'kitten'));
$this->libraryDiscovery->clearCachedDefinitions();
// Assert message.
$this->pass(sprintf('Activated theme "%s"', $theme_name));
}
/**
* Asserts that the specified asset is in the given library.
*
* @param string $asset
* The asset file with the path for the file.
* @param string $extension
* The extension in which the $library is defined.
* @param string $library_name
* Name of the library.
* @param mixed $sub_key
* The library sub key where the given asset is defined.
* @param string $message
* (optional) A message to display with the assertion.
*
* @return bool
* TRUE if the specified asset is found in the library.
*/
protected function assertAssetInLibrary($asset, $extension, $library_name, $sub_key, $message = NULL) {
if (!isset($message)) {
$message = sprintf('Asset %s found in library "%s/%s"', $asset, $extension, $library_name);
}
$library = $this->libraryDiscovery->getLibraryByName($extension, $library_name);
foreach ($library[$sub_key] as $definition) {
if ($asset == $definition['data']) {
return $this->pass($message);
}
}
return $this->fail($message);
}
/**
* Asserts that the specified asset is not in the given library.
*
* @param string $asset
* The asset file with the path for the file.
* @param string $extension
* The extension in which the $library_name is defined.
* @param string $library_name
* Name of the library.
* @param mixed $sub_key
* The library sub key where the given asset is defined.
* @param string $message
* (optional) A message to display with the assertion.
*
* @return bool
* TRUE if the specified asset is not found in the library.
*/
protected function assertNoAssetInLibrary($asset, $extension, $library_name, $sub_key, $message = NULL) {
if (!isset($message)) {
$message = sprintf('Asset %s not found in library "%s/%s"', $asset, $extension, $library_name);
}
$library = $this->libraryDiscovery->getLibraryByName($extension, $library_name);
foreach ($library[$sub_key] as $definition) {
if ($asset == $definition['data']) {
return $this->fail($message);
}
}
return $this->pass($message);
}
}

View file

@ -54,12 +54,14 @@ class ProcessingTest extends WebTestBase {
// Batch 0: no operation.
$edit = array('batch' => 'batch_0');
$this->drupalPostForm('batch-test', $edit, 'Submit');
$this->assertNoEscaped('<', 'No escaped markup is present.');
$this->assertBatchMessages($this->_resultMessages('batch_0'), 'Batch with no operation performed successfully.');
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
// Batch 1: several simple operations.
$edit = array('batch' => 'batch_1');
$this->drupalPostForm('batch-test', $edit, 'Submit');
$this->assertNoEscaped('<', 'No escaped markup is present.');
$this->assertBatchMessages($this->_resultMessages('batch_1'), 'Batch with simple operations performed successfully.');
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), 'Execution order was correct.');
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
@ -67,6 +69,7 @@ class ProcessingTest extends WebTestBase {
// Batch 2: one multistep operation.
$edit = array('batch' => 'batch_2');
$this->drupalPostForm('batch-test', $edit, 'Submit');
$this->assertNoEscaped('<', 'No escaped markup is present.');
$this->assertBatchMessages($this->_resultMessages('batch_2'), 'Batch with multistep operation performed successfully.');
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_2'), 'Execution order was correct.');
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
@ -74,6 +77,7 @@ class ProcessingTest extends WebTestBase {
// Batch 3: simple + multistep combined.
$edit = array('batch' => 'batch_3');
$this->drupalPostForm('batch-test', $edit, 'Submit');
$this->assertNoEscaped('<', 'No escaped markup is present.');
$this->assertBatchMessages($this->_resultMessages('batch_3'), 'Batch with simple and multistep operations performed successfully.');
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_3'), 'Execution order was correct.');
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
@ -81,6 +85,7 @@ class ProcessingTest extends WebTestBase {
// Batch 4: nested batch.
$edit = array('batch' => 'batch_4');
$this->drupalPostForm('batch-test', $edit, 'Submit');
$this->assertNoEscaped('<', 'No escaped markup is present.');
$this->assertBatchMessages($this->_resultMessages('batch_4'), 'Nested batch performed successfully.');
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_4'), 'Execution order was correct.');
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
@ -91,6 +96,7 @@ class ProcessingTest extends WebTestBase {
*/
function testBatchFormMultistep() {
$this->drupalGet('batch-test/multistep');
$this->assertNoEscaped('<', 'No escaped markup is present.');
$this->assertText('step 1', 'Form is displayed in step 1.');
// First step triggers batch 1.
@ -98,12 +104,14 @@ class ProcessingTest extends WebTestBase {
$this->assertBatchMessages($this->_resultMessages('batch_1'), 'Batch for step 1 performed successfully.');
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), 'Execution order was correct.');
$this->assertText('step 2', 'Form is displayed in step 2.');
$this->assertNoEscaped('<', 'No escaped markup is present.');
// Second step triggers batch 2.
$this->drupalPostForm(NULL, array(), 'Submit');
$this->assertBatchMessages($this->_resultMessages('batch_2'), 'Batch for step 2 performed successfully.');
$this->assertEqual(batch_test_stack(), $this->_resultStack('batch_2'), 'Execution order was correct.');
$this->assertText('Redirection successful.', 'Redirection after batch execution is correct.');
$this->assertNoEscaped('<', 'No escaped markup is present.');
}
/**

View file

@ -162,7 +162,7 @@ class SystemMenuBlockTest extends KernelTestBase {
'theme' => 'stark',
));
$dependencies = $block->calculateDependencies();
$dependencies = $block->calculateDependencies()->getDependencies();
$expected = array(
'config' => array(
'system.menu.' . $this->menu->id()

View file

@ -37,14 +37,14 @@ class DrupalSetMessageTest extends WebTestBase {
$this->assertUniqueText('Non Duplicated message');
$this->assertNoUniqueText('Duplicated message');
// Ensure SafeString objects are rendered as expected.
$this->assertRaw('SafeString with <em>markup!</em>');
$this->assertUniqueText('SafeString with markup!');
$this->assertRaw('SafeString2 with <em>markup!</em>');
// Ensure Markup objects are rendered as expected.
$this->assertRaw('Markup with <em>markup!</em>');
$this->assertUniqueText('Markup with markup!');
$this->assertRaw('Markup2 with <em>markup!</em>');
// Ensure when the same message is of different types it is not duplicated.
$this->assertUniqueText('Non duplicate SafeString / string.');
$this->assertNoUniqueText('Duplicate SafeString / string.');
$this->assertUniqueText('Non duplicate Markup / string.');
$this->assertNoUniqueText('Duplicate Markup / string.');
// Ensure that strings that are not marked as safe are escaped.
$this->assertEscaped('<em>This<span>markup will be</span> escaped</em>.');

View file

@ -17,8 +17,18 @@ use Drupal\Core\Cache\ApcuBackend;
*/
class ApcuBackendUnitTest extends GenericCacheBackendUnitTestBase {
protected function checkRequirements() {
$requirements = parent::checkRequirements();
/**
* Get a list of failed requirements.
*
* This specifically bypasses checkRequirements because it fails tests. PHP 7
* does not have APC and simpletest does not have a explicit "skip"
* functionality so to emulate it we override all test methods and explicitly
* pass when requirements are not met.
*
* @return array
*/
protected function getRequirements() {
$requirements = [];
if (!extension_loaded('apc')) {
$requirements[] = 'APC extension not found.';
}
@ -33,10 +43,35 @@ class ApcuBackendUnitTest extends GenericCacheBackendUnitTestBase {
return $requirements;
}
/**
* Check if requirements fail.
*
* If the requirements fail the test method should return immediately instead
* of running any tests. Messages will be output to display why the test was
* skipped.
*/
protected function requirementsFail() {
$requirements = $this->getRequirements();
if (!empty($requirements)) {
foreach ($requirements as $message) {
$this->pass($message);
}
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
protected function createCacheBackend($bin) {
return new ApcuBackend($bin, $this->databasePrefix, \Drupal::service('cache_tags.invalidator.checksum'));
}
/**
* {@inheritdoc}
*/
protected function tearDown() {
foreach ($this->cachebackends as $bin => $cachebackend) {
$this->cachebackends[$bin]->removeBin();
@ -44,4 +79,114 @@ class ApcuBackendUnitTest extends GenericCacheBackendUnitTestBase {
parent::tearDown();
}
/**
* {@inheritdoc}
*/
public function testSetGet() {
if ($this->requirementsFail()) {
return;
}
parent::testSetGet();
}
/**
* {@inheritdoc}
*/
public function testDelete() {
if ($this->requirementsFail()) {
return;
}
parent::testDelete();
}
/**
* {@inheritdoc}
*/
public function testValueTypeIsKept() {
if ($this->requirementsFail()) {
return;
}
parent::testValueTypeIsKept();
}
/**
* {@inheritdoc}
*/
public function testGetMultiple() {
if ($this->requirementsFail()) {
return;
}
parent::testGetMultiple();
}
/**
* {@inheritdoc}
*/
public function testSetMultiple() {
if ($this->requirementsFail()) {
return;
}
parent::testSetMultiple();
}
/**
* {@inheritdoc}
*/
public function testDeleteMultiple() {
if ($this->requirementsFail()) {
return;
}
parent::testDeleteMultiple();
}
/**
* {@inheritdoc}
*/
public function testDeleteAll() {
if ($this->requirementsFail()) {
return;
}
parent::testDeleteAll();
}
/**
* {@inheritdoc}
*/
public function testInvalidate() {
if ($this->requirementsFail()) {
return;
}
parent::testInvalidate();
}
/**
* {@inheritdoc}
*/
public function testInvalidateTags() {
if ($this->requirementsFail()) {
return;
}
parent::testInvalidateTags();
}
/**
* {@inheritdoc}
*/
public function testInvalidateAll() {
if ($this->requirementsFail()) {
return;
}
parent::testInvalidateAll();
}
/**
* {@inheritdoc}
*/
public function testRemoveBin() {
if ($this->requirementsFail()) {
return;
}
parent::testRemoveBin();
}
}

View file

@ -218,13 +218,13 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
$this->assertEqual('value', $backend->get('TEST8')->data);
$this->assertFalse($backend->get('test8'));
// Calling ::set() with invalid cache tags.
// Calling ::set() with invalid cache tags. This should fail an assertion.
try {
$backend->set('exception_test', 'value', Cache::PERMANENT, ['node' => [3, 5, 7]]);
$this->fail('::set() was called with invalid cache tags, no exception was thrown.');
$backend->set('assertion_test', 'value', Cache::PERMANENT, ['node' => [3, 5, 7]]);
$this->fail('::set() was called with invalid cache tags, runtime assertion did not fail.');
}
catch (\LogicException $e) {
$this->pass('::set() was called with invalid cache tags, an exception was thrown.');
catch (\AssertionError $e) {
$this->pass('::set() was called with invalid cache tags, runtime assertion failed.');
}
}
@ -412,7 +412,8 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
$this->assertEqual($cached['cid_5']->data, $items['cid_5']['data'], 'New cache item set correctly.');
// Calling ::setMultiple() with invalid cache tags.
// Calling ::setMultiple() with invalid cache tags. This should fail an
// assertion.
try {
$items = [
'exception_test_1' => array('data' => 1, 'tags' => []),
@ -420,10 +421,10 @@ abstract class GenericCacheBackendUnitTestBase extends KernelTestBase {
'exception_test_3' => array('data' => 3, 'tags' => ['node' => [3, 5, 7]]),
];
$backend->setMultiple($items);
$this->fail('::setMultiple() was called with invalid cache tags, no exception was thrown.');
$this->fail('::setMultiple() was called with invalid cache tags, runtime assertion did not fail.');
}
catch (\LogicException $e) {
$this->pass('::setMultiple() was called with invalid cache tags, an exception was thrown.');
catch (\AssertionError $e) {
$this->pass('::setMultiple() was called with invalid cache tags, runtime assertion failed.');
}
}

View file

@ -61,9 +61,14 @@ class AddFeedTest extends WebTestBase {
$build['#attached']['feed'][] = [$feed_info['url'], $feed_info['title']];
}
drupal_process_attached($build);
$this->setRawContent(drupal_get_html_head());
// Use the bare HTML page renderer to render our links.
$renderer = $this->container->get('bare_html_page_renderer');
$response = $renderer->renderBarePage(
$build, '', $this->container->get('theme.manager')->getActiveTheme()->getName()
);
// Glean the content from the response object.
$this->setRawContent($response->getContent());
// Assert that the content contains the RSS links we specified.
foreach ($urls as $description => $feed_info) {
$this->assertPattern($this->urlToRSSLinkPattern($feed_info['url'], $feed_info['title']), format_string('Found correct feed header for %description', array('%description' => $description)));
}

View file

@ -288,7 +288,7 @@ class AttachedAssetsTest extends KernelTestBase {
$js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js);
$rendered_js = $this->renderer->renderPlain($js_render_array);
$this->assertTrue(strpos($rendered_js, 'core/assets/vendor/backbone/backbone-min.js?v=1.2.1') > 0 && strpos($rendered_js, 'core/assets/vendor/domready/ready.min.js?v=1.0.8') > 0 , 'JavaScript version identifiers correctly appended to URLs');
$this->assertTrue(strpos($rendered_js, 'core/assets/vendor/backbone/backbone-min.js?v=1.2.3') > 0 && strpos($rendered_js, 'core/assets/vendor/domready/ready.min.js?v=1.0.8') > 0 , 'JavaScript version identifiers correctly appended to URLs');
}
/**

View file

@ -117,5 +117,10 @@ class FormatDateTest extends WebTestBase {
$this->assertIdentical(format_date($timestamp, 'html_week'), '2007-W12', 'Test html_week date format.');
$this->assertIdentical(format_date($timestamp, 'html_month'), '2007-03', 'Test html_month date format.');
$this->assertIdentical(format_date($timestamp, 'html_year'), '2007', 'Test html_year date format.');
// HTML is not escaped by the date formatter, it must be escaped later.
$formatter = \Drupal::service('date.formatter');
$this->assertIdentical($formatter->format($timestamp, 'custom', '\<\s\c\r\i\p\t\>\a\l\e\r\t\(\'Y\'\)\;\<\/\s\c\r\i\p\t\>'), "<script>alert('2007');</script>", 'Script tags not removed from dates.');
$this->assertIdentical($formatter->format($timestamp, 'custom', '\<\e\m\>Y\<\/\e\m\>'), '<em>2007</em>', 'Em tags are not removed from dates.');
}
}

View file

@ -53,17 +53,18 @@ class RenderTest extends KernelTestBase {
}
/**
* Tests drupal_process_attached().
* Tests that we get an exception when we try to attach an illegal type.
*/
public function testDrupalProcessAttached() {
public function testProcessAttached() {
// Specify invalid attachments in a render array.
$build['#attached']['library'][] = 'core/drupal.states';
$build['#attached']['drupal_process_states'][] = [];
$renderer = $this->container->get('bare_html_page_renderer');
try {
drupal_process_attached($build);
$renderer->renderBarePage($build, '', $this->container->get('theme.manager')->getActiveTheme()->getName());
$this->fail("Invalid #attachment 'drupal_process_states' allowed");
}
catch (\Exception $e) {
catch (\LogicException $e) {
$this->pass("Invalid #attachment 'drupal_process_states' not allowed");
}
}

View file

@ -132,7 +132,7 @@ class RenderWebTest extends WebTestBase {
),
);
$this->assertRenderedElement($element, '//a[@href=:href and contains(., :title)]', array(
':href' => \Drupal::urlGenerator()->generateFromPath('common-test/destination', ['absolute' => TRUE]),
':href' => URL::fromRoute('common_test.destination')->setAbsolute()->toString(),
':title' => $element['#title'],
));

View file

@ -17,8 +17,9 @@ use Drupal\simpletest\WebTestBase;
/**
* Confirm that \Drupal\Core\Url,
* \Drupal\Component\Utility\UrlHelper::filterQueryParameters(),
* \Drupal\Component\Utility\UrlHelper::buildQuery(), and _l() work correctly
* with various input.
* \Drupal\Component\Utility\UrlHelper::buildQuery(), and
* \Drupal\Core\Utility\LinkGeneratorInterface::generate()
* work correctly with various input.
*
* @group Common
*/
@ -36,7 +37,7 @@ class UrlTest extends WebTestBase {
$encoded_path = "3CSCRIPT%3Ealert%28%27XSS%27%29%3C/SCRIPT%3E";
$link = \Drupal::l($text, Url::fromUserInput('/' . $path));
$this->assertTrue(strpos($link, $encoded_path) !== FALSE && strpos($link, $path) === FALSE, format_string('XSS attack @path was filtered by _l().', array('@path' => $path)));
$this->assertTrue(strpos($link, $encoded_path) !== FALSE && strpos($link, $path) === FALSE, format_string('XSS attack @path was filtered by \Drupal\Core\Utility\LinkGeneratorInterface::generate().', array('@path' => $path)));
// Test \Drupal\Core\Url.
$link = Url::fromUri('base:' . $path)->toString();
@ -102,7 +103,8 @@ class UrlTest extends WebTestBase {
$rendered = $renderer->renderRoot($hreflang_override_link);
$this->assertTrue($this->hasAttribute('hreflang', $rendered, 'foo'), format_string('hreflang attribute with value @hreflang is present on a rendered link when @hreflang is provided in the render array.', array('@hreflang' => 'foo')));
// Test the active class in links produced by _l() and #type 'link'.
// Test the active class in links produced by
// \Drupal\Core\Utility\LinkGeneratorInterface::generate() and #type 'link'.
$options_no_query = array();
$options_query = array(
'query' => array(
@ -122,23 +124,24 @@ class UrlTest extends WebTestBase {
$this->drupalGet($path, $options_no_query);
$links = $this->xpath('//a[@href = :href and contains(@class, :class)]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_no_query)->toString(), ':class' => 'is-active'));
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page is marked active.');
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page is marked active.');
$links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_query)->toString(), ':class' => 'is-active'));
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page with a query string when the current page has no query string is not marked active.');
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string when the current page has no query string is not marked active.');
$this->drupalGet($path, $options_query);
$links = $this->xpath('//a[@href = :href and contains(@class, :class)]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_query)->toString(), ':class' => 'is-active'));
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page with a query string that matches the current query string is marked active.');
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string that matches the current query string is marked active.');
$links = $this->xpath('//a[@href = :href and contains(@class, :class)]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_query_reverse)->toString(), ':class' => 'is-active'));
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page with a query string that has matching parameters to the current query string but in a different order is marked active.');
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string that has matching parameters to the current query string but in a different order is marked active.');
$links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', array(':href' => Url::fromRoute('common_test.l_active_class', [], $options_no_query)->toString(), ':class' => 'is-active'));
$this->assertTrue(isset($links[0]), 'A link generated by _l() to the current page without a query string when the current page has a query string is not marked active.');
$this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page without a query string when the current page has a query string is not marked active.');
// Test adding a custom class in links produced by _l() and #type 'link'.
// Test _l().
// Test adding a custom class in links produced by
// \Drupal\Core\Utility\LinkGeneratorInterface::generate() and #type 'link'.
// Test the link generator.
$class_l = $this->randomMachineName();
$link_l = \Drupal::l($this->randomMachineName(), new Url('<current>', [], ['attributes' => ['class' => [$class_l]]]));
$this->assertTrue($this->hasAttribute('class', $link_l, $class_l), format_string('Custom class @class is present on link when requested by l()', array('@class' => $class_l)));
@ -166,10 +169,10 @@ class UrlTest extends WebTestBase {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
// Build a link with _l() for reference.
// Build a link with the link generator for reference.
$l = \Drupal::l('foo', Url::fromUri('https://www.drupal.org'));
// Test a renderable array passed to _l().
// Test a renderable array passed to the link generator.
$renderer->executeInRenderContext(new RenderContext(), function() use ($renderer, $l) {
$renderable_text = array('#markup' => 'foo');
$l_renderable_text = \Drupal::l($renderable_text, Url::fromUri('https://www.drupal.org'));

View file

@ -40,8 +40,6 @@ class XssUnitTest extends KernelTestBase {
$this->assertEqual($text, 'Escaped text: &lt;script&gt;', 't replaces and escapes string.');
$text = t('Placeholder text: %value', array('%value' => '<script>'));
$this->assertEqual($text, 'Placeholder text: <em class="placeholder">&lt;script&gt;</em>', 't replaces, escapes and themes string.');
$text = t('Verbatim text: !value', array('!value' => '<script>'));
$this->assertEqual($text, 'Verbatim text: <script>', 't replaces verbatim string as-is.');
}
/**

View file

@ -8,6 +8,7 @@
namespace Drupal\system\Tests\Database;
use Drupal\Core\Database\Database;
use Drupal\Core\Database\DatabaseExceptionWrapper;
/**
* Tests of the core database system.
@ -122,22 +123,41 @@ class ConnectionTest extends DatabaseTestBase {
* Ensure that you cannot execute multiple statements on phpversion() > 5.5.21 or > 5.6.5.
*/
public function testMultipleStatementsForNewPhp() {
// This just tests mysql, as other PDO integrations don't allow to disable
// This just tests mysql, as other PDO integrations don't allow disabling
// multiple statements.
if (Database::getConnection()->databaseType() !== 'mysql' || !defined('\PDO::MYSQL_ATTR_MULTI_STATEMENTS')) {
return;
}
$db = Database::getConnection('default', 'default');
// Disable the protection at the PHP level.
try {
$db->query('SELECT * FROM {test}; SELECT * FROM {test_people}')->execute();
$this->fail('NO PDO exception thrown for multiple statements.');
$db->query('SELECT * FROM {test}; SELECT * FROM {test_people}',
[],
[ 'allow_delimiter_in_query' => TRUE ]
);
$this->fail('No PDO exception thrown for multiple statements.');
}
catch (\Exception $e) {
catch (DatabaseExceptionWrapper $e) {
$this->pass('PDO exception thrown for multiple statements.');
}
}
/**
* Ensure that you cannot execute multiple statements.
*/
public function testMultipleStatements() {
$db = Database::getConnection('default', 'default');
try {
$db->query('SELECT * FROM {test}; SELECT * FROM {test_people}');
$this->fail('No exception thrown for multiple statements.');
}
catch (\InvalidArgumentException $e) {
$this->pass('Exception thrown for multiple statements.');
}
}
/**
* Test the escapeTable(), escapeField() and escapeAlias() methods with all possible reserved words in PostgreSQL.
*/

View file

@ -31,6 +31,7 @@ abstract class DatabaseTestBase extends KernelTestBase {
'test_null',
'test_serialized',
'test_special_columns',
'TEST_UPPERCASE',
));
self::addSampleData();
}

View file

@ -66,6 +66,74 @@ class QueryTest extends DatabaseTestBase {
$this->assertFalse($result, 'SQL injection attempt did not result in a row being inserted in the database table.');
}
/**
* Tests SQL injection via condition operator.
*/
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);
});
try {
$result = db_select('test', 't')
->fields('t')
->condition('name', 1, $injection)
->execute();
$this->fail('Should not be able to attempt SQL injection via condition operator.');
}
catch (\ErrorException $e) {
$this->pass('SQL injection attempt via condition arguments should result in a database exception.');
}
// Test that the insert query that was used in the SQL injection attempt did
// not result in a row being inserted in the database.
$result = db_select('test')
->condition('name', 'test12345678')
->countQuery()
->execute()
->fetchField();
$this->assertFalse($result, 'SQL injection attempt did not result in a row being inserted in the database table.');
// Attempt SQLi via union query with no unsafe characters.
$this->enableModules(['user']);
$this->installEntitySchema('user');
db_insert('test')
->fields(['name' => '123456'])
->execute();
$injection = "= 1 UNION ALL SELECT password FROM user WHERE uid =";
try {
$result = db_select('test', 't')
->fields('t', array('name', 'name'))
->condition('name', 1, $injection)
->execute();
$this->fail('Should not be able to attempt SQL injection via operator.');
}
catch (\ErrorException $e) {
$this->pass('SQL injection attempt via condition arguments should result in a database exception.');
}
// Attempt SQLi via union query - uppercase tablename.
db_insert('TEST_UPPERCASE')
->fields(['name' => 'secrets'])
->execute();
$injection = "IS NOT NULL) UNION ALL SELECT name FROM {TEST_UPPERCASE} -- ";
try {
$result = db_select('test', 't')
->fields('t', array('name'))
->condition('name', 1, $injection)
->execute();
$this->fail('Should not be able to attempt SQL injection via operator.');
}
catch (\ErrorException $e) {
$this->pass('SQL injection attempt via condition arguments should result in a database exception.');
}
restore_error_handler();
}
/**
* Tests numeric query parameter expansion in expressions.
*

View file

@ -640,7 +640,7 @@ class SchemaTest extends KernelTestBase {
}
/**
* Tests changing columns between numeric types.
* Tests changing columns between types.
*/
function testSchemaChangeField() {
$field_specs = array(
@ -661,6 +661,27 @@ class SchemaTest extends KernelTestBase {
$this->assertFieldChange($old_spec, $new_spec);
}
}
$field_specs = array(
array('type' => 'varchar_ascii', 'length' => '255'),
array('type' => 'varchar', 'length' => '255'),
array('type' => 'text'),
array('type' => 'blob', 'size' => 'big'),
);
foreach ($field_specs as $i => $old_spec) {
foreach ($field_specs as $j => $new_spec) {
if ($i === $j) {
// Do not change a field into itself.
continue;
}
// Note if the serialized data contained an object this would fail on
// Postgres.
// @see https://www.drupal.org/node/1031122
$this->assertFieldChange($old_spec, $new_spec, serialize(['string' => "This \n has \\\\ some backslash \"*string action.\\n"]));
}
}
}
/**
@ -671,7 +692,7 @@ class SchemaTest extends KernelTestBase {
* @param $new_spec
* The ending field specification.
*/
protected function assertFieldChange($old_spec, $new_spec) {
protected function assertFieldChange($old_spec, $new_spec, $test_data = NULL) {
$table_name = 'test_table_' . ($this->counter++);
$table_spec = array(
'fields' => array(
@ -689,9 +710,24 @@ class SchemaTest extends KernelTestBase {
// Remove inserted rows.
db_truncate($table_name)->execute();
if ($test_data) {
$id = db_insert($table_name)
->fields(['test_field'], [$test_data])
->execute();
}
// Change the field.
db_change_field($table_name, 'test_field', 'test_field', $new_spec);
if ($test_data) {
$field_value = db_select($table_name)
->fields($table_name, ['test_field'])
->condition('serial_column', $id)
->execute()
->fetchField();
$this->assertIdentical($field_value, $test_data);
}
// Check the field was changed.
$this->assertFieldCharacteristics($table_name, 'test_field', $new_spec);

View file

@ -58,7 +58,7 @@ class SelectTest extends DatabaseTestBase {
$records = $result->fetchAll();
$query = (string) $query;
$expected = "/* Testing query comments * / SELECT nid FROM {node}; -- */ SELECT test.name AS name, test.age AS age\nFROM \n{test} test";
$expected = "/* Testing query comments * / SELECT nid FROM {node}. -- */ SELECT test.name AS name, test.age AS age\nFROM \n{test} test";
$this->assertEqual(count($records), 4, 'Returned the correct number of rows.');
$this->assertNotIdentical(FALSE, strpos($query, $expected), 'The flattened query contains the sanitised comment string.');
@ -81,21 +81,21 @@ class SelectTest extends DatabaseTestBase {
],
// Try and close the comment early.
[
'/* Exploit * / DROP TABLE node; -- */ ',
'/* Exploit * / DROP TABLE node. -- */ ',
['Exploit */ DROP TABLE node; --'],
],
// Variations on comment closing.
[
'/* Exploit * / * / DROP TABLE node; -- */ ',
'/* Exploit * / * / DROP TABLE node. -- */ ',
['Exploit */*/ DROP TABLE node; --'],
],
[
'/* Exploit * * // DROP TABLE node; -- */ ',
'/* Exploit * * // DROP TABLE node. -- */ ',
['Exploit **// DROP TABLE node; --'],
],
// Try closing the comment in the second string which is appended.
[
'/* Exploit * / DROP TABLE node; --; Another try * / DROP TABLE node; -- */ ',
'/* Exploit * / DROP TABLE node. --. Another try * / DROP TABLE node. -- */ ',
['Exploit */ DROP TABLE node; --', 'Another try */ DROP TABLE node; --'],
],
];

View file

@ -184,7 +184,7 @@ class PathElementFormTest extends KernelTestBase implements FormInterface {
$errors = $form_state->getErrors();
// Should be missing 'required_validate' field.
$this->assertEqual(count($errors), 1);
$this->assertEqual($errors, array('required_validate' => t('!name field is required.', array('!name' => 'required_validate'))));
$this->assertEqual($errors, array('required_validate' => t('@name field is required.', array('@name' => 'required_validate'))));
// Test invalid parameters.
$form_state = (new FormState())

View file

@ -31,7 +31,7 @@ class ConfigEntityImportTest extends WebTestBase {
protected function setUp() {
parent::setUp();
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
}
/**
@ -58,7 +58,7 @@ class ConfigEntityImportTest extends WebTestBase {
$this->checkSinglePluginConfigSync($entity, 'configuration', 'message', '');
// Read the existing data, and prepare an altered version in staging.
// Read the existing data, and prepare an altered version in sync.
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
$custom_data['configuration']['message'] = 'Granny Smith';
$this->assertConfigUpdateImport($name, $original_data, $custom_data);
@ -78,7 +78,7 @@ class ConfigEntityImportTest extends WebTestBase {
$this->checkSinglePluginConfigSync($block, 'settings', 'label', 'Red Delicious');
// Read the existing data, and prepare an altered version in staging.
// Read the existing data, and prepare an altered version in sync.
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
$custom_data['settings']['label'] = 'Granny Smith';
$this->assertConfigUpdateImport($name, $original_data, $custom_data);
@ -110,7 +110,7 @@ class ConfigEntityImportTest extends WebTestBase {
$this->assertIdentical($filters, $entity->get('filters'));
$this->assertIdentical($filters, $plugin_collection->getConfiguration());
// Read the existing data, and prepare an altered version in staging.
// Read the existing data, and prepare an altered version in sync.
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
$custom_data['filters']['filter_url']['settings']['filter_url_length'] = 100;
$this->assertConfigUpdateImport($name, $original_data, $custom_data);
@ -145,7 +145,7 @@ class ConfigEntityImportTest extends WebTestBase {
$this->assertIdentical($effects, $entity->get('effects'));
$this->assertIdentical($effects, $plugin_collection->getConfiguration());
// Read the existing data, and prepare an altered version in staging.
// Read the existing data, and prepare an altered version in sync.
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
$effect_name = key($original_data['effects']);
@ -167,7 +167,7 @@ class ConfigEntityImportTest extends WebTestBase {
$this->checkSinglePluginConfigSync($entity, 'configuration', 'boost', 'bi');
// Read the existing data, and prepare an altered version in staging.
// Read the existing data, and prepare an altered version in sync.
$custom_data = $original_data = $this->container->get('config.storage')->read($name);
$custom_data['configuration']['boost'] = 'asdf';
$this->assertConfigUpdateImport($name, $original_data, $custom_data);
@ -218,7 +218,7 @@ class ConfigEntityImportTest extends WebTestBase {
* The new data to store in the config object.
*/
public function assertConfigUpdateImport($name, $original_data, $custom_data) {
$this->container->get('config.storage.staging')->write($name, $custom_data);
$this->container->get('config.storage.sync')->write($name, $custom_data);
// Verify the active configuration still returns the default values.
$config = $this->config($name);

View file

@ -481,6 +481,74 @@ class ConfigEntityQueryTest extends KernelTestBase {
$this->assertIdentical(array_values($this->queryResults), array('1', '2', '3', '4'));
}
/**
* Tests sorting with tableSort on config entity queries.
*/
public function testTableSort() {
$header = array(
array('data' => t('ID'), 'specifier' => 'id'),
array('data' => t('Number'), 'specifier' => 'number'),
);
// Sort key: id
// Sorting with 'DESC' upper case
$this->queryResults = $this->factory->get('config_query_test')
->tableSort($header)
->sort('id', 'DESC')
->execute();
$this->assertIdentical(array_values($this->queryResults), array('5', '4', '3', '2', '1'));
// Sorting with 'ASC' upper case
$this->queryResults = $this->factory->get('config_query_test')
->tableSort($header)
->sort('id', 'ASC')
->execute();
$this->assertIdentical(array_values($this->queryResults), array('1', '2', '3', '4', '5'));
// Sorting with 'desc' lower case
$this->queryResults = $this->factory->get('config_query_test')
->tableSort($header)
->sort('id', 'desc')
->execute();
$this->assertIdentical(array_values($this->queryResults), array('5', '4', '3', '2', '1'));
// Sorting with 'asc' lower case
$this->queryResults = $this->factory->get('config_query_test')
->tableSort($header)
->sort('id', 'asc')
->execute();
$this->assertIdentical(array_values($this->queryResults), array('1', '2', '3', '4', '5'));
// Sort key: number
// Sorting with 'DeSc' mixed upper and lower case
$this->queryResults = $this->factory->get('config_query_test')
->tableSort($header)
->sort('number', 'DeSc')
->execute();
$this->assertIdentical(array_values($this->queryResults), array('3', '5', '2', '1', '4'));
// Sorting with 'AsC' mixed upper and lower case
$this->queryResults = $this->factory->get('config_query_test')
->tableSort($header)
->sort('number', 'AsC')
->execute();
$this->assertIdentical(array_values($this->queryResults), array('4', '1', '2', '5', '3'));
// Sorting with 'dEsC' mixed upper and lower case
$this->queryResults = $this->factory->get('config_query_test')
->tableSort($header)
->sort('number', 'dEsC')
->execute();
$this->assertIdentical(array_values($this->queryResults), array('3', '5', '2', '1', '4'));
// Sorting with 'aSc' mixed upper and lower case
$this->queryResults = $this->factory->get('config_query_test')
->tableSort($header)
->sort('number', 'aSc')
->execute();
$this->assertIdentical(array_values($this->queryResults), array('4', '1', '2', '5', '3'));
}
/**
* Tests dotted path matching.
*/

View file

@ -422,7 +422,7 @@ class ContentEntityChangedTest extends EntityUnitTestBase {
'Changed flag of German translation is set when changing the German translation.'
);
$french = $entity->getTranslation('fr');
$french = $entity->addTranslation('fr');
$entity->setNewRevision();
$entity->save();

View file

@ -51,11 +51,11 @@ class ContentEntityNullStorageTest extends KernelTestBase {
$contact_form = ContactForm::create(['id' => 'test']);
$contact_form->save();
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
// Set up the ConfigImporter object for testing.
$storage_comparer = new StorageComparer(
$this->container->get('config.storage.staging'),
$this->container->get('config.storage.sync'),
$this->container->get('config.storage'),
$this->container->get('config.manager')
);
@ -71,9 +71,9 @@ class ContentEntityNullStorageTest extends KernelTestBase {
$this->container->get('string_translation')
);
// Delete the contact message in staging.
$staging = $this->container->get('config.storage.staging');
$staging->delete($contact_form->getConfigDependencyName());
// Delete the contact message in sync.
$sync = $this->container->get('config.storage.sync');
$sync->delete($contact_form->getConfigDependencyName());
// Import.
$config_importer->reset()->import();

View file

@ -137,7 +137,7 @@ class EntityAccessControlHandlerTest extends EntityLanguageTestBase {
));
$entity->save();
$translation = $entity->getTranslation('bar');
$translation = $entity->addTranslation('bar');
$this->assertEntityAccess(array(
'view' => TRUE,
), $translation);

View file

@ -95,6 +95,31 @@ class EntityApiTest extends EntityUnitTestBase {
if ($revision_table = $definition->getRevisionTable()) {
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {' . $revision_table . '}')->fetchField(), 'Data table was emptied');
}
// Test deleting a list of entities not indexed by entity id.
$entities = array();
$entity = entity_create($entity_type, array('name' => 'test', 'user_id' => $user1->id()));
$entity->save();
$entities['test'] = $entity;
$entity = entity_create($entity_type, array('name' => 'test2', 'user_id' => $user1->id()));
$entity->save();
$entities['test2'] = $entity;
$controller = \Drupal::entityManager()->getStorage($entity_type);
$controller->delete($entities);
// Verify that entities got deleted.
$all = entity_load_multiple($entity_type);
$this->assertTrue(empty($all), format_string('%entity_type: Deleted all entities.', array('%entity_type' => $entity_type)));
// Verify that all data got deleted from the tables.
$definition = \Drupal::entityManager()->getDefinition($entity_type);
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {' . $definition->getBaseTable() . '}')->fetchField(), 'Base table was emptied');
if ($data_table = $definition->getDataTable()) {
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {' . $data_table . '}')->fetchField(), 'Data table was emptied');
}
if ($revision_table = $definition->getRevisionTable()) {
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {' . $revision_table . '}')->fetchField(), 'Data table was emptied');
}
}
/**

View file

@ -57,8 +57,8 @@ class EntityAutocompleteTest extends EntityUnitTestBase {
$entity_2 = entity_create($this->entityType, array('name' => '10/17/2011'));
$entity_2->save();
// Add another entity that has both a comma and a slash character.
$entity_3 = entity_create($this->entityType, array('name' => 'label with, and / test'));
// Add another entity that has both a comma, a slash and markup.
$entity_3 = entity_create($this->entityType, array('name' => 'label with, and / <em>test</em>'));
$entity_3->save();
// Try to autocomplete a entity label that matches both entities.
@ -84,8 +84,8 @@ class EntityAutocompleteTest extends EntityUnitTestBase {
$data = $this->getAutocompleteResult($input);
$this->assertIdentical($data[0]['label'], Html::escape($entity_2->name->value), 'Autocomplete returned the second matching entity');
// Try to autocomplete a entity label with both a comma and a slash.
$input = '"label with, and / t';
// Try to autocomplete a entity label with both a comma, a slash and markup.
$input = '"label with, and / <em>';
$data = $this->getAutocompleteResult($input);
$n = $entity_3->name->value . ' (3)';
// Entity labels containing commas or quotes must be wrapped in quotes.

View file

@ -29,7 +29,7 @@ abstract class EntityCacheTagsTestBase extends PageCacheTagsTestBase {
*
* @var array
*/
public static $modules = array('entity_reference', 'entity_test', 'field_test');
public static $modules = ['entity_test', 'field_test'];
/**
* The main entity used for testing.

View file

@ -107,7 +107,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Update the %entity_type entity type.', array('%entity_type' => $this->entityManager->getDefinition('entity_test_update')->getLabel())),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected); //, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected); //, 'EntityDefinitionUpdateManager reports the expected change summary.');
// Run the update and ensure the revision table is created.
$this->entityDefinitionUpdateManager->applyUpdates();
@ -146,7 +146,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Create the %field_name field.', array('%field_name' => t('A new base field'))),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->entityDefinitionUpdateManager->applyUpdates();
$this->assertTrue($this->database->schema()->fieldExists('entity_test_update', 'new_base_field'), 'Column created in shared table for new_base_field.');
@ -159,7 +159,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Update the %field_name field.', array('%field_name' => t('A new base field'))),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->entityDefinitionUpdateManager->applyUpdates();
$this->assertTrue($this->database->schema()->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), 'Index created.');
@ -172,7 +172,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Update the %field_name field.', array('%field_name' => t('A new base field'))),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->entityDefinitionUpdateManager->applyUpdates();
$this->assertFalse($this->database->schema()->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), 'Index deleted.');
@ -186,7 +186,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Update the %field_name field.', array('%field_name' => t('A new base field'))),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->entityDefinitionUpdateManager->applyUpdates();
$this->assertFalse($this->database->schema()->fieldExists('entity_test_update', 'new_base_field'), 'Original column deleted in shared table for new_base_field.');
$this->assertTrue($this->database->schema()->fieldExists('entity_test_update', 'new_base_field__value'), 'Value column created in shared table for new_base_field.');
@ -201,7 +201,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Delete the %field_name field.', array('%field_name' => t('A new base field'))),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->entityDefinitionUpdateManager->applyUpdates();
$this->assertFalse($this->database->schema()->fieldExists('entity_test_update', 'new_base_field_value'), 'Value column deleted from shared table for new_base_field.');
$this->assertFalse($this->database->schema()->fieldExists('entity_test_update', 'new_base_field_format'), 'Format column deleted from shared table for new_base_field.');
@ -220,7 +220,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Create the %field_name field.', array('%field_name' => t('A new bundle field'))),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->entityDefinitionUpdateManager->applyUpdates();
$this->assertTrue($this->database->schema()->tableExists('entity_test_update__new_bundle_field'), 'Dedicated table created for new_bundle_field.');
@ -234,7 +234,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Update the %field_name field.', array('%field_name' => t('A new bundle field'))),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->entityDefinitionUpdateManager->applyUpdates();
$this->assertTrue($this->database->schema()->fieldExists('entity_test_update__new_bundle_field', 'new_bundle_field_format'), 'Format column created in dedicated table for new_base_field.');
@ -247,7 +247,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Delete the %field_name field.', array('%field_name' => t('A new bundle field'))),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->entityDefinitionUpdateManager->applyUpdates();
$this->assertFalse($this->database->schema()->tableExists('entity_test_update__new_bundle_field'), 'Dedicated table deleted for new_bundle_field.');
}
@ -489,7 +489,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Update the %entity_type entity type.', array('%entity_type' => $this->entityManager->getDefinition('entity_test_update')->getLabel())),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
// Run the update and ensure the new index is created.
$this->entityDefinitionUpdateManager->applyUpdates();
@ -504,7 +504,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
t('Update the %entity_type entity type.', array('%entity_type' => $this->entityManager->getDefinition('entity_test_update')->getLabel())),
),
);
$this->assertIdentical($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
$this->assertEqual($this->entityDefinitionUpdateManager->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
// Run the update and ensure the index is deleted.
$this->entityDefinitionUpdateManager->applyUpdates();
@ -619,7 +619,7 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
}
/**
* Tests ::applyEntityUpdate() and ::applyFieldUpdate().
* Tests applying single updates.
*/
public function testSingleActionCalls() {
$db_schema = $this->database->schema();
@ -668,9 +668,9 @@ class EntityDefinitionUpdateTest extends EntityUnitTestBase {
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table.");
// Ensure that installing an existing entity type is a no-op.
// Ensure that installing an existing field is a no-op.
$this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), 'Installing an existing entity type is a no-op');
$this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), 'Installing an existing field is a no-op');
// Update an existing field schema.
$this->modifyBaseField();

View file

@ -30,7 +30,7 @@ class EntityFieldTest extends EntityUnitTestBase {
*
* @var array
*/
public static $modules = array('filter', 'text', 'node', 'user');
public static $modules = array('filter', 'text', 'node', 'user', 'field_test');
/**
* @var string
@ -688,12 +688,10 @@ class EntityFieldTest extends EntityUnitTestBase {
->save();
$definition = BaseFieldDefinition::create('entity_reference')
->setLabel('Test entity')
->setSettings(array(
'target_type' => 'node',
'target_bundle' => 'article',
));
->setSetting('target_type', 'node')
->setSetting('handler_settings', ['target_bundles' => ['article' => 'article']]);
$reference_field = \Drupal::TypedDataManager()->create($definition);
$reference = $reference_field->appendItem(array('entity' => $node))->get('entity');
$reference = $reference_field->appendItem(array('entity' => $node));
$violations = $reference->validate();
$this->assertEqual($violations->count(), 1);

View file

@ -70,4 +70,12 @@ class EntityListBuilderTest extends WebTestBase {
$this->assertEqual(['entity_test_view_grants', 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.permissions'], $build['#cache']['contexts']);
}
/**
* Tests if the list cache tags are set.
*/
public function testCacheTags() {
$this->drupalGet('entity_test/list');
$this->assertCacheTag('entity_test_list');
}
}

View file

@ -7,7 +7,7 @@
namespace Drupal\system\Tests\Entity;
use Drupal\Component\Utility\Unicode;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
/**
* Tests the Entity Query relationship API.

View file

@ -130,7 +130,7 @@ class EntityQueryTest extends EntityUnitTestBase {
));
// Make sure the name is set for every language that we might create.
foreach (array('tr', 'pl') as $langcode) {
$entity->getTranslation($langcode)->name = $this->randomMachineName();
$entity->addTranslation($langcode)->name = $this->randomMachineName();
}
foreach (array_reverse(str_split(decbin($i))) as $key => $bit) {
if ($bit) {

View file

@ -12,8 +12,9 @@ use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
@ -105,8 +106,14 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
$this->assertEqual($violations->count(), 1, 'Validation throws a violation.');
$this->assertEqual($violations[0]->getMessage(), t('The referenced entity (%type: %id) does not exist.', array('%type' => $this->referencedEntityType, '%id' => 9999)));
// @todo Implement a test case for invalid bundle references after
// https://www.drupal.org/node/2064191 is fixed.
// Test a non-referenceable bundle.
entity_test_create_bundle('non_referenceable', NULL, $this->referencedEntityType);
$referenced_entity = entity_create($this->referencedEntityType, array('type' => 'non_referenceable'));
$referenced_entity->save();
$entity->{$this->fieldName}->target_id = $referenced_entity->id();
$violations = $entity->{$this->fieldName}->validate();
$this->assertEqual($violations->count(), 1, 'Validation throws a violation.');
$this->assertEqual($violations[0]->getMessage(), t('The entity must be of bundle %bundle.', array('%bundle' => $this->bundle)));
}
/**
@ -170,7 +177,7 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
else {
// A non-existent or NULL entity target id must not return any item in
// the target entities set.
$this->assertFalse(isset($loaded_entities[$delta]));
$this->assertFalse(isset($entities[$delta]));
}
}
}
@ -238,16 +245,15 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
});
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
$entity->user_id[0]->get('entity')->setValue($user);
$entity->user_id[0]->get('target_id')->setValue(-1);
});
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
$entity->user_id->setValue(array('entity' => $user, 'target_id' => -1));
$entity->user_id->setValue(array('entity' => $user, 'target_id' => NULL));
});
try {
$message = 'Setting both the entity and an invalid target_id property fails.';
$this->assertUserAutocreate($entity, function(EntityInterface $entity, UserInterface $user) {
$user->save();
$entity->user_id->setValue(array('entity' => $user, 'target_id' => -1));
$entity->user_id->setValue(array('entity' => $user, 'target_id' => $this->generateRandomEntityId()));
});
$this->fail($message);
}
@ -273,16 +279,15 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
});
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
$entity->user_role[0]->get('entity')->setValue($role);
$entity->user_role[0]->get('target_id')->setValue(-1);
});
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
$entity->user_role->setValue(array('entity' => $role, 'target_id' => -1));
$entity->user_role->setValue(array('entity' => $role, 'target_id' => NULL));
});
try {
$message = 'Setting both the entity and an invalid target_id property fails.';
$this->assertUserRoleAutocreate($entity, function(EntityInterface $entity, RoleInterface $role) {
$role->save();
$entity->user_role->setValue(array('entity' => $role, 'target_id' => -1));
$entity->user_role->setValue(array('entity' => $role, 'target_id' => $this->generateRandomEntityId(TRUE)));
});
$this->fail($message);
}
@ -402,4 +407,35 @@ class EntityReferenceFieldTest extends EntityUnitTestBase {
}
}
/**
* Tests the dependencies entity reference fields are created with.
*/
public function testEntityReferenceFieldDependencies() {
$field_name = 'user_reference_field';
$entity_type = 'entity_test';
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'type' => 'entity_reference',
'entity_type' => $entity_type,
'settings' => [
'target_type' => 'user',
],
]);
$field_storage->save();
$this->assertEqual(['module' => ['entity_test', 'user']], $field_storage->getDependencies());
$field = FieldConfig::create([
'field_name' => $field_name,
'entity_type' => $entity_type,
'bundle' => 'entity_test',
'label' => $field_name,
'settings' => [
'handler' => 'default',
],
]);
$field->save();
$this->assertEqual(['config' => ['field.storage.entity_test.user_reference_field'], 'module' => ['entity_test']], $field->getDependencies());
}
}

View file

@ -77,7 +77,7 @@ class EntityReferenceSelectionAccessTest extends WebTestBase {
'target_type' => 'node',
'handler' => 'default',
'handler_settings' => array(
'target_bundles' => array(),
'target_bundles' => NULL,
),
);
@ -203,7 +203,7 @@ class EntityReferenceSelectionAccessTest extends WebTestBase {
'target_type' => 'user',
'handler' => 'default',
'handler_settings' => array(
'target_bundles' => array(),
'target_bundles' => NULL,
'include_anonymous' => TRUE,
),
);
@ -345,7 +345,7 @@ class EntityReferenceSelectionAccessTest extends WebTestBase {
'target_type' => 'comment',
'handler' => 'default',
'handler_settings' => array(
'target_bundles' => array(),
'target_bundles' => NULL,
),
);

View file

@ -100,7 +100,7 @@ class EntityReferenceSelectionSortTest extends EntityUnitTestBase {
'target_type' => 'node',
'handler' => 'default',
'handler_settings' => array(
'target_bundles' => array(),
'target_bundles' => NULL,
// Add sorting.
'sort' => array(
'field' => 'field_text.value',

View file

@ -57,4 +57,39 @@ class EntityRevisionTranslationTest extends EntityUnitTestBase {
$this->assertTrue($this->reloadEntity($entity)->getRevisionId() > $old_rev_id, 'The entity from the storage has a newer revision id.');
}
/**
* Tests if the translation object has the right revision id after new revision.
*/
public function testRevertRevisionAfterTranslation() {
$user = $this->createUser();
$storage = $this->entityManager->getStorage('entity_test_mulrev');
// Create a test entity.
$entity = EntityTestMulRev::create([
'name' => $this->randomString(),
'user_id' => $user->id(),
'language' => 'en',
]);
$entity->save();
$old_rev_id = $entity->getRevisionId();
$translation = $entity->addTranslation('de');
$translation->setNewRevision();
$translation->save();
$entity = $this->reloadEntity($entity);
$this->assertTrue($entity->hasTranslation('de'));
$entity = $storage->loadRevision($old_rev_id);
$entity->setNewRevision();
$entity->isDefaultRevision(TRUE);
$entity->save();
$entity = $this->reloadEntity($entity);
$this->assertFalse($entity->hasTranslation('de'));
}
}

View file

@ -139,4 +139,59 @@ class EntitySchemaTest extends EntityUnitTestBase {
}
}
/**
* Tests fields from an uninstalled module are removed from the schema.
*/
public function testCleanUpStorageDefinition() {
// Find all the entity types provided by the entity_test module and install
// the schema for them.
$entity_type_ids = [];
$entities = \Drupal::entityManager()->getDefinitions();
foreach ($entities as $entity_type_id => $definition) {
if ($definition->getProvider() == 'entity_test') {
$this->installEntitySchema($entity_type_id);
$entity_type_ids[] = $entity_type_id;
};
}
// Get a list of all the entities in the schema.
$key_value_store = \Drupal::keyValue('entity.storage_schema.sql');
$schema = $key_value_store->getAll();
// Count the storage definitions provided by the entity_test module, so that
// after uninstall we can be sure there were some to be deleted.
$entity_type_id_count = 0;
foreach (array_keys($schema) as $storage_definition_name) {
list($entity_type_id, ,) = explode('.', $storage_definition_name);
if (in_array($entity_type_id, $entity_type_ids)) {
$entity_type_id_count++;
}
}
// Ensure that there are storage definitions from the entity_test module.
$this->assertNotEqual($entity_type_id_count, 0, 'There are storage definitions provided by the entity_test module in the schema.');
// Uninstall the entity_test module.
$this->container->get('module_installer')->uninstall(array('entity_test'));
// Get a list of all the entities in the schema.
$key_value_store = \Drupal::keyValue('entity.storage_schema.sql');
$schema = $key_value_store->getAll();
// Count the storage definitions that come from entity types provided by
// the entity_test module.
$entity_type_id_count = 0;
foreach (array_keys($schema) as $storage_definition_name) {
list($entity_type_id, ,) = explode('.', $storage_definition_name);
if (in_array($entity_type_id, $entity_type_ids)) {
$entity_type_id_count++;
}
}
// Ensure that all storage definitions have been removed from the schema.
$this->assertEqual($entity_type_id_count, 0, 'After uninstalling entity_test module the schema should not contains fields from entities provided by the module.');
}
}

View file

@ -106,9 +106,10 @@ class EntityTranslationFormTest extends WebTestBase {
// Create a body translation and check the form language.
$langcode2 = $this->langcodes[1];
$node->getTranslation($langcode2)->title->value = $this->randomString();
$node->getTranslation($langcode2)->body->value = $this->randomMachineName(16);
$node->getTranslation($langcode2)->setOwnerId($web_user->id());
$translation = $node->addTranslation($langcode2);
$translation->title->value = $this->randomString();
$translation->body->value = $this->randomMachineName(16);
$translation->setOwnerId($web_user->id());
$node->save();
$this->drupalGet($langcode2 . '/node/' . $node->id() . '/edit');
$form_langcode = \Drupal::state()->get('entity_test.form_langcode');

View file

@ -8,7 +8,6 @@
namespace Drupal\system\Tests\Entity;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_test\Entity\EntityTestMulRev;
use Drupal\language\Entity\ConfigurableLanguage;
@ -58,18 +57,15 @@ class EntityTranslationTest extends EntityLanguageTestBase {
$this->assertEqual($field->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
$this->assertEqual($field->getLangcode(), LanguageInterface::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Set the value in a certain language. As the entity is not
// language-specific it should use the default language and so ignore the
// specified language.
$entity->getTranslation($this->langcodes[1])->set($this->fieldName, array(0 => array('value' => 'default value2')));
$this->assertEqual($entity->get($this->fieldName)->value, 'default value2', format_string('%entity_type: Untranslated value updated.', array('%entity_type' => $entity_type)));
$this->assertFalse($entity->getTranslationLanguages(FALSE), format_string('%entity_type: No translations are available', array('%entity_type' => $entity_type)));
// Test getting a field value using a specific language for a not
// language-specific entity.
$field = $entity->getTranslation($this->langcodes[1])->get($this->fieldName);
$this->assertEqual($field->value, 'default value2', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
$this->assertEqual($field->getLangcode(), LanguageInterface::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Try to get add a translation to language neutral entity.
$message = 'Adding a translation to a language-neutral entity results in an error.';
try {
$entity->addTranslation($this->langcodes[1]);
$this->fail($message);
}
catch (\InvalidArgumentException $e) {
$this->pass($message);
}
// Now, make the entity language-specific by assigning a language and test
// translating it.
@ -87,7 +83,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
$this->assertEqual($field->getLangcode(), $default_langcode, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Set a translation.
$entity->getTranslation($this->langcodes[1])->set($this->fieldName, array(0 => array('value' => 'translation 1')));
$entity->addTranslation($this->langcodes[1])->set($this->fieldName, array(0 => array('value' => 'translation 1')));
$field = $entity->getTranslation($this->langcodes[1])->{$this->fieldName};
$this->assertEqual($field->value, 'translation 1', format_string('%entity_type: Translated value set.', array('%entity_type' => $entity_type)));
$this->assertEqual($field->getLangcode(), $this->langcodes[1], format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
@ -100,16 +96,27 @@ class EntityTranslationTest extends EntityLanguageTestBase {
$translations[$this->langcodes[1]] = \Drupal::languageManager()->getLanguage($this->langcodes[1]);
$this->assertEqual($entity->getTranslationLanguages(FALSE), $translations, 'Translations retrieved.');
// Try to get a not available translation.
$this->assertNull($entity->getTranslation($this->langcodes[2])->get($this->fieldName)->value, format_string('%entity_type: A translation that is not available is NULL.', array('%entity_type' => $entity_type)));
// Try to get a value using an invalid language code.
// Try to get a value using a language code for a non-existing translation.
$message = 'Getting a non existing translation results in an error.';
try {
$entity->getTranslation('invalid')->get($this->fieldName)->value;
$this->fail('Getting a translation for an invalid language is NULL.');
$entity->getTranslation($this->langcodes[2])->get($this->fieldName)->value;
$this->fail($message);
}
catch (\InvalidArgumentException $e) {
$this->pass('A translation for an invalid language is NULL.');
$this->pass($message);
}
// Try to get a not available translation.
$this->assertNull($entity->addTranslation($this->langcodes[2])->get($this->fieldName)->value, format_string('%entity_type: A translation that is not available is NULL.', array('%entity_type' => $entity_type)));
// Try to get a value using an invalid language code.
$message = 'Getting an invalid translation results in an error.';
try {
$entity->getTranslation('invalid')->get($this->fieldName)->value;
$this->fail($message);
}
catch (\InvalidArgumentException $e) {
$this->pass($message);
}
// Try to set a value using an invalid language code.
@ -164,10 +171,12 @@ class EntityTranslationTest extends EntityLanguageTestBase {
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation(LanguageInterface::LANGCODE_DEFAULT)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation($langcode)->get('name');
$translation = $entity->getTranslation(LanguageInterface::LANGCODE_DEFAULT);
$field = $translation->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to neutral language.', array('%entity_type' => $entity_type)));
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to neutral language.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $translation->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to neutral language.', array('%entity_type' => $entity_type)));
$field = $entity->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
@ -184,16 +193,6 @@ class EntityTranslationTest extends EntityLanguageTestBase {
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
// Translatable properties on a translatable entity should use default
// language if LanguageInterface::LANGCODE_NOT_SPECIFIED is passed.
$field = $entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to the default language.', array('%entity_type' => $entity_type)));
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to the default language.', array('%entity_type' => $entity_type)));
$field = $entity->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
$this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->get('user_id')->target_id, format_string('%entity_type: The entity author can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
// Create property translations.
$properties = array();
@ -211,7 +210,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
'user_id' => array(0 => $uid),
);
}
$translation = $entity->getTranslation($langcode);
$translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode);
foreach ($properties[$langcode] as $field_name => $values) {
$translation->set($field_name, $values);
}
@ -328,7 +327,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
// Verify that we obtain the entity object itself when we attempt to
// retrieve a translation referring to it.
$translation = $entity->getTranslation($langcode);
$translation = $entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED);
$this->assertIdentical($entity, $translation, 'The translation object corresponding to a non-default language is the entity object itself when the entity is language-neutral.');
$entity->{$langcode_key}->value = $default_langcode;
$translation = $entity->getTranslation($default_langcode);
@ -337,6 +336,17 @@ class EntityTranslationTest extends EntityLanguageTestBase {
$this->assertIdentical($entity, $translation, 'The translation object corresponding to the default language (implicit) is the entity object itself.');
$this->assertTrue($entity->{$default_langcode_key}->value, 'The translation object is the default one.');
// Verify that trying to retrieve a translation for a locked language when
// the entity is language-aware causes an exception to be thrown.
$message = 'A language-neutral translation cannot be retrieved.';
try {
$entity->getTranslation(LanguageInterface::LANGCODE_NOT_SPECIFIED);
$this->fail($message);
}
catch (\LogicException $e) {
$this->pass($message);
}
// Create a translation and verify that the translation object and the
// original object behave independently.
$name = $default_langcode . '_' . $this->randomMachineName();
@ -416,7 +426,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
// new translation object can be obtained also by just specifying a valid
// language.
$langcode2 = $this->langcodes[2];
$translation = $entity->getTranslation($langcode2);
$translation = $entity->addTranslation($langcode2);
$value = $entity !== $translation && $translation->language()->getId() == $langcode2 && $entity->hasTranslation($langcode2);
$this->assertTrue($value, 'A new translation object can be obtained also by specifying a valid language.');
$this->assertEqual($entity->language()->getId(), $default_langcode, 'The original language has been preserved.');
@ -526,7 +536,7 @@ class EntityTranslationTest extends EntityLanguageTestBase {
// 'description' field.
$entity = $this->entityManager
->getStorage('entity_test_mul_default_value')
->create(array('name' => $this->randomMachineName(), 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED));
->create(['name' => $this->randomMachineName(), 'langcode' => $langcode]);
$translation = $entity->addTranslation($langcode2);
$expected = array(
array(

View file

@ -20,7 +20,7 @@ abstract class EntityUnitTestBase extends KernelTestBase {
*
* @var array
*/
public static $modules = array('user', 'system', 'field', 'text', 'filter', 'entity_test', 'entity_reference');
public static $modules = ['user', 'system', 'field', 'text', 'filter', 'entity_test'];
/**
* The entity manager service.

View file

@ -8,7 +8,7 @@
namespace Drupal\system\Tests\Entity;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Core\Cache\Cache;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
@ -22,13 +22,6 @@ class EntityViewBuilderTest extends EntityUnitTestBase {
use EntityReferenceTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('entity_reference');
/**
* {@inheritdoc}
*/
@ -49,6 +42,7 @@ class EntityViewBuilderTest extends EntityUnitTestBase {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
$cache_contexts_manager = \Drupal::service("cache_contexts_manager");
$cache = \Drupal::cache();
// Force a request via GET so we can get drupal_render() cache working.
$request = \Drupal::request();
@ -78,8 +72,10 @@ class EntityViewBuilderTest extends EntityUnitTestBase {
$this->assertTrue($this->container->get('cache.' . $bin)->get($cid), 'The entity render element has been cached.');
// Re-save the entity and check that the cache entry has been deleted.
$cache->set('kittens', 'Kitten data', Cache::PERMANENT, $build['#cache']['tags']);
$entity_test->save();
$this->assertFalse($this->container->get('cache.' . $bin)->get($cid), 'The entity render cache has been cleared when the entity was saved.');
$this->assertFalse($cache->get('kittens'), 'The entity saving has invalidated cache tags.');
// Rebuild the render array (creating a new cache entry in the process) and
// delete the entity to check the cache entry is deleted.

View file

@ -47,7 +47,7 @@ class EntityViewControllerTest extends WebTestBase {
*/
function testEntityViewController() {
$get_label_markup = function($label) {
return '<h1>
return '<h1 class="page-title">
<div class="field field--name-name field--type-string field--label-hidden field__item">' . $label . '</div>
</h1>';
};

View file

@ -22,7 +22,7 @@ class FieldAccessTest extends KernelTestBase {
*
* @var array
*/
public static $modules = array('entity_test', 'field', 'system', 'text', 'filter', 'user', 'entity_reference');
public static $modules = ['entity_test', 'field', 'system', 'text', 'filter', 'user'];
/**
* Holds the currently active global user ID that initiated the test run.

View file

@ -469,35 +469,6 @@ class FieldSqlStorageTest extends EntityUnitTestBase {
$this->assertEqual($schema['foreign keys'][$foreign_key_name]['columns'][$foreign_key_name], 'id', 'Foreign key column name modified after update');
}
/**
* Tests reacting to a bundle being renamed.
*/
function testFieldSqlStorageBundleRename() {
$entity_type = $bundle = 'entity_test_rev';
$field_name = $this->fieldStorage->getName();
// Create an entity.
$value = mt_rand(1, 127);
$entity = entity_create($entity_type, array(
'type' => $bundle,
$field_name => $value,
));
$entity->save();
// Rename the bundle.
$bundle_new = $bundle . '_renamed';
entity_test_rename_bundle($bundle, $bundle_new, $entity_type);
// Check that the 'bundle' column has been updated in storage.
$row = db_select($this->table, 't')
->fields('t', array('bundle', $field_name . '_value'))
->condition('entity_id', $entity->id())
->execute()
->fetch();
$this->assertEqual($row->bundle, $bundle_new);
$this->assertEqual($row->{$field_name . '_value'}, $value);
}
/**
* Tests table name generation.
*/

View file

@ -0,0 +1,26 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Entity\Update\LangcodeToAsciiUpdateFilledTest.
*/
namespace Drupal\system\Tests\Entity\Update;
/**
* Runs LangcodeToAsciiUpdateTest with a dump filled with content.
*
* @group Entity
*/
class LangcodeToAsciiUpdateFilledTest extends LangcodeToAsciiUpdateTest {
/**
* {@inheritdoc}
*/
public function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.filled.standard.php.gz',
];
}
}

View file

@ -0,0 +1,79 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Entity\Update\LangcodeToAsciiUpdateTest.
*/
namespace Drupal\system\Tests\Entity\Update;
use Drupal\Core\Database\Database;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests that the entity langcode fields have been updated to varchar_ascii.
*
* @group Entity
*/
class LangcodeToAsciiUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
public function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../tests/fixtures/update/drupal-8.bare.standard.php.gz',
];
}
/**
* Tests that the column collation has been updated on MySQL.
*/
public function testLangcodeColumnCollation() {
// Only testable on MySQL.
// @see https://www.drupal.org/node/301038
if (Database::getConnection()->databaseType() !== 'mysql') {
$this->pass('This test can only run on MySQL');
return;
}
// Check a few different tables.
$tables = [
'node_field_data' => ['langcode'],
'users_field_data' => ['langcode', 'preferred_langcode', 'preferred_admin_langcode'],
];
foreach ($tables as $table => $columns) {
foreach ($columns as $column) {
$this->assertEqual('utf8mb4_general_ci', $this->getColumnCollation($table, $column), 'Found correct starting collation for ' . $table . '.' . $column);
}
}
// Apply updates.
$this->runUpdates();
foreach ($tables as $table => $columns) {
foreach ($columns as $column) {
$this->assertEqual('ascii_general_ci', $this->getColumnCollation($table, $column), 'Found correct updated collation for ' . $table . '.' . $column);
}
}
}
/**
* Determine the column collation.
*
* @param string $table
* The table name.
* @param string $column
* The column name.
*/
protected function getColumnCollation($table, $column) {
$query = Database::getConnection()->query("SHOW FULL COLUMNS FROM {" . $table . "}");
while ($row = $query->fetchAssoc()) {
if ($row['Field'] === $column) {
return $row['Collation'];
}
}
$this->fail('No collation found for ' . $table . '.' . $column);
}
}

View file

@ -68,9 +68,9 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
$this->assertEqual(count($entity->user_id), 1);
$this->assertEqual($entity->user_id->target_id, $user_ids[0]);
// Make 'user_id' multiple by running updates.
// Make 'user_id' multiple by applying updates.
$this->enableUpdates('entity_test', 'entity_definition_updates', 8001);
$this->runUpdates();
$this->applyUpdates();
// Check that data was correctly migrated.
$entity = $this->reloadEntity($entity);
@ -85,14 +85,21 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
$this->assertEqual($entity->user_id[0]->target_id, $user_ids[0]);
$this->assertEqual($entity->user_id[1]->target_id, $user_ids[1]);
// Make 'user_id' single again by running updates.
// Make 'user_id' single again by applying updates.
$this->enableUpdates('entity_test', 'entity_definition_updates', 8002);
$this->runUpdates();
$this->applyUpdates();
// Check that data was correctly migrated/dropped.
$entity = $this->reloadEntity($entity);
$this->assertEqual(count($entity->user_id), 1);
$this->assertEqual($entity->user_id->target_id, $user_ids[0]);
// Check that only a single value is stored for 'user_id' again.
$entity->user_id = $user_ids;
$entity->save();
$entity = $this->reloadEntity($entity);
$this->assertEqual(count($entity->user_id), 1);
$this->assertEqual($entity->user_id[0]->target_id, $user_ids[0]);
}
/**
@ -109,9 +116,9 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
$this->assertEqual(count($entity->user_id), 1);
$this->assertEqual($entity->user_id->target_id, $user_ids[0]);
// Make 'user_id' multiple and then single again by running updates.
// Make 'user_id' multiple and then single again by applying updates.
$this->enableUpdates('entity_test', 'entity_definition_updates', 8002);
$this->runUpdates();
$this->applyUpdates();
// Check that data was correctly migrated back and forth.
$entity = $this->reloadEntity($entity);
@ -154,8 +161,8 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
$this->assertRaw('Out of date');
$this->assertNoRaw('Mismatch detected');
// Run db updates and check that entity updates were not applied.
$this->runUpdates();
// Apply db updates and check that entity updates were not applied.
$this->applyUpdates();
$this->drupalGet('admin/reports/status');
$this->assertNoRaw('Out of date');
$this->assertRaw('Mismatch detected');
@ -180,7 +187,7 @@ class UpdateApiEntityDefinitionUpdateTest extends WebTestBase {
// entity updates were not applied even when no data exists.
$entity->delete();
$this->enableUpdates('entity_test', 'status_report', 8002);
$this->runUpdates();
$this->applyUpdates();
$this->drupalGet('admin/reports/status');
$this->assertNoRaw('Out of date');
$this->assertRaw('Mismatch detected');

View file

@ -0,0 +1,120 @@
<?php
/**
* @file
* Contains Drupal\system\Tests\Field\FieldSettingsTest.
*/
namespace Drupal\system\Tests\Field;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\system\Tests\Entity\EntityUnitTestBase;
/**
* Tests field settings methods on field definition structures.
*
* @group Field
*/
class FieldSettingsTest extends EntityUnitTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('field', 'field_test');
/**
* @covers \Drupal\Core\Field\BaseFieldDefinition::getSettings()
* @covers \Drupal\Core\Field\BaseFieldDefinition::setSettings()
*/
public function testBaseFieldSettings() {
$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->assertEqual($base_field->getSettings(), $expected_settings);
// Change one single setting using setSettings(), and check that the other
// expected settings are still present.
$expected_settings['test_field_setting'] = 'another test string';
$base_field->setSettings(['test_field_setting' => $expected_settings['test_field_setting']]);
$this->assertEqual($base_field->getSettings(), $expected_settings);
}
/**
* @covers \Drupal\field\Entity\FieldStorageConfig::getSettings()
* @covers \Drupal\field\Entity\FieldStorageConfig::setSettings()
*/
public function testConfigurableFieldStorageSettings() {
$field_storage = FieldStorageConfig::create([
'field_name' => 'test_field',
'entity_type' => 'entity_test',
'type' => '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',
];
$this->assertEqual($field_storage->getSettings(), $expected_settings);
// Change one single setting using setSettings(), and check that the other
// expected settings are still present.
$expected_settings['test_field_storage_setting'] = 'another test string';
$field_storage->setSettings(['test_field_storage_setting' => $expected_settings['test_field_storage_setting']]);
$this->assertEqual($field_storage->getSettings(), $expected_settings);
}
/**
* @covers \Drupal\field\Entity\FieldStorageConfig::getSettings()
* @covers \Drupal\field\Entity\FieldStorageConfig::setSettings()
*/
public function testConfigurableFieldSettings() {
$field_storage = FieldStorageConfig::create([
'field_name' => 'test_field',
'entity_type' => 'entity_test',
'type' => 'test_field'
]);
$field = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'entity_test'
]);
// Note: FieldConfig does not populate default settings until the config
// is saved.
// @todo Remove once https://www.drupal.org/node/2327883 is fixed.
$field->save();
// Check that the default settings have been populated. Note: getSettings()
// returns both storage and field settings.
$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',
'field_setting_from_config_data' => TRUE,
];
$this->assertEqual($field->getSettings(), $expected_settings);
// Change one single setting using setSettings(), and check that the other
// expected settings are still present.
$expected_settings['test_field_setting'] = 'another test string';
$field->setSettings(['test_field_setting' => $expected_settings['test_field_setting']]);
$this->assertEqual($field->getSettings(), $expected_settings);
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\File\FileSaveHtaccessLoggingTest.
*/
namespace Drupal\system\Tests\File;
use Drupal\Component\PhpStorage\FileStorage;
use Drupal\simpletest\WebTestBase;
/**
* Tests the log message added by file_save_htacess().
*
* @group File
*/
class FileSaveHtaccessLoggingTest extends WebTestBase {
protected static $modules = ['dblog'];
/**
* Tests file_save_htaccess().
*/
function testHtaccessSave() {
// Prepare test directories.
$private = $this->publicFilesDirectory . '/test/private';
// Verify that file_save_htaccess() returns FALSE if .htaccess cannot be
// written and writes a correctly formatted message to the error log. Set
// $private to TRUE so all possible .htaccess lines are written.
$this->assertFalse(file_save_htaccess($private, TRUE));
$this->drupalLogin($this->rootUser);
$this->drupalGet('admin/reports/dblog');
$this->clickLink("Security warning: Couldn't write .htaccess file. Please…");
$lines = FileStorage::htaccessLines(TRUE);
foreach (array_filter(explode("\n", $lines)) as $line) {
$this->assertEscaped($line);
}
}
}

View file

@ -44,7 +44,7 @@ class NameMungingTest extends FileTestBase {
$this->config('system.file')->set('allow_insecure_uploads', 0)->save();
$munged_name = file_munge_filename($this->name, '', TRUE);
$messages = drupal_get_messages();
$this->assertTrue(in_array(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $munged_name)), $messages['status']), 'Alert properly set when a file is renamed.');
$this->assertTrue(in_array(strtr('For security reasons, your upload has been renamed to <em class="placeholder">%filename</em>.', array('%filename' => $munged_name)), $messages['status']), 'Alert properly set when a file is renamed.');
$this->assertNotEqual($munged_name, $this->name, format_string('The new filename (%munged) has been modified from the original (%original)', array('%munged' => $munged_name, '%original' => $this->name)));
}

View file

@ -62,6 +62,12 @@ class ElementTest extends WebTestBase {
}
}
// Verify that the choices are admin filtered as expected.
$this->assertRaw("<em>Special Char</em>alert('checkboxes');");
$this->assertRaw("<em>Special Char</em>alert('radios');");
$this->assertRaw('<em>Bar - checkboxes</em>');
$this->assertRaw('<em>Bar - radios</em>');
// Enable customized option sub-elements.
$this->drupalGet('form-test/checkboxes-radios/customize');
@ -160,4 +166,12 @@ class ElementTest extends WebTestBase {
$this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion');
}
/**
* Tests form element error messages.
*/
public function testFormElementErrors() {
$this->drupalPostForm('form_test/details-form', [], 'Submit');
$this->assertText('I am an error on the details element.');
}
}

View file

@ -71,7 +71,7 @@ class ElementsLabelsTest extends WebTestBase {
$elements = $this->xpath('//label[@for="edit-form-textfield-test-title-no-show"]');
$this->assertFalse(isset($elements[0]), 'No label tag when title set not to display.');
$elements = $this->xpath('//div[contains(@class, "form-item-form-textfield-test-title-invisible") and contains(@class, "form-no-label")]');
$elements = $this->xpath('//div[contains(@class, "js-form-item-form-textfield-test-title-invisible") and contains(@class, "form-no-label")]');
$this->assertTrue(isset($elements[0]), 'Field class is form-no-label when there is no label.');
// Check #field_prefix and #field_suffix placement.
@ -82,10 +82,10 @@ class ElementsLabelsTest extends WebTestBase {
$this->assertTrue(isset($elements[0]), 'Properly places the #field_suffix element immediately after the form field.');
// Check #prefix and #suffix placement.
$elements = $this->xpath('//div[@id="form-test-textfield-title-prefix"]/following-sibling::div[contains(@class, \'form-item-form-textfield-test-title\')]');
$elements = $this->xpath('//div[@id="form-test-textfield-title-prefix"]/following-sibling::div[contains(@class, \'js-form-item-form-textfield-test-title\')]');
$this->assertTrue(isset($elements[0]), 'Properly places the #prefix element before the form item.');
$elements = $this->xpath('//div[@id="form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'form-item-form-textfield-test-title\')]');
$elements = $this->xpath('//div[@id="form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'js-form-item-form-textfield-test-title\')]');
$this->assertTrue(isset($elements[0]), 'Properly places the #suffix element before the form item.');
// Check title attribute for radios and checkboxes.

View file

@ -35,7 +35,7 @@ class EmailTest extends WebTestBase {
$edit['email_required'] = ' ';
$this->drupalPostForm('form-test/email', $edit, 'Submit');
$this->assertRaw(t('The email address %mail is not valid.', array('%mail' => 'invalid')));
$this->assertRaw(t('!name field is required.', array('!name' => 'Address')));
$this->assertRaw(t('@name field is required.', array('@name' => 'Address')));
$edit = array();
$edit['email_required'] = ' foo.bar@example.com ';

View file

@ -144,7 +144,7 @@ class FormTest extends WebTestBase {
// Select elements are going to have validation errors with empty
// input, since those are illegal choices. Just make sure the
// error is not "field is required".
$this->assertTrue((empty($errors[$element]) || strpos('field is required', $errors[$element]) === FALSE), "Optional '$type' field '$element' is not treated as a required element");
$this->assertTrue((empty($errors[$element]) || strpos('field is required', (string) $errors[$element]) === FALSE), "Optional '$type' field '$element' is not treated as a required element");
}
else {
// Make sure there is *no* form error for this element.
@ -185,12 +185,12 @@ class FormTest extends WebTestBase {
$expected[] = $form[$key]['#form_test_required_error'];
}
else {
$expected[] = t('!name field is required.', array('!name' => $form[$key]['#title']));
$expected[] = t('@name field is required.', array('@name' => $form[$key]['#title']));
}
}
// Check the page for error messages.
$errors = $this->xpath('//div[contains(@class, "form-item--error-message")]//strong');
$errors = $this->xpath('//div[contains(@class, "error")]//li');
foreach ($errors as $error) {
$expected_key = array_search($error[0], $expected);
// If the error message is not one of the expected messages, fail.
@ -294,6 +294,18 @@ class FormTest extends WebTestBase {
$this->assertFieldByName('url', $edit['url']);
}
/**
* CSRF tokens for GET forms should not be added by default.
*/
public function testGetFormsCsrfToken() {
// We need to be logged in to have CSRF tokens.
$account = $this->createUser();
$this->drupalLogin($account);
$this->drupalGet(Url::fromRoute('form_test.get_form'));
$this->assertNoRaw('form_token');
}
/**
* Tests validation for required textfield element without title.
*
@ -335,7 +347,7 @@ class FormTest extends WebTestBase {
// First, try to submit without the required checkbox.
$edit = array();
$this->drupalPostForm('form-test/checkbox', $edit, t('Submit'));
$this->assertRaw(t('!name field is required.', array('!name' => 'required_checkbox')), 'A required checkbox is actually mandatory');
$this->assertRaw(t('@name field is required.', array('@name' => 'required_checkbox')), 'A required checkbox is actually mandatory');
// Now try to submit the form correctly.
$values = Json::decode($this->drupalPostForm(NULL, array('required_checkbox' => 1), t('Submit')));
@ -361,9 +373,12 @@ class FormTest extends WebTestBase {
*/
function testSelect() {
$form = \Drupal::formBuilder()->getForm('Drupal\form_test\Form\FormTestSelectForm');
$error = '!name field is required.';
$this->drupalGet('form-test/select');
// Verify that the options are escaped as expected.
$this->assertEscaped('<strong>four</strong>');
$this->assertNoRaw('<strong>four</strong>');
// Posting without any values should throw validation errors.
$this->drupalPostForm(NULL, array(), 'Submit');
$no_errors = array(
@ -379,7 +394,7 @@ class FormTest extends WebTestBase {
'multiple_no_default',
);
foreach ($no_errors as $key) {
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
}
$expected_errors = array(
@ -390,7 +405,7 @@ class FormTest extends WebTestBase {
'multiple_no_default_required',
);
foreach ($expected_errors as $key) {
$this->assertText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
$this->assertText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
}
// Post values for required fields.

View file

@ -42,13 +42,18 @@ class ModulesListFormWebTest extends WebTestBase {
$this->assertResponse('200');
// Check that system_test's configure link was rendered correctly.
$this->assertFieldByXPath("//a[contains(@href, '/system-test/configure/bar') and @title='Bar.bar']");
$this->assertFieldByXPath("//a[contains(@href, '/system-test/configure/bar') and text()='Configure ']/span[contains(@class, 'visually-hidden') and text()='the System test module']");
// Check that system_test's permissions link was rendered correctly.
$this->assertFieldByXPath("//a[contains(@href, '/admin/people/permissions#module-system_test') and @title='Configure permissions']");
// Check that system_test's help link was rendered correctly.
$this->assertFieldByXPath("//a[contains(@href, '/admin/help/system_test') and @title='Help']");
// Ensure that the Testing module's machine name is printed. Testing module
// is used because its machine name is different than its human readable
// name.
$this->assertText('simpletest');
}
}

View file

@ -109,7 +109,7 @@ class RebuildTest extends WebTestBase {
// Ensure that the form contains two items in the multi-valued field, so we
// know we're testing a form that was correctly retrieved from cache.
$this->assert(count($this->xpath('//form[contains(@id, "node-page-form")]//div[contains(@class, "form-item-field-ajax-test")]//input[@type="text"]')) == 2, 'Form retained its state from cache.');
$this->assert(count($this->xpath('//form[contains(@id, "node-page-form")]//div[contains(@class, "js-form-item-field-ajax-test")]//input[@type="text"]')) == 2, 'Form retained its state from cache.');
// Ensure that the form's action is correct.
$forms = $this->xpath('//form[contains(@class, "node-page-form")]');

View file

@ -19,20 +19,8 @@ use Drupal\simpletest\KernelTestBase;
*/
class TriggeringElementProgrammedUnitTest extends KernelTestBase implements FormInterface {
/**
* {@inheritdoc}
*/
public static $modules = array('system');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installSchema('system', ['router']);
\Drupal::service('router.builder')->rebuild();
}
/**
* {@inheritdoc}
*/

View file

@ -35,7 +35,7 @@ class UrlTest extends WebTestBase {
$edit['url_required'] = ' ';
$this->drupalPostForm('form-test/url', $edit, 'Submit');
$this->assertRaw(t('The URL %url is not valid.', array('%url' => 'http://')));
$this->assertRaw(t('!name field is required.', array('!name' => 'Required URL')));
$this->assertRaw(t('@name field is required.', array('@name' => 'Required URL')));
$edit = array();
$edit['url'] = "\n";

View file

@ -8,7 +8,6 @@
namespace Drupal\system\Tests\Form;
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
/**
@ -75,6 +74,14 @@ class ValidationTest extends WebTestBase {
$this->assertText('The form has become outdated. Copy any unsaved work in the form below');
}
/**
* Tests that a form with a disabled CSRF token can be validated.
*/
function testDisabledToken() {
$this->drupalPostForm('form-test/validate-no-token', [], 'Save');
$this->assertText('The form_test_validate_no_token form has been submitted successfully.');
}
/**
* Tests partial form validation through #limit_validation_errors.
*/
@ -110,19 +117,19 @@ class ValidationTest extends WebTestBase {
// validated, but the #element_validate handler for the 'test' field
// is triggered.
$this->drupalPostForm($path, $edit, t('Partial validate'));
$this->assertNoText(t('!name field is required.', array('!name' => 'Title')));
$this->assertNoText(t('@name field is required.', array('@name' => 'Title')));
$this->assertText('Test element is invalid');
// Edge case of #limit_validation_errors containing numeric indexes: same
// thing with the 'Partial validate (numeric index)' button and the
// 'test_numeric_index' field.
$this->drupalPostForm($path, $edit, t('Partial validate (numeric index)'));
$this->assertNoText(t('!name field is required.', array('!name' => 'Title')));
$this->assertNoText(t('@name field is required.', array('@name' => 'Title')));
$this->assertText('Test (numeric index) element is invalid');
// Ensure something like 'foobar' isn't considered "inside" 'foo'.
$this->drupalPostForm($path, $edit, t('Partial validate (substring)'));
$this->assertNoText(t('!name field is required.', array('!name' => 'Title')));
$this->assertNoText(t('@name field is required.', array('@name' => 'Title')));
$this->assertText('Test (substring) foo element is invalid');
// Ensure not validated values are not available to submit handlers.
@ -132,7 +139,7 @@ class ValidationTest extends WebTestBase {
// Now test full form validation and ensure that the #element_validate
// handler is still triggered.
$this->drupalPostForm($path, $edit, t('Full validate'));
$this->assertText(t('!name field is required.', array('!name' => 'Title')));
$this->assertText(t('@name field is required.', array('@name' => 'Title')));
$this->assertText('Test element is invalid');
}
@ -207,33 +214,17 @@ class ValidationTest extends WebTestBase {
$edit = array();
$this->drupalPostForm('form-test/validate-required', $edit, 'Submit');
$messages = [];
foreach (Element::children($form) as $key) {
if (isset($form[$key]['#required_error'])) {
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
$messages[] = [
'title' => $form[$key]['#title'],
'message' => $form[$key]['#required_error'],
'key' => $key,
];
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
$this->assertText($form[$key]['#required_error']);
}
elseif (isset($form[$key]['#form_test_required_error'])) {
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
$messages[] = [
'title' => $form[$key]['#title'],
'message' => $form[$key]['#form_test_required_error'],
'key' => $key,
];
}
elseif (!empty($form[$key]['#required'])) {
$messages[] = [
'title' => $form[$key]['#title'],
'message' => t('!name field is required.', ['!name' => $form[$key]['#title']]),
'key' => $key,
];
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
$this->assertText($form[$key]['#form_test_required_error']);
}
}
$this->assertErrorMessages($messages);
$this->assertNoText(t('An illegal choice has been detected. Please contact the site administrator.'));
// Verify that no custom validation error appears with valid values.
$edit = array(
@ -243,60 +234,17 @@ class ValidationTest extends WebTestBase {
);
$this->drupalPostForm('form-test/validate-required', $edit, 'Submit');
$messages = [];
foreach (Element::children($form) as $key) {
if (isset($form[$key]['#required_error'])) {
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
$this->assertNoText($form[$key]['#required_error']);
}
elseif (isset($form[$key]['#form_test_required_error'])) {
$this->assertNoText(t('!name field is required.', array('!name' => $form[$key]['#title'])));
$this->assertNoText(t('@name field is required.', array('@name' => $form[$key]['#title'])));
$this->assertNoText($form[$key]['#form_test_required_error']);
}
elseif (!empty($form[$key]['#required'])) {
$messages[] = [
'title' => $form[$key]['#title'],
'message' => t('!name field is required.', ['!name' => $form[$key]['#title']]),
'key' => $key,
];
}
}
$this->assertErrorMessages($messages);
}
/**
* Asserts that the given error messages are displayed.
*
* @param array $messages
* An associative array of error messages keyed by the order they appear on
* the page, with the following key-value pairs:
* - title: The human readable form element title.
* - message: The error message for this form element.
* - key: The key used for the form element.
*/
protected function assertErrorMessages($messages) {
$element = $this->xpath('//div[@class = "form-item--error-message"]/strong');
$this->assertIdentical(count($messages), count($element));
$error_links = [];
foreach ($messages as $delta => $message) {
// Ensure the message appears in the correct place.
if (!isset($element[$delta])) {
$this->fail(format_string('The error message for the "@title" element with key "@key" was not found.', ['@title' => $message['title'], '@key' => $message['key']]));
}
else {
$this->assertIdentical($message['message'], (string) $element[$delta]);
}
// Gather the element for checking the jump link section.
$error_links[] = \Drupal::l($message['title'], Url::fromRoute('<none>', [], ['fragment' => 'edit-' . str_replace('_', '-', $message['key']), 'external' => TRUE]));
}
$top_message = \Drupal::translation()->formatPlural(count($error_links), '1 error has been found:', '@count errors have been found:');
$this->assertRaw($top_message);
foreach ($error_links as $error_link) {
$this->assertRaw($error_link);
}
$this->assertNoText('An illegal choice has been detected. Please contact the site administrator.');
$this->assertNoText(t('An illegal choice has been detected. Please contact the site administrator.'));
}
}

View file

@ -1,37 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\HttpKernel\HeadersResponseCodeRenderTest.
*/
namespace Drupal\system\Tests\HttpKernel;
use Drupal\simpletest\WebTestBase;
/**
* Tests rendering headers and response codes.
*
* @group Routing
*/
class HeadersResponseCodeRenderTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('httpkernel_test');
/**
* Tests the rendering of an array-based header and response code.
*/
public function testHeaderResponseCode() {
$this->drupalGet('/httpkernel-test/teapot');
$this->assertResponse(418);
$this->assertHeader('X-Test-Teapot', 'Teapot Mode Active');
$this->assertHeader('X-Test-Teapot-Replace', 'Teapot replaced');
$this->assertHeader('X-Test-Teapot-No-Replace', 'This value is not replaced,This one is added');
}
}

View file

@ -8,8 +8,8 @@
namespace Drupal\system\Tests\Image;
use Drupal\Core\Image\ImageInterface;
use \Drupal\simpletest\KernelTestBase;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\simpletest\KernelTestBase;
/**
* Tests that core image manipulations work properly: scale, resize, rotate,
@ -278,9 +278,19 @@ class ToolkitGdTest extends KernelTestBase {
}
}
// Store the original GD resource.
$old_res = $toolkit->getResource();
// Perform our operation.
$image->apply($values['function'], $values['arguments']);
// If the operation replaced the resource, check that the old one has
// been destroyed.
$new_res = $toolkit->getResource();
if ($new_res !== $old_res) {
$this->assertFalse(is_resource($old_res), SafeMarkup::format("'%operation' destroyed the original resource.", ['%operation' => $values['function']]));
}
// To keep from flooding the test with assert values, make a general
// value for whether each group of values fail.
$correct_dimensions_real = TRUE;
@ -389,7 +399,7 @@ class ToolkitGdTest extends KernelTestBase {
}
}
// Test failures of CreateNew.
// Test failures of the 'create_new' operation.
$image = $this->imageFactory->get();
$image->createNew(-50, 20);
$this->assertFalse($image->isValid(), 'CreateNew with negative width fails.');
@ -401,6 +411,30 @@ class ToolkitGdTest extends KernelTestBase {
$this->assertTrue($image->isValid(), 'CreateNew with valid arguments validates the Image.');
}
/**
* Tests that GD resources are freed from memory.
*/
public function testResourceDestruction() {
// Test that an Image object going out of scope releases its GD resource.
$image = $this->imageFactory->get(drupal_get_path('module', 'simpletest') . '/files/image-test.png');
$res = $image->getToolkit()->getResource();
$this->assertTrue(is_resource($res), 'Successfully loaded image resource.');
$image = NULL;
$this->assertFalse(is_resource($res), 'Image resource was destroyed after losing scope.');
// Test that 'create_new' operation does not leave orphaned GD resources.
$image = $this->imageFactory->get(drupal_get_path('module', 'simpletest') . '/files/image-test.png');
$old_res = $image->getToolkit()->getResource();
// Check if resource has been created successfully.
$this->assertTrue(is_resource($old_res));
$image->createNew(20, 20);
$new_res = $image->getToolkit()->getResource();
// Check if the original resource has been destroyed.
$this->assertFalse(is_resource($old_res));
// Check if a new resource has been created successfully.
$this->assertTrue(is_resource($new_res));
}
/**
* Tests loading an image whose transparent color index is out of range.
*/

View file

@ -0,0 +1,49 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Installer\ConfigAfterInstallerTestBase.
*/
namespace Drupal\system\Tests\Installer;
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\StorageInterface;
use Drupal\KernelTests\AssertConfigTrait;
use Drupal\simpletest\InstallerTestBase;
/**
* Provides a class for install profiles to check their installed config.
*/
abstract class ConfigAfterInstallerTestBase extends InstallerTestBase {
use AssertConfigTrait;
/**
* Ensures that all the installed config looks like the exported one.
*
* @param array $skipped_config
* An array of skipped config.
*/
protected function assertInstalledConfig(array $skipped_config) {
/** @var \Drupal\Core\Config\StorageInterface $active_config_storage */
$active_config_storage = $this->container->get('config.storage');
/** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
$config_manager = $this->container->get('config.manager');
$default_install_path = 'core/profiles/' . $this->profile . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY;
$profile_config_storage = new FileStorage($default_install_path, StorageInterface::DEFAULT_COLLECTION);
foreach ($profile_config_storage->listAll() as $config_name) {
$result = $config_manager->diff($profile_config_storage, $active_config_storage, $config_name);
try {
$this->assertConfigDiff($result, $config_name, $skipped_config);
}
catch (\Exception $e) {
$this->fail($e->getMessage());
}
}
}
}

View file

@ -7,9 +7,11 @@
namespace Drupal\system\Tests\Installer;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Site\Settings;
use Drupal\simpletest\InstallerTestBase;
use Drupal\Core\Database\Database;
use Symfony\Component\HttpFoundation\Request;
/**
* Tests the installer with an existing settings file but no install profile.
@ -44,17 +46,12 @@ class InstallerExistingSettingsNoProfileTest extends InstallerTestBase {
// Pre-configure config directories.
$this->settings['config_directories'] = array(
CONFIG_ACTIVE_DIRECTORY => (object) array(
'value' => conf_path() . '/files/config_active',
'required' => TRUE,
),
CONFIG_STAGING_DIRECTORY => (object) array(
'value' => conf_path() . '/files/config_staging',
CONFIG_SYNC_DIRECTORY => (object) array(
'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync',
'required' => TRUE,
),
);
mkdir($this->settings['config_directories'][CONFIG_ACTIVE_DIRECTORY]->value, 0777, TRUE);
mkdir($this->settings['config_directories'][CONFIG_STAGING_DIRECTORY]->value, 0777, TRUE);
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
parent::setUp();
}

View file

@ -55,17 +55,12 @@ class InstallerExistingSettingsTest extends InstallerTestBase {
$site_path = DrupalKernel::findSitePath(Request::createFromGlobals());
// Pre-configure config directories.
$this->settings['config_directories'] = array(
CONFIG_ACTIVE_DIRECTORY => (object) array(
'value' => $site_path . '/files/config_active',
'required' => TRUE,
),
CONFIG_STAGING_DIRECTORY => (object) array(
'value' => $site_path . '/files/config_staging',
CONFIG_SYNC_DIRECTORY => (object) array(
'value' => $site_path . '/files/config_sync',
'required' => TRUE,
),
);
mkdir($this->settings['config_directories'][CONFIG_ACTIVE_DIRECTORY]->value, 0777, TRUE);
mkdir($this->settings['config_directories'][CONFIG_STAGING_DIRECTORY]->value, 0777, TRUE);
mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE);
parent::setUp();
}

View file

@ -7,6 +7,7 @@
namespace Drupal\system\Tests\Installer;
use Drupal\Core\Language\LanguageManager;
use Drupal\simpletest\InstallerTestBase;
/**
@ -26,7 +27,7 @@ class InstallerLanguagePageTest extends InstallerTestBase {
// Check that all predefined languages show up with their native names.
$this->drupalGet($GLOBALS['base_url'] . '/core/install.php');
foreach (\Drupal::languageManager()->getStandardLanguageList() as $langcode => $names) {
foreach (LanguageManager::getStandardLanguageList() as $langcode => $names) {
$this->assertOption('edit-langcode', $langcode);
$this->assertRaw('>' . $names[1] . '<');
}

View file

@ -40,6 +40,41 @@ class InstallerTest extends InstallerTestBase {
// metatags as expected to the first page of the installer.
$this->assertRaw('core/themes/seven/css/components/buttons.css');
$this->assertRaw('<meta charset="utf-8" />');
// Assert that the expected title is present.
$this->assertEqual('Choose language', $this->cssSelect('main h1')[0]);
parent::setUpLanguage();
}
/**
* {@inheritdoc}
*/
protected function setUpProfile() {
// Assert that the expected title is present.
$this->assertEqual('Select an installation profile', $this->cssSelect('main h1')[0]);
parent::setUpProfile();
}
/**
* {@inheritdoc}
*/
protected function setUpSettings() {
// Assert that the expected title is present.
$this->assertEqual('Database configuration', $this->cssSelect('main h1')[0]);
parent::setUpSettings();
}
/**
* {@inheritdoc}
*/
protected function setUpSite() {
// Assert that the expected title is present.
$this->assertEqual('Configure site', $this->cssSelect('main h1')[0]);
parent::setUpSite();
}
}

View file

@ -96,7 +96,7 @@ class InstallerTranslationTest extends InstallerTestBase {
$edit = array('preprocess_css' => FALSE);
$this->drupalPostForm('admin/config/development/performance', $edit, t('Save configuration'));
$this->drupalGet('<front>');
$this->assertRaw('classy/css/layout.css');
$this->assertRaw('classy/css/components/action-links.css');
// Verify the strings from the translation files were imported.
$test_samples = ['Save and continue', 'Anonymous'];

View file

@ -1,145 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Installer\InstallerTranslationVersionUnitTest.
*/
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\KernelTestBase;
/**
* Tests the translation version fallback used during site installation to
* determine available translation files.
*
* @group Installer
*/
class InstallerTranslationVersionUnitTest extends KernelTestBase {
protected function setUp() {
parent::setUp();
require_once \Drupal::root() . '/core/includes/install.core.inc';
}
/**
* Asserts version fallback results of install_get_localization_release().
*
* @param $version
* Version string for which to determine version fallbacks.
* @param $fallback
* Array of fallback versions ordered for most to least significant.
* @param string $message
* (optional) A message to display with the assertion.
* @param string $group
* (optional) The group this message is in.
*
* @return bool
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertVersionFallback($version, $fallback, $message = '', $group = 'Other') {
$equal = TRUE;
$results = install_get_localization_release($version);
// Check the calculated results with the required results.
// The $results is an array of arrays, each containing:
// 'version': A release version (e.g. 8.0)
// 'core' : The matching core version (e.g. 8.x)
if (count($fallback) == count($results)) {
foreach($results as $key => $result) {
$equal &= $result['version'] == $fallback[$key];
list($major_release) = explode('.', $fallback[$key]);
$equal &= $result['core'] == $major_release . '.x';
}
}
else {
$equal = FALSE;
}
$message = $message ? $message : t('Version fallback for @version.', array('@version' => $version));
return $this->assert((bool) $equal, $message, $group);
}
/**
* Tests version fallback of install_get_localization_release().
*/
public function testVersionFallback() {
$version = '8.0.0';
$fallback = array('8.0.0', '8.0.0-rc1', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.1.0';
$fallback = array('8.1.0', '8.1.0-rc1', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.12.0';
$fallback = array('8.12.0', '8.12.0-rc1', '8.11.0', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.0-dev';
$fallback = array('8.0.0-rc1', '8.0.0-beta1', '8.0.0-alpha1', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.9.0-dev';
$fallback = array('8.9.0-rc1', '8.9.0-beta1', '8.9.0-alpha1', '8.8.0', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.0-alpha3';
$fallback = array('8.0.0-alpha3', '8.0.0-alpha2', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.0-alpha1';
$fallback = array('8.0.0-alpha1', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.0-beta2';
$fallback = array('8.0.0-beta2', '8.0.0-beta1', '8.0.0-alpha1', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.0-beta1';
$fallback = array('8.0.0-beta1', '8.0.0-alpha1', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.0-rc8';
$fallback = array('8.0.0-rc8', '8.0.0-rc7', '8.0.0-beta1', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.0-rc1';
$fallback = array('8.0.0-rc1', '8.0.0-beta1', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.2.0-beta1';
$fallback = array('8.2.0-beta1', '8.2.0-alpha1', '8.1.0', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.2.0-beta7';
$fallback = array('8.2.0-beta7', '8.2.0-beta6', '8.2.0-alpha1', '8.1.0', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.2.0-rc1';
$fallback = array('8.2.0-rc1', '8.2.0-beta1', '8.1.0', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.2.0-rc2';
$fallback = array('8.2.0-rc2', '8.2.0-rc1', '8.2.0-beta1', '8.1.0', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.0-foo2';
$fallback = array('8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.0.4';
$fallback = array('8.0.4', '8.0.3', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '8.3.5';
$fallback = array('8.3.5', '8.3.4', '8.3.0', '8.2.0', '8.0.0', '7.0');
$this->assertVersionFallback($version, $fallback);
$version = '99.0.1';
$fallback = array('99.0.1', '99.0.0' ,'98.0.0');
$this->assertVersionFallback($version, $fallback);
$version = '99.7.1';
$fallback = array('99.7.1', '99.7.0', '99.6.0', '99.0.0' ,'98.0.0');
$this->assertVersionFallback($version, $fallback);
}
}

View file

@ -0,0 +1,33 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Installer\MinimalInstallerTest.
*/
namespace Drupal\system\Tests\Installer;
use Drupal\KernelTests\AssertConfigTrait;
/**
* Tests the interactive installer installing the minimal profile.
*
* @group Installer
*/
class MinimalInstallerTest extends ConfigAfterInstallerTestBase {
use AssertConfigTrait;
/**
* {@inheritdoc}
*/
protected $profile = 'minimal';
/**
* Ensures that the exported minimal configuration is up to date.
*/
public function testMinimalConfig() {
$this->assertInstalledConfig([]);
}
}

View file

@ -7,14 +7,12 @@
namespace Drupal\system\Tests\Installer;
use Drupal\simpletest\InstallerTestBase;
/**
* Tests the interactive installer installing the standard profile.
*
* @group Installer
*/
class StandardInstallerTest extends InstallerTestBase {
class StandardInstallerTest extends ConfigAfterInstallerTestBase {
/**
* {@inheritdoc}
@ -42,5 +40,24 @@ class StandardInstallerTest extends InstallerTestBase {
parent::setUpSite();
}
/**
* Ensures that the exported standard configuration is up to date.
*/
public function testStandardConfig() {
$skipped_config = [];
// \Drupal\simpletest\WebTestBase::installParameters() uses
// simpletest@example.com as mail address.
$skipped_config['contact.form.feedback'][] = ' - simpletest@example.com';
// \Drupal\filter\Entity\FilterFormat::toArray() drops the roles of filter
// formats.
$skipped_config['filter.format.basic_html'][] = 'roles:';
$skipped_config['filter.format.basic_html'][] = ' - authenticated';
$skipped_config['filter.format.full_html'][] = 'roles:';
$skipped_config['filter.format.full_html'][] = ' - administrator';
$skipped_config['filter.format.restricted_html'][] = 'roles:';
$skipped_config['filter.format.restricted_html'][] = ' - anonymous';
$this->assertInstalledConfig($skipped_config);
}
}

View file

@ -159,6 +159,9 @@ class LocalTasksTest extends WebTestBase {
$this->assertEqual('Settings', (string) $result[0], 'The settings tab is active.');
$this->assertEqual('Dynamic title for TestTasksSettingsSub1', (string) $result[1], 'The sub1 tab is active.');
$this->assertCacheTag('kittens:ragdoll');
$this->assertCacheTag('kittens:dwarf-cat');
$this->drupalGet(Url::fromRoute('menu_test.local_task_test_tasks_settings_derived', ['placeholder' => 'derive1']));
$this->assertLocalTasks($sub_tasks, 1);

View file

@ -2,7 +2,7 @@
/**
* @file
* Contains \Drupal\system\Tests\Menu\MenuTranslateTest.
* Contains \Drupal\system\Tests\Menu\MenuAccessTest.
*/
namespace Drupal\system\Tests\Menu;
@ -11,12 +11,11 @@ use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
/**
* Tests the _menu_translate() method.
* Tests the route access checks on menu links.
*
* @group Menu
* @see _menu_translate().
*/
class MenuTranslateTest extends WebTestBase {
class MenuAccessTest extends WebTestBase {
/**
* Modules to enable.
@ -35,9 +34,23 @@ class MenuTranslateTest extends WebTestBase {
}
/**
* Tests _menu_translate().
* Tests menu link for route with access check.
*
* @see \Drupal\menu_test\Access\AccessCheck::access()
*/
public function testMenuTranslate() {
public function testMenuBlockLinksAccessCheck() {
$this->drupalPlaceBlock('system_menu_block:account');
// Test that there's link rendered on the route.
$this->drupalGet('menu_test_access_check_session');
$this->assertLink('Test custom route access check');
// Page still accessible but thre should not be menu link.
$this->drupalGet('menu_test_access_check_session');
$this->assertResponse(200);
$this->assertNoLink('Test custom route access check');
// Test that page is no more accessible.
$this->drupalGet('menu_test_access_check_session');
$this->assertResponse(403);
// Check for access to a restricted local task from a default local task.
$this->drupalGet('foo/asdf');
$this->assertResponse(200);

View file

@ -44,6 +44,7 @@ class MenuRouterTest extends WebTestBase {
$this->drupalPlaceBlock('system_menu_block:tools');
$this->drupalPlaceBlock('local_tasks_block');
$this->drupalPlaceBlock('page_title_block');
}
/**

View file

@ -319,6 +319,37 @@ class MenuTreeStorageTest extends KernelTestBase {
$this->assertEqual($this->treeStorage->getSubtreeHeight('child4'), 1);
}
/**
* Ensure hierarchy persists after a menu rebuild.
*/
public function testMenuRebuild() {
// root
// - child1
// -- child2
// --- child3
// ---- child4
$this->addMenuLink('root');
$this->addMenuLink('child1', 'root');
$this->addMenuLink('child2', 'child1');
$this->addMenuLink('child3', 'child2');
$this->addMenuLink('child4', 'child3');
$this->assertEqual($this->treeStorage->getSubtreeHeight('root'), 5);
$this->assertEqual($this->treeStorage->getSubtreeHeight('child1'), 4);
$this->assertEqual($this->treeStorage->getSubtreeHeight('child2'), 3);
$this->assertEqual($this->treeStorage->getSubtreeHeight('child3'), 2);
$this->assertEqual($this->treeStorage->getSubtreeHeight('child4'), 1);
// Intentionally leave child3 out to mimic static or external links.
$definitions = $this->treeStorage->loadMultiple(['root', 'child1', 'child2', 'child4']);
$this->treeStorage->rebuild($definitions);
$this->assertEqual($this->treeStorage->getSubtreeHeight('root'), 5);
$this->assertEqual($this->treeStorage->getSubtreeHeight('child1'), 4);
$this->assertEqual($this->treeStorage->getSubtreeHeight('child2'), 3);
$this->assertEqual($this->treeStorage->getSubtreeHeight('child3'), 2);
$this->assertEqual($this->treeStorage->getSubtreeHeight('child4'), 1);
}
/**
* Tests MenuTreeStorage::loadByProperties().
*/

View file

@ -47,7 +47,9 @@ EOT;
->execute();
$migration = Migration::load('menu');
db_truncate($migration->getIdMap()->mapTableName())->execute();
\Drupal::database()
->truncate($migration->getIdMap()->mapTableName())
->execute();
$this->executeMigration($migration);
$navigation_menu = Menu::load('navigation');

View file

@ -7,7 +7,8 @@
namespace Drupal\system\Tests\Migrate\d6;
use Drupal\migrate\MigrateExecutable;
use Drupal\Core\Datetime\Entity\DateFormat;
use Drupal\migrate\Entity\Migration;
use Drupal\Core\Database\Database;
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
@ -30,13 +31,13 @@ class MigrateDateFormatTest extends MigrateDrupal6TestBase {
* Tests the Drupal 6 date formats to Drupal 8 migration.
*/
public function testDateFormats() {
$short_date_format = entity_load('date_format', 'short');
$short_date_format = DateFormat::load('short');
$this->assertIdentical('\S\H\O\R\T m/d/Y - H:i', $short_date_format->getPattern());
$medium_date_format = entity_load('date_format', 'medium');
$medium_date_format = DateFormat::load('medium');
$this->assertIdentical('\M\E\D\I\U\M D, m/d/Y - H:i', $medium_date_format->getPattern());
$long_date_format = entity_load('date_format', 'long');
$long_date_format = DateFormat::load('long');
$this->assertIdentical('\L\O\N\G l, F j, Y - H:i', $long_date_format->getPattern());
// Test that we can re-import using the EntityDateFormat destination.
@ -45,12 +46,17 @@ class MigrateDateFormatTest extends MigrateDrupal6TestBase {
->fields(array('value' => serialize('\S\H\O\R\T d/m/Y - H:i')))
->condition('name', 'date_format_short')
->execute();
db_truncate(entity_load('migration', 'd6_date_formats')->getIdMap()->mapTableName())->execute();
$migration = entity_load_unchanged('migration', 'd6_date_formats');
$executable = new MigrateExecutable($migration, $this);
$executable->import();
$short_date_format = entity_load('date_format', 'short');
\Drupal::database()
->truncate(Migration::load('d6_date_formats')->getIdMap()->mapTableName())
->execute();
$migration = \Drupal::entityManager()
->getStorage('migration')
->loadUnchanged('d6_date_formats');
$this->executeMigration($migration);
$short_date_format = DateFormat::load('short');
$this->assertIdentical('\S\H\O\R\T d/m/Y - H:i', $short_date_format->getPattern());
}

View file

@ -53,6 +53,21 @@ class InstallTest extends WebTestBase {
$this->assertTrue($version > 0, 'System module version is > 0.');
$version = drupal_get_installed_schema_version('user', TRUE);
$this->assertTrue($version > 0, 'User module version is > 0.');
$post_update_key_value = \Drupal::keyValue('post_update');
$existing_updates = $post_update_key_value->get('existing_updates', []);
$this->assertTrue(in_array('module_test_post_update_test', $existing_updates));
}
/**
* Ensures that post update functions are removed on uninstall.
*/
public function testUninstallPostUpdateFunctions() {
\Drupal::service('module_installer')->uninstall(['module_test']);
$post_update_key_value = \Drupal::keyValue('post_update');
$existing_updates = $post_update_key_value->get('existing_updates', []);
$this->assertFalse(in_array('module_test_post_update_test', $existing_updates));
}
/**

View file

@ -16,7 +16,10 @@ use Drupal\Core\Logger\RfcLogLevel;
*/
class InstallUninstallTest extends ModuleTestBase {
public static $modules = array('system_test', 'dblog', 'taxonomy');
/**
* {@inheritdoc}
*/
public static $modules = array('system_test', 'dblog', 'taxonomy', 'update_test_postupdate');
/**
* Tests that a fixed set of modules can be installed and uninstalled.
@ -34,43 +37,61 @@ class InstallUninstallTest extends ModuleTestBase {
$this->assertEqual($this->container->get('state')->get('system_test_preuninstall_module'), 'module_test');
$this->resetAll();
// Try to install and uninstall book, toolbar modules and its dependencies.
$all_modules = system_rebuild_module_data();
// Test help on required modules, but do not test uninstalling.
$required_modules = array_filter($all_modules, function ($module) {
if (!empty($module->info['required']) || $module->status == TRUE) {
if ($module->info['package'] != 'Testing' && empty($module->info['hidden'])) {
return TRUE;
}
}
return FALSE;
});
$required_modules['help'] = $all_modules['help'];
// Test uninstalling without hidden, required, and already enabled modules.
$all_modules = array_filter($all_modules, function ($module) {
// Filter hidden, required and already enabled modules.
if (!empty($module->info['hidden']) || !empty($module->info['required']) || $module->status == TRUE || $module->info['package'] == 'Testing') {
return FALSE;
}
return TRUE;
});
// Go through each module in the list and try to install it (unless it was
// already installed automatically due to a dependency).
$automatically_installed = array();
// Install the Help module, and verify it installed successfully.
unset($all_modules['help']);
$this->assertModuleNotInstalled('help');
$edit = array();
$package = $required_modules['help']->info['package'];
$edit["modules[$package][help][enable]"] = TRUE;
$this->drupalPostForm('admin/modules', $edit, t('Install'));
$this->assertText('has been enabled', 'Modules status has been updated.');
$this->assertText(t('hook_modules_installed fired for help'));
$this->assertModuleSuccessfullyInstalled('help');
// Test help for the required modules.
foreach ($required_modules as $name => $module) {
$this->assertHelp($name, $module->info['name']);
}
// Go through each module in the list and try to install and uninstall
// it with its dependencies.
while (list($name, $module) = each($all_modules)) {
// Skip modules that have been automatically installed.
if (in_array($name, $automatically_installed)) {
continue;
}
$was_installed_list = \Drupal::moduleHandler()->getModuleList();
// Start a list of modules that we expect to be installed this time.
$modules_to_install = array($name);
foreach (array_keys($module->requires) as $dependency) {
if (isset($all_modules[$dependency]) && !in_array($dependency, $automatically_installed)) {
if (isset($all_modules[$dependency])) {
$modules_to_install[] = $dependency;
// Add any potential dependency of this module to the list of modules we
// expect to be automatically installed.
$automatically_installed[] = $dependency;
}
}
// Check that each module is not yet enabled and does not have any
// database tables yet.
foreach ($modules_to_install as $module_to_install) {
$this->assertModules(array($module_to_install), FALSE);
$this->assertModuleTablesDoNotExist($module_to_install);
$this->assertModuleNotInstalled($module_to_install);
}
// Install the module.
@ -101,42 +122,55 @@ class InstallUninstallTest extends ModuleTestBase {
// appropriate messages appear in the logs.
foreach ($modules_to_install as $module_to_install) {
$this->assertText(t('hook_modules_installed fired for @module', array('@module' => $module_to_install)));
$this->assertModules(array($module_to_install), TRUE);
$this->assertModuleTablesExist($module_to_install);
$this->assertModuleConfig($module_to_install);
$this->assertLogMessage('system', "%module module installed.", array('%module' => $module_to_install), RfcLogLevel::INFO);
$this->assertInstallModuleUpdates($module_to_install);
$this->assertModuleSuccessfullyInstalled($module_to_install);
}
// Uninstall the original module, and check appropriate
// hooks, tables, and log messages. (Later, we'll go back and do the
// same thing for modules that were enabled automatically.)
$this->assertSuccessfulUninstall($name, $package);
}
// Verify the help page.
$this->assertHelp($name, $module->info['name']);
// Go through all modules that were automatically installed, and try to
// uninstall them one by one.
while ($automatically_installed) {
$initial_count = count($automatically_installed);
foreach ($automatically_installed as $name) {
$package = $all_modules[$name]->info['package'];
// If the module can't be uninstalled due to dependencies, skip it and
// try again the next time. Otherwise, try to uninstall it.
$this->drupalGet('admin/modules/uninstall');
$disabled_checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="uninstall[' . $name . ']"]');
if (empty($disabled_checkbox)) {
$automatically_installed = array_diff($automatically_installed, array($name));
$this->assertSuccessfulUninstall($name, $package);
// Uninstall the original module, plus everything else that was installed
// with it.
if ($name == 'forum') {
// Forum has an extra step to be able to uninstall it.
$this->preUninstallForum();
}
$now_installed_list = \Drupal::moduleHandler()->getModuleList();
$added_modules = array_diff(array_keys($now_installed_list), array_keys($was_installed_list));
while ($added_modules) {
$initial_count = count($added_modules);
foreach ($added_modules as $to_uninstall) {
// See if we can currently uninstall this module (if its dependencies
// have been uninstalled), and do so if we can.
$this->drupalGet('admin/modules/uninstall');
$field_name = "uninstall[$to_uninstall]";
$has_checkbox = $this->xpath('//input[@type="checkbox" and @name="' . $field_name . '"]');
$disabled = $this->xpath('//input[@type="checkbox" and @name="' . $field_name . '" and @disabled="disabled"]');
if (!empty($has_checkbox) && empty($disabled)) {
// This one is eligible for being uninstalled.
$package = $all_modules[$to_uninstall]->info['package'];
$this->assertSuccessfulUninstall($to_uninstall, $package);
$added_modules = array_diff($added_modules, array($to_uninstall));
}
}
// If we were not able to find a module to uninstall, fail and exit the
// loop.
$final_count = count($added_modules);
if ($initial_count == $final_count) {
$this->fail('Remaining modules could not be uninstalled for ' . $name);
break;
}
}
$final_count = count($automatically_installed);
// If all checkboxes were disabled, something is really wrong with the
// test. Throw a failure and avoid an infinite loop.
if ($initial_count == $final_count) {
$this->fail('Remaining modules could not be disabled.');
break;
}
}
// Uninstall the help module and put it back into the list of modules.
$all_modules['help'] = $required_modules['help'];
$this->assertSuccessfulUninstall('help', $required_modules['help']->info['package']);
// Now that all modules have been tested, go back and try to enable them
// all again at once. This tests two things:
// - That each module can be successfully enabled again after being
@ -151,6 +185,29 @@ class InstallUninstallTest extends ModuleTestBase {
$this->assertText(t('@count modules have been enabled: ', array('@count' => count($all_modules))), 'Modules status has been updated.');
}
/**
* Asserts that a module is not yet installed.
*
* @param string $name
* Name of the module to check.
*/
protected function assertModuleNotInstalled($name) {
$this->assertModules(array($name), FALSE);
$this->assertModuleTablesDoNotExist($name);
}
/**
* Asserts that a module was successfully installed.
*
* @param string $name
* Name of the module to check.
*/
protected function assertModuleSuccessfullyInstalled($name) {
$this->assertModules(array($name), TRUE);
$this->assertModuleTablesExist($name);
$this->assertModuleConfig($name);
}
/**
* Uninstalls a module and asserts that it was done correctly.
*
@ -162,15 +219,6 @@ class InstallUninstallTest extends ModuleTestBase {
*/
protected function assertSuccessfulUninstall($module, $package = 'Core') {
$edit = array();
if ($module == 'forum') {
// Forum cannot be uninstalled until all of the content entities related
// to it have been deleted.
$vid = $this->config('forum.settings')->get('vocabulary');
$terms = entity_load_multiple_by_properties('taxonomy_term', ['vid' => $vid]);
foreach ($terms as $term) {
$term->delete();
}
}
$edit['uninstall[' . $module . ']'] = TRUE;
$this->drupalPostForm('admin/modules/uninstall', $edit, t('Uninstall'));
$this->drupalPostForm(NULL, NULL, t('Uninstall'));
@ -188,6 +236,92 @@ class InstallUninstallTest extends ModuleTestBase {
$this->assertModuleTablesDoNotExist($module);
// Check that the module's config files no longer exist.
$this->assertNoModuleConfig($module);
$this->assertUninstallModuleUpdates($module);
}
/**
* Asserts the module post update functions after install.
*
* @param string $module
* The module that got installed.
*/
protected function assertInstallModuleUpdates($module) {
/** @var \Drupal\Core\Update\UpdateRegistry $post_update_registry */
$post_update_registry = \Drupal::service('update.post_update_registry');
$all_update_functions = $post_update_registry->getPendingUpdateFunctions();
$empty_result = TRUE;
foreach ($all_update_functions as $function) {
list($function_module, ) = explode('_post_update_', $function);
if ($module === $function_module) {
$empty_result = FALSE;
break;
}
}
$this->assertTrue($empty_result, 'Ensures that no pending post update functions are available.');
$existing_updates = \Drupal::keyValue('post_update')->get('existing_updates', []);
switch ($module) {
case 'block':
$this->assertFalse(array_diff(['block_post_update_disable_blocks_with_missing_contexts'], $existing_updates));
break;
case 'update_test_postupdate':
$this->assertFalse(array_diff(['update_test_postupdate_post_update_first', 'update_test_postupdate_post_update_second', 'update_test_postupdate_post_update_test1', 'update_test_postupdate_post_update_test0'], $existing_updates));
break;
}
}
/**
* Asserts the module post update functions after uninstall.
*
* @param string $module
* The module that got installed.
*/
protected function assertUninstallModuleUpdates($module) {
/** @var \Drupal\Core\Update\UpdateRegistry $post_update_registry */
$post_update_registry = \Drupal::service('update.post_update_registry');
$all_update_functions = $post_update_registry->getPendingUpdateFunctions();
switch ($module) {
case 'block':
$this->assertFalse(array_intersect(['block_post_update_disable_blocks_with_missing_contexts'], $all_update_functions), 'Asserts that no pending post update functions are available.');
$existing_updates = \Drupal::keyValue('post_update')->get('existing_updates', []);
$this->assertFalse(array_intersect(['block_post_update_disable_blocks_with_missing_contexts'], $existing_updates), 'Asserts that no post update functions are stored in keyvalue store.');
break;
}
}
/**
* Verifies a module's help.
*
* Verifies that the module help page from hook_help() exists and can be
* displayed, and that it contains the phrase "Foo Bar module", where "Foo
* Bar" is the name of the module from the .info.yml file.
*
* @param string $module
* Machine name of the module to verify.
* @param string $name
* Human-readable name of the module to verify.
*/
protected function assertHelp($module, $name) {
$this->drupalGet('admin/help/' . $module);
$this->assertResponse(200, "Help for $module displayed successfully");
$this->assertText($name . ' module', "'$name module' is on the help page for $module");
$this->assertLink('online documentation for the ' . $name . ' module', 0, "Correct online documentation link is in the help page for $module");
}
/**
* Deletes forum taxonomy terms, so Forum can be uninstalled.
*/
protected function preUninstallForum() {
// There only should be a 'General discussion' term in the 'forums'
// vocabulary, but just delete any terms there in case the name changes.
$query = \Drupal::entityQuery('taxonomy_term');
$query->condition('vid', 'forums');
$ids = $query->execute();
$storage = \Drupal::entityManager()->getStorage('taxonomy_term');
$terms = $storage->loadMultiple($ids);
$storage->delete($terms);
}
}

View file

@ -72,7 +72,7 @@ class UninstallTest extends WebTestBase {
$this->drupalPostForm('admin/modules/uninstall', $edit, t('Uninstall'));
$this->assertNoText(\Drupal::translation()->translate('Configuration deletions'), 'No configuration deletions listed on the module install confirmation page.');
$this->assertText(\Drupal::translation()->translate('Configuration updates'), 'Configuration updates listed on the module install confirmation page.');
$this->assertText($node_type->label(), SafeMarkup::format('The entity label "!label" found.', array('!label' => $node_type->label())));
$this->assertText($node_type->label());
$this->drupalPostForm(NULL, NULL, t('Uninstall'));
$this->assertText(t('The selected modules have been uninstalled.'), 'Modules status has been updated.');
@ -88,7 +88,7 @@ class UninstallTest extends WebTestBase {
$entity_types = array();
foreach ($node_dependencies as $entity) {
$label = $entity->label() ?: $entity->id();
$this->assertText($label, SafeMarkup::format('The entity label "!label" found.', array('!label' => $label)));
$this->assertText($label);
$entity_types[] = $entity->getEntityTypeId();
}
$entity_types = array_unique($entity_types);

View file

@ -143,18 +143,28 @@ class PagerTest extends WebTestBase {
$next = array_pop($elements);
}
// We remove elements from the $elements array in the following code, so
// we store the total number of pages for verifying the "last" link.
$total_pages = count($elements);
// Verify items and links to pages.
foreach ($elements as $page => $element) {
// Make item/page index 1-based.
$page++;
if ($current_page == $page) {
$this->assertClass($element, 'is-active', 'Element for current page has .is-active class.');
$this->assertTrue($element->a, 'Element for current page has link.');
$destination = $element->a['href'][0]->__toString();
// URL query string param is 0-indexed.
$this->assertEqual($destination, '?page=' . ($page - 1));
}
else {
$this->assertNoClass($element, 'is-active', "Element for page $page has no .is-active class.");
$this->assertClass($element, 'pager__item', "Element for page $page has .pager__item class.");
$this->assertTrue($element->a, "Link to page $page found.");
$destination = $element->a['href'][0]->__toString();
$this->assertEqual($destination, '?page=' . ($page - 1));
}
unset($elements[--$page]);
}
@ -166,21 +176,32 @@ class PagerTest extends WebTestBase {
$this->assertClass($first, 'pager__item--first', 'Element for first page has .pager__item--first class.');
$this->assertTrue($first->a, 'Link to first page found.');
$this->assertNoClass($first->a, 'is-active', 'Link to first page is not active.');
$destination = $first->a['href'][0]->__toString();
$this->assertEqual($destination, '?page=0');
}
if (isset($previous)) {
$this->assertClass($previous, 'pager__item--previous', 'Element for first page has .pager__item--previous class.');
$this->assertTrue($previous->a, 'Link to previous page found.');
$this->assertNoClass($previous->a, 'is-active', 'Link to previous page is not active.');
$destination = $previous->a['href'][0]->__toString();
// URL query string param is 0-indexed, $current_page is 1-indexed.
$this->assertEqual($destination, '?page=' . ($current_page - 2));
}
if (isset($next)) {
$this->assertClass($next, 'pager__item--next', 'Element for next page has .pager__item--next class.');
$this->assertTrue($next->a, 'Link to next page found.');
$this->assertNoClass($next->a, 'is-active', 'Link to next page is not active.');
$destination = $next->a['href'][0]->__toString();
// URL query string param is 0-indexed, $current_page is 1-indexed.
$this->assertEqual($destination, '?page=' . $current_page);
}
if (isset($last)) {
$this->assertClass($last, 'pager__item--last', 'Element for last page has .pager__item--last class.');
$this->assertTrue($last->a, 'Link to last page found.');
$this->assertNoClass($last->a, 'is-active', 'Link to last page is not active.');
$destination = $last->a['href'][0]->__toString();
// URL query string param is 0-indexed.
$this->assertEqual($destination, '?page=' . ($total_pages - 1));
}
}

View file

@ -82,14 +82,14 @@ class UrlAlterFunctionalTest extends WebTestBase {
* A string with the original path that is run through generateFrommPath().
* @param $final
* A string with the expected result after generateFrommPath().
*
* @return
* TRUE if $original was correctly altered to $final, FALSE otherwise.
*/
protected function assertUrlOutboundAlter($original, $final) {
// Test outbound altering.
$result = $this->container->get('url_generator')->generateFromPath(ltrim($original, '/'));
$final = Url::fromUri('internal:' . $final)->toString();
$this->assertIdentical($result, $final, format_string('Altered outbound URL %original, expected %final, and got %result.', array('%original' => $original, '%final' => $final, '%result' => $result)));
$result = $this->container->get('path_processor_manager')->processOutbound($original);
return $this->assertIdentical($result, $final, format_string('Altered outbound URL %original, expected %final, and got %result.', array('%original' => $original, '%final' => $final, '%result' => $result)));
}
/**
@ -99,12 +99,13 @@ class UrlAlterFunctionalTest extends WebTestBase {
* The original path before it has been altered by inbound URL processing.
* @param $final
* A string with the expected result.
*
* @return
* TRUE if $original was correctly altered to $final, FALSE otherwise.
*/
protected function assertUrlInboundAlter($original, $final) {
// Test inbound altering.
$result = $this->container->get('path.alias_manager')->getPathByAlias($original);
$this->assertIdentical($result, $final, format_string('Altered inbound URL %original, expected %final, and got %result.', array('%original' => $original, '%final' => $final, '%result' => $result)));
return $this->assertIdentical($result, $final, format_string('Altered inbound URL %original, expected %final, and got %result.', array('%original' => $original, '%final' => $final, '%result' => $result)));
}
}

View file

@ -9,6 +9,7 @@ namespace Drupal\system\Tests\Plugin;
use Drupal\Component\Plugin\Exception\ContextException;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\node\Entity\NodeType;
use Drupal\plugin_test\Plugin\MockBlockManager;
use Drupal\simpletest\KernelTestBase;
@ -26,6 +27,10 @@ class ContextPluginTest extends KernelTestBase {
*/
function testContext() {
$this->installEntitySchema('user');
$this->installEntitySchema('node');
$this->installEntitySchema('node_type');
$type = NodeType::create(['type' => 'page', 'name' => 'Page']);
$type->save();
$name = $this->randomMachineName();
$manager = new MockBlockManager();

View file

@ -7,7 +7,7 @@
namespace Drupal\system\Tests\Plugin\Discovery;
use Drupal\Core\StringTranslation\TranslationWrapper;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\simpletest\KernelTestBase;
/**
@ -77,7 +77,7 @@ abstract class DiscoveryTestBase extends KernelTestBase {
*/
protected function assertDefinitionIdentical(array $definition, array $expected_definition) {
$func = function (&$item){
if ($item instanceof TranslationWrapper) {
if ($item instanceof TranslatableMarkup) {
$item = (string) $item;
}
};

View file

@ -31,8 +31,8 @@ class InspectionTest extends PluginTestBase {
$plugin = $this->mockBlockManager->createInstance($id);
$expected_definition = $this->mockBlockExpectedDefinitions[$id];
$this->assertIdentical($plugin->getPluginId(), $id);
$this->assertIdentical($this->mockBlockManager->getDefinition($id), $expected_definition);
$this->assertIdentical($plugin->getPluginDefinition(), $expected_definition);
$this->assertIdentical($this->castSafeStrings($this->mockBlockManager->getDefinition($id)), $expected_definition);
$this->assertIdentical($this->castSafeStrings($plugin->getPluginDefinition()), $expected_definition);
}
// Test a plugin manager that provides defaults.
foreach (array('test_block1', 'test_block2') as $id) {
@ -40,7 +40,7 @@ class InspectionTest extends PluginTestBase {
$expected_definition = $this->defaultsTestPluginExpectedDefinitions[$id];
$this->assertIdentical($plugin->getPluginId(), $id);
$this->assertIdentical($this->defaultsTestPluginManager->getDefinition($id), $expected_definition);
$this->assertIdentical($plugin->getPluginDefinition(), $expected_definition);
$this->assertIdentical($this->castSafeStrings($plugin->getPluginDefinition()), $expected_definition);
}
}

View file

@ -0,0 +1,113 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Render\AjaxPageStateTest.
*/
namespace Drupal\system\Tests\Render;
use Drupal\simpletest\WebTestBase;
/**
* Performs tests for the effects of the ajax_page_state query parameter.
*
* @group Render
*/
class AjaxPageStateTest extends WebTestBase {
/**
* User account with all available permissions
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $adminUser;
protected function setUp() {
parent::setUp();
// Create an administrator with all permissions.
$this->adminUser = $this->drupalCreateUser(array_keys(\Drupal::service('user.permissions')
->getPermissions()));
// Login so there are more libraries to test with otherwise only html5shiv
// is the only one in the source we can easily test for.
$this->drupalLogin($this->adminUser);
}
/**
* Default functionality without the param ajax_page_state[libraries].
*
* The libraries html5shiv and drupalSettings are loaded default from core
* and available in code as scripts. Do this as the base test.
*/
public function testLibrariesAvailable() {
$this->drupalGet('node', array());
$this->assertRaw(
'/core/assets/vendor/html5shiv/html5shiv.min.js',
'The html5shiv library from core should be loaded.'
);
$this->assertRaw(
'/core/misc/drupalSettingsLoader.js',
'The Dupalsettings library from core should be loaded.'
);
}
/**
* Give ajax_page_state[libraries]=core/html5shiv to exclude the library.
*
* When called with ajax_page_state[libraries]=core/html5shiv the library
* should be excluded as it is already loaded. This should not affect other
* libraries so test if drupalSettings is still available.
*
*/
public function testHtml5ShivIsNotLoaded() {
$this->drupalGet('node',
array(
"query" =>
array(
'ajax_page_state' => array(
'libraries' => 'core/html5shiv'
)
)
)
);
$this->assertNoRaw(
'/core/assets/vendor/html5shiv/html5shiv.min.js',
'The html5shiv library from core should be excluded from loading'
);
$this->assertRaw(
'/core/misc/drupalSettingsLoader.js',
'The Dupalsettings library from core should be loaded.'
);
}
/**
* Test if multiple libaries can be excluded.
*
* ajax_page_state[libraries] should be able to support multiple libraries
* comma separated.
*
*/
public function testMultipleLibrariesAreNotLoaded() {
$this->drupalGet('node',
array(
"query" =>
array(
'ajax_page_state' => array(
'libraries' => 'core/html5shiv,core/drupalSettings'
)
)
)
);
$this->assertNoRaw(
'/core/assets/vendor/html5shiv/html5shiv.min.js',
'The html5shiv library from core should be excluded from loading.'
);
$this->assertNoRaw(
'/core/misc/drupalSettingsLoader.js',
'The Dupalsettings library from core should be excluded from loading.'
);
}
}

View file

@ -32,6 +32,8 @@ class DisplayVariantTest extends WebTestBase {
// error page here.
$this->drupalGet('<front>');
$this->assertRaw('A very important, required value.');
$this->assertRaw('Explicitly passed in context.');
$this->assertCacheTag('custom_cache_tag');
}
}

View file

@ -0,0 +1,141 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Render\HtmlResponseAttachmentsTest.
*/
namespace Drupal\system\Tests\Render;
use Drupal\simpletest\WebTestBase;
/**
* Functional tests for HtmlResponseAttachmentsProcessor.
*
* @group Render
*/
class HtmlResponseAttachmentsTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['render_attached_test'];
/**
* Test rendering of ['#attached'].
*/
public function testAttachments() {
// Test ['#attached']['http_header] = ['Status', $code].
$this->drupalGet('/render_attached_test/teapot');
$this->assertResponse(418);
$this->assertHeader('X-Drupal-Cache', 'MISS');
// Repeat for the cache.
$this->drupalGet('/render_attached_test/teapot');
$this->assertResponse(418);
$this->assertHeader('X-Drupal-Cache', 'HIT');
// Test ['#attached']['http_header'] with various replacement rules.
$this->drupalGet('/render_attached_test/header');
$this->assertTeapotHeaders();
$this->assertHeader('X-Drupal-Cache', 'MISS');
// Repeat for the cache.
$this->drupalGet('/render_attached_test/header');
$this->assertHeader('X-Drupal-Cache', 'HIT');
// Test ['#attached']['feed'].
$this->drupalGet('/render_attached_test/feed');
$this->assertHeader('X-Drupal-Cache', 'MISS');
$this->assertFeed();
// Repeat for the cache.
$this->drupalGet('/render_attached_test/feed');
$this->assertHeader('X-Drupal-Cache', 'HIT');
// Test ['#attached']['html_head'].
$this->drupalGet('/render_attached_test/head');
$this->assertHeader('X-Drupal-Cache', 'MISS');
$this->assertHead();
// Repeat for the cache.
$this->drupalGet('/render_attached_test/head');
$this->assertHeader('X-Drupal-Cache', 'HIT');
}
/**
* Test caching of ['#attached'].
*/
public function testRenderCachedBlock() {
// Make sure our test block is visible.
$this->drupalPlaceBlock('attached_rendering_block', ['region' => 'content']);
// Get the front page, which should now have our visible block.
$this->drupalGet('');
// Make sure our block is visible.
$this->assertText('Markup from attached_rendering_block.');
// Test that all our attached items are present.
$this->assertFeed();
$this->assertHead();
$this->assertResponse(418);
$this->assertTeapotHeaders();
// Reload the page, to test caching.
$this->drupalGet('');
// Make sure our block is visible.
$this->assertText('Markup from attached_rendering_block.');
// The header should be present again.
$this->assertHeader('X-Test-Teapot', 'Teapot Mode Active');
}
/**
* Helper function to make assertions about added HTTP headers.
*/
protected function assertTeapotHeaders() {
$this->assertHeader('X-Test-Teapot', 'Teapot Mode Active');
$this->assertHeader('X-Test-Teapot-Replace', 'Teapot replaced');
$this->assertHeader('X-Test-Teapot-No-Replace', 'This value is not replaced,This one is added');
}
/**
* Helper function to make assertions about the presence of an RSS feed.
*/
protected function assertFeed() {
// Discover the DOM element for the feed link.
$test_meta = $this->xpath('//head/link[@href="test://url"]');
$this->assertEqual(1, count($test_meta), 'Link has URL.');
// Reconcile the other attributes.
$test_meta_attributes = [
'href' => 'test://url',
'rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => 'Your RSS feed.',
];
$test_meta = reset($test_meta);
if (empty($test_meta)) {
$this->fail('Unable to find feed link.');
}
else {
foreach ($test_meta->attributes() as $attribute => $value) {
$this->assertEqual($value, $test_meta_attributes[$attribute]);
}
}
}
/**
* Helper function to make assertions about HTML head elements.
*/
protected function assertHead() {
// Discover the DOM element for the meta link.
$test_meta = $this->xpath('//head/meta[@test-attribute="testvalue"]');
$this->assertEqual(1, count($test_meta), 'There\'s only one test attribute.');
// Grab the only DOM element.
$test_meta = reset($test_meta);
if (empty($test_meta)) {
$this->fail('Unable to find the head meta.');
}
else {
$test_meta_attributes = $test_meta->attributes();
$this->assertEqual($test_meta_attributes['test-attribute'], 'testvalue');
}
}
}

View file

@ -13,6 +13,7 @@ use Drupal\Core\Language\LanguageInterface;
use Drupal\simpletest\WebTestBase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Drupal\Core\Url;
/**
* Functional class for the full integrated routing system.
@ -181,10 +182,10 @@ class RouterTest extends WebTestBase {
* Checks the generate method on the url generator using the front router.
*/
public function testUrlGeneratorFront() {
global $base_path;
$this->assertEqual($this->container->get('url_generator')->generate('<front>'), $base_path);
$this->assertEqual($this->container->get('url_generator')->generateFromPath('<front>'), $base_path);
$front_url = Url::fromRoute('<front>', [], ['absolute' => TRUE]);
// Compare to the site base URL.
$base_url = Url::fromUri('base:/', ['absolute' => TRUE]);
$this->assertIdentical($base_url->toString(), $front_url->toString());
}
/**

View file

@ -153,6 +153,11 @@ class SessionTest extends WebTestBase {
* Test that empty anonymous sessions are destroyed.
*/
function testEmptyAnonymousSession() {
// Disable the dynamic_page_cache module; it'd cause session_test's debug
// output (that is added in
// SessionTestSubscriber::onKernelResponseSessionTest()) to not be added.
$this->container->get('module_installer')->uninstall(['dynamic_page_cache']);
// Verify that no session is automatically created for anonymous user when
// page caching is disabled.
$this->container->get('module_installer')->uninstall(['page_cache']);

View file

@ -30,6 +30,8 @@ class AccessDeniedTest extends WebTestBase {
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('page_title_block');
// Create an administrative user.
$this->adminUser = $this->drupalCreateUser(['access administration pages', 'administer site configuration', 'link to any page', 'administer blocks']);

View file

@ -21,7 +21,7 @@ class CronRunTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('common_test', 'common_test_cron_helper');
public static $modules = ['common_test', 'common_test_cron_helper', 'automated_cron'];
/**
* Test cron runs.
@ -43,42 +43,42 @@ class CronRunTest extends WebTestBase {
}
/**
* Ensure that the automatic cron run feature is working.
* Ensure that the automated cron run module is working.
*
* In these tests we do not use REQUEST_TIME to track start time, because we
* need the exact time when cron is triggered.
*/
function testAutomaticCron() {
function testAutomatedCron() {
// Test with a logged in user; anonymous users likely don't cause Drupal to
// fully bootstrap, because of the internal page cache or an external
// reverse proxy. Reuse this user for disabling cron later in the test.
$admin_user = $this->drupalCreateUser(array('administer site configuration'));
$this->drupalLogin($admin_user);
// Ensure cron does not run when the cron threshold is enabled and was
// not passed.
// Ensure cron does not run when a non-zero cron interval is specified and
// was not passed.
$cron_last = time();
$cron_safe_threshold = 100;
$cron_safe_interval = 100;
\Drupal::state()->set('system.cron_last', $cron_last);
$this->config('system.cron')
->set('threshold.autorun', $cron_safe_threshold)
$this->config('automated_cron.settings')
->set('interval', $cron_safe_interval)
->save();
$this->drupalGet('');
$this->assertTrue($cron_last == \Drupal::state()->get('system.cron_last'), 'Cron does not run when the cron threshold is not passed.');
$this->assertTrue($cron_last == \Drupal::state()->get('system.cron_last'), 'Cron does not run when the cron interval is not passed.');
// Test if cron runs when the cron threshold was passed.
// Test if cron runs when the cron interval was passed.
$cron_last = time() - 200;
\Drupal::state()->set('system.cron_last', $cron_last);
$this->drupalGet('');
sleep(1);
$this->assertTrue($cron_last < \Drupal::state()->get('system.cron_last'), 'Cron runs when the cron threshold is passed.');
$this->assertTrue($cron_last < \Drupal::state()->get('system.cron_last'), 'Cron runs when the cron interval is passed.');
// Disable the cron threshold through the interface.
$this->drupalPostForm('admin/config/system/cron', array('cron_safe_threshold' => 0), t('Save configuration'));
// Disable cron through the interface by setting the interval to zero.
$this->drupalPostForm('admin/config/system/cron', ['interval' => 0], t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'));
$this->drupalLogout();
// Test if cron does not run when the cron threshold is disabled.
// Test if cron does not run when the cron interval is set to zero.
$cron_last = time() - 200;
\Drupal::state()->set('system.cron_last', $cron_last);
$this->drupalGet('');

View file

@ -7,6 +7,7 @@
namespace Drupal\system\Tests\System;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
/**
@ -133,20 +134,31 @@ class DateTimeTest extends WebTestBase {
$this->assertText(t('Custom date format added.'), 'Date format added confirmation message appears.');
$this->assertText($name, 'Custom date format appears in the date format list.');
$this->assertText(t('Delete'), 'Delete link for custom date format appears.');
}
/**
* Test that date formats are sanitized.
*/
function testDateFormatXSS() {
$date_format = entity_create('date_format', array(
'id' => 'xss_short',
'label' => 'XSS format',
'pattern' => '\<\s\c\r\i\p\t\>\a\l\e\r\t\(\'\X\S\S\'\)\;\<\/\s\c\r\i\p\t\>',
));
));
$date_format->save();
$this->drupalGet('admin/config/regional/date-time');
$this->assertNoRaw("<script>alert('XSS');</script>", 'The date format was properly sanitized');
$this->drupalGet(Url::fromRoute('entity.date_format.collection'));
$this->assertEscaped("<script>alert('XSS');</script>", 'The date format was properly escaped');
// Add a new date format with HTML in it.
$date_format_id = strtolower($this->randomMachineName(8));
$name = ucwords($date_format_id);
$date_format = '& \<\e\m\>Y\<\/\e\m\>';
$edit = array(
'id' => $date_format_id,
'label' => $name,
'date_format_pattern' => $date_format,
);
$this->drupalPostForm('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
$this->assertUrl(\Drupal::url('entity.date_format.collection', [], ['absolute' => TRUE]), [], 'Correct page redirection.');
$this->assertText(t('Custom date format added.'), 'Date format added confirmation message appears.');
$this->assertText($name, 'Custom date format appears in the date format list.');
$this->assertEscaped('<em>' . date("Y") . '</em>');
}
}

View file

@ -68,14 +68,14 @@ class HtaccessTest extends WebTestBase {
$file_paths["$path/access_test.$file_ext"] = 403;
}
// Tests the .htaccess file in core/vendor and created by a Composer script.
// Tests the .htaccess file in vendor and created by a Composer script.
// Try and access a non PHP file in the vendor directory.
// @see Drupal\\Core\\Composer\\Composer::ensureHtaccess
$file_paths['core/vendor/composer/installed.json'] = 403;
$file_paths['vendor/composer/installed.json'] = 403;
// Tests the rewrite conditions and rule that denies access to php files.
$file_paths['core/lib/Drupal.php'] = 403;
$file_paths['core/vendor/autoload.php'] = 403;
$file_paths['vendor/autoload.php'] = 403;
$file_paths['autoload.php'] = 403;
// Test extensions that should be permitted.

View file

@ -23,7 +23,7 @@ class PageTitleTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('node', 'test_page_test', 'form_test');
public static $modules = ['node', 'test_page_test', 'form_test', 'block'];
protected $contentUser;
protected $savedTitle;
@ -36,6 +36,8 @@ class PageTitleTest extends WebTestBase {
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
$this->drupalPlaceBlock('page_title_block');
$this->contentUser = $this->drupalCreateUser(array('create page content', 'access content', 'administer themes', 'administer site configuration', 'link to any page'));
$this->drupalLogin($this->contentUser);
}
@ -71,13 +73,6 @@ class PageTitleTest extends WebTestBase {
$slogan = '<script type="text/javascript">alert("Slogan XSS!");</script>';
$slogan_filtered = Xss::filterAdmin($slogan);
// Activate needed appearance settings.
$edit = array(
'toggle_name' => TRUE,
'toggle_slogan' => TRUE,
);
$this->drupalPostForm('admin/appearance/settings', $edit, t('Save configuration'));
// Set title and slogan.
$edit = array(
'site_name' => $title,
@ -85,6 +80,9 @@ class PageTitleTest extends WebTestBase {
);
$this->drupalPostForm('admin/config/system/site-information', $edit, t('Save configuration'));
// Place branding block with site name and slogan into header region.
$this->drupalPlaceBlock('system_branding_block', ['region' => 'header']);
// Load frontpage.
$this->drupalGet('');
@ -109,14 +107,14 @@ class PageTitleTest extends WebTestBase {
$this->drupalGet('test-render-title');
$this->assertTitle('Foo | Drupal');
$result = $this->xpath('//h1');
$result = $this->xpath('//h1[@class="page-title"]');
$this->assertEqual('Foo', (string) $result[0]);
// Test forms
$this->drupalGet('form-test/object-builder');
$this->assertTitle('Test dynamic title | Drupal');
$result = $this->xpath('//h1');
$result = $this->xpath('//h1[@class="page-title"]');
$this->assertEqual('Test dynamic title', (string) $result[0]);
// Set some custom translated strings.
@ -129,14 +127,14 @@ class PageTitleTest extends WebTestBase {
$this->drupalGet('test-page-static-title');
$this->assertTitle('Static title translated | Drupal');
$result = $this->xpath('//h1');
$result = $this->xpath('//h1[@class="page-title"]');
$this->assertEqual('Static title translated', (string) $result[0]);
// Test the dynamic '_title_callback' route option.
$this->drupalGet('test-page-dynamic-title');
$this->assertTitle('Dynamic title | Drupal');
$result = $this->xpath('//h1');
$result = $this->xpath('//h1[@class="page-title"]');
$this->assertEqual('Dynamic title', (string) $result[0]);
// Ensure that titles are cacheable and are escaped normally if the

View file

@ -54,7 +54,7 @@ class SiteMaintenanceTest extends WebTestBase {
);
$this->drupalPostForm('admin/config/development/maintenance', $edit, t('Save configuration'));
$admin_message = t('Operating in maintenance mode. <a href="@url">Go online.</a>', array('@url' => \Drupal::url('system.site_maintenance_mode')));
$admin_message = t('Operating in maintenance mode. <a href=":url">Go online.</a>', array(':url' => \Drupal::url('system.site_maintenance_mode')));
$user_message = t('Operating in maintenance mode.');
$offline_message = t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => $this->config('system.site')->get('name')));
@ -67,10 +67,13 @@ class SiteMaintenanceTest extends WebTestBase {
// Logout and verify that offline message is displayed.
$this->drupalLogout();
$this->drupalGet('');
$this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]);
$this->assertText($offline_message);
$this->drupalGet('node');
$this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]);
$this->assertText($offline_message);
$this->drupalGet('user/register');
$this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]);
$this->assertText($offline_message);
// Verify that user is able to log in.
@ -103,6 +106,7 @@ class SiteMaintenanceTest extends WebTestBase {
// Logout and verify that custom site offline message is displayed.
$this->drupalLogout();
$this->drupalGet('');
$this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]);
$this->assertRaw($offline_message, 'Found the site offline message.');
// Verify that custom site offline message is not displayed on user/password.
@ -121,5 +125,14 @@ class SiteMaintenanceTest extends WebTestBase {
// Log in with temporary login link.
$this->drupalPostForm($path, array(), t('Log in'));
$this->assertText($user_message);
// Regression test to check if title displays in Bartik on maintenance page.
\Drupal::service('theme_handler')->install(array('bartik'));
\Drupal::service('theme_handler')->setDefault('bartik');
// Logout and verify that offline message is displayed in Bartik.
$this->drupalLogout();
$this->drupalGet('');
$this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]);
}
}

View file

@ -18,6 +18,11 @@ use Drupal\system\SystemRequirements;
*/
class StatusTest extends WebTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['update_test_postupdate'];
/**
* {@inheritdoc}
*/
@ -57,6 +62,23 @@ class StatusTest extends WebTestBase {
$this->assertNoLinkByHref(Url::fromRoute('system.php')->toString());
}
// If a module is fully installed no pending updates exists.
$this->assertNoText(t('Out of date'));
// Set the schema version of update_test_postupdate to a lower version, so
// update_test_postupdate_update_8001() needs to be executed.
drupal_set_installed_schema_version('update_test_postupdate', 8000);
$this->drupalGet('admin/reports/status');
$this->assertText(t('Out of date'));
// Now cleanup the executed post update functions.
drupal_set_installed_schema_version('update_test_postupdate', 8001);
/** @var \Drupal\Core\Update\UpdateRegistry $post_update_registry */
$post_update_registry = \Drupal::service('update.post_update_registry');
$post_update_registry->filterOutInvokedUpdatesByModule('update_test_postupdate');
$this->drupalGet('admin/reports/status');
$this->assertText(t('Out of date'));
$this->drupalGet('admin/reports/status/php');
$this->assertResponse(200, 'The phpinfo page is reachable.');
}

View file

@ -96,7 +96,7 @@ class ThemeTest extends WebTestBase {
// Verify logo path examples.
$elements = $this->xpath('//div[contains(@class, :item)]/div[@class=:description]/code', array(
':item' => 'form-item-logo-path',
':item' => 'js-form-item-logo-path',
':description' => 'description',
));
// Expected default values (if all else fails).
@ -123,9 +123,11 @@ class ThemeTest extends WebTestBase {
$this->assertEqual((string) $elements[1], $explicit_file);
$this->assertEqual((string) $elements[2], $local_file);
// Verify the actual 'src' attribute of the logo being output.
// Verify the actual 'src' attribute of the logo being output in a site
// branding block.
$this->drupalPlaceBlock('system_branding_block', ['region' => 'header']);
$this->drupalGet('');
$elements = $this->xpath('//header/a[@rel=:rel]/img', array(
$elements = $this->xpath('//header//a[@rel=:rel]/img', array(
':rel' => 'home',
)
);
@ -175,8 +177,9 @@ class ThemeTest extends WebTestBase {
$fields = $this->xpath($this->constructFieldXpath('name', 'logo_path'));
$uploaded_filename = 'public://' . $fields[0]['value'];
$this->drupalPlaceBlock('system_branding_block', ['region' => 'header']);
$this->drupalGet('');
$elements = $this->xpath('//header/a[@rel=:rel]/img', array(
$elements = $this->xpath('//header//a[@rel=:rel]/img', array(
':rel' => 'home',
)
);
@ -345,9 +348,9 @@ class ThemeTest extends WebTestBase {
*/
function testInstallAndSetAsDefault() {
$this->drupalGet('admin/appearance');
// Bartik is uninstalled in the test profile and has the second "Install and
// Bartik is uninstalled in the test profile and has the third "Install and
// set as default" link.
$this->clickLink(t('Install and set as default'), 1);
$this->clickLink(t('Install and set as default'), 2);
// Test the confirmation message.
$this->assertText('Bartik is now the default theme.');
// Make sure Bartik is now set as the default theme in config.

View file

@ -7,6 +7,7 @@
namespace Drupal\system\Tests\System;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Render\BubbleableMetadata;
@ -103,7 +104,7 @@ class TokenReplaceUnitTest extends TokenReplaceUnitTestBase {
->save();
// Generate and test sanitized tokens.
// Generate and test tokens.
$tests = array();
$tests['[site:name]'] = Html::escape($config->get('name'));
$tests['[site:slogan]'] = $safe_slogan;
@ -129,29 +130,9 @@ class TokenReplaceUnitTest extends TokenReplaceUnitTestBase {
foreach ($tests as $input => $expected) {
$bubbleable_metadata = new BubbleableMetadata();
$output = $this->tokenService->replace($input, array(), array('langcode' => $this->interfaceLanguage->getId()), $bubbleable_metadata);
$this->assertEqual($output, $expected, format_string('Sanitized system site information token %token replaced.', array('%token' => $input)));
$this->assertEqual($output, $expected, new FormattableMarkup('System site information token %token replaced.', ['%token' => $input]));
$this->assertEqual($bubbleable_metadata, $metadata_tests[$input]);
}
// Generate and test unsanitized tokens.
$tests['[site:name]'] = $config->get('name');
$tests['[site:slogan]'] = $config->get('slogan');
foreach ($tests as $input => $expected) {
$output = $this->tokenService->replace($input, array(), array('langcode' => $this->interfaceLanguage->getId(), 'sanitize' => FALSE), $bubbleable_metadata);
$this->assertEqual($output, $expected, format_string('Unsanitized system site information token %token replaced.', array('%token' => $input)));
}
// Check that the results of Token::generate are sanitized properly. This
// does NOT test the cleanliness of every token -- just that the $sanitize
// flag is being passed properly through the call stack and being handled
// correctly by a 'known' token, [site:slogan].
$raw_tokens = array('slogan' => '[site:slogan]');
$generated = $this->tokenService->generate('site', $raw_tokens, [], [], $bubbleable_metadata);
$this->assertEqual($generated['[site:slogan]'], $safe_slogan, 'Token sanitized.');
$generated = $this->tokenService->generate('site', $raw_tokens, array(), array('sanitize' => FALSE), $bubbleable_metadata);
$this->assertEqual($generated['[site:slogan]'], $slogan, 'Unsanitized token generated properly.');
}
/**

Some files were not shown because too many files have changed in this diff Show more