Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace Drupal\Tests\field_ui\Functional;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityFormMode;
|
||||
use Drupal\Core\Entity\Entity\EntityViewMode;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
|
@ -16,7 +19,7 @@ class EntityDisplayModeTest extends BrowserTestBase {
|
|||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public static $modules = ['block', 'entity_test', 'field_ui'];
|
||||
public static $modules = ['block', 'entity_test', 'field_ui', 'node'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -24,6 +27,12 @@ class EntityDisplayModeTest extends BrowserTestBase {
|
|||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a node type.
|
||||
$this->drupalCreateContentType([
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
]);
|
||||
|
||||
$this->drupalPlaceBlock('local_actions_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
@ -68,6 +77,14 @@ class EntityDisplayModeTest extends BrowserTestBase {
|
|||
// Test editing the view mode.
|
||||
$this->drupalGet('admin/structure/display-modes/view/manage/entity_test.' . $edit['id']);
|
||||
|
||||
// Test that the link templates added by field_ui_entity_type_build() are
|
||||
// generating valid routes.
|
||||
$view_mode = EntityViewMode::load('entity_test.' . $edit['id']);
|
||||
$this->assertEquals(Url::fromRoute('entity.entity_view_mode.collection')->toString(), $view_mode->toUrl('collection')->toString());
|
||||
$this->assertEquals(Url::fromRoute('entity.entity_view_mode.add_form', ['entity_type_id' => $view_mode->getTargetType()])->toString(), $view_mode->toUrl('add-form')->toString());
|
||||
$this->assertEquals(Url::fromRoute('entity.entity_view_mode.edit_form', ['entity_view_mode' => $view_mode->id()])->toString(), $view_mode->toUrl('edit-form')->toString());
|
||||
$this->assertEquals(Url::fromRoute('entity.entity_view_mode.delete_form', ['entity_view_mode' => $view_mode->id()])->toString(), $view_mode->toUrl('delete-form')->toString());
|
||||
|
||||
// Test deleting the view mode.
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->assertRaw(t('Are you sure you want to delete the view mode %label?', ['%label' => $edit['label']]));
|
||||
|
@ -114,6 +131,14 @@ class EntityDisplayModeTest extends BrowserTestBase {
|
|||
// Test editing the form mode.
|
||||
$this->drupalGet('admin/structure/display-modes/form/manage/entity_test.' . $edit['id']);
|
||||
|
||||
// Test that the link templates added by field_ui_entity_type_build() are
|
||||
// generating valid routes.
|
||||
$form_mode = EntityFormMode::load('entity_test.' . $edit['id']);
|
||||
$this->assertEquals(Url::fromRoute('entity.entity_form_mode.collection')->toString(), $form_mode->toUrl('collection')->toString());
|
||||
$this->assertEquals(Url::fromRoute('entity.entity_form_mode.add_form', ['entity_type_id' => $form_mode->getTargetType()])->toString(), $form_mode->toUrl('add-form')->toString());
|
||||
$this->assertEquals(Url::fromRoute('entity.entity_form_mode.edit_form', ['entity_form_mode' => $form_mode->id()])->toString(), $form_mode->toUrl('edit-form')->toString());
|
||||
$this->assertEquals(Url::fromRoute('entity.entity_form_mode.delete_form', ['entity_form_mode' => $form_mode->id()])->toString(), $form_mode->toUrl('delete-form')->toString());
|
||||
|
||||
// Test deleting the form mode.
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->assertRaw(t('Are you sure you want to delete the form mode %label?', ['%label' => $edit['label']]));
|
||||
|
@ -121,4 +146,62 @@ class EntityDisplayModeTest extends BrowserTestBase {
|
|||
$this->assertRaw(t('The form mode %label has been deleted.', ['%label' => $edit['label']]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if view modes appear in alphabetical order by visible name.
|
||||
*
|
||||
* The machine name should not be used for sorting.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2858569
|
||||
*/
|
||||
public function testAlphabeticalDisplaySettings() {
|
||||
$this->drupalLogin($this->drupalCreateUser([
|
||||
'access administration pages',
|
||||
'administer content types',
|
||||
'administer display modes',
|
||||
'administer nodes',
|
||||
'administer node fields',
|
||||
'administer node display',
|
||||
'administer node form display',
|
||||
'view the administration theme',
|
||||
]));
|
||||
$this->drupalGet('admin/structure/types/manage/article/display');
|
||||
// Verify that the order of view modes is alphabetical by visible label.
|
||||
// Since the default view modes all have machine names which coincide with
|
||||
// the English labels, they should appear in alphabetical order, by default
|
||||
// if viewing the site in English and if no changes have been made. We will
|
||||
// verify this first.
|
||||
$page_text = $this->getTextContent();
|
||||
$start = strpos($page_text, 'view modes');
|
||||
$pos = $start;
|
||||
$list = ['Full content', 'RSS', 'Search index', 'Search result', 'Teaser'];
|
||||
foreach ($list as $name) {
|
||||
$new_pos = strpos($page_text, $name, $start);
|
||||
$this->assertTrue($new_pos > $pos, 'Order of ' . $name . ' is correct on page');
|
||||
$pos = $new_pos;
|
||||
}
|
||||
// Now that we have verified the original display order, we can change the
|
||||
// label for one of the view modes. If we rename "Teaser" to "Breezer", it
|
||||
// should appear as the first of the listed view modes:
|
||||
// Set new values and enable test plugins.
|
||||
$edit = [
|
||||
'label' => 'Breezer',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/display-modes/view/manage/node.teaser', $edit, 'Save');
|
||||
$this->assertSession()->pageTextContains('Saved the Breezer view mode.');
|
||||
|
||||
// Re-open the display settings for the article content type and verify
|
||||
// that changing "Teaser" to "Breezer" makes it appear before "Full
|
||||
// content".
|
||||
$this->drupalGet('admin/structure/types/manage/article/display');
|
||||
$page_text = $this->getTextContent();
|
||||
$start = strpos($page_text, 'view modes');
|
||||
$pos = $start;
|
||||
$list = ['Breezer', 'Full content'];
|
||||
foreach ($list as $name) {
|
||||
$new_pos = strpos($page_text, $name, $start);
|
||||
$this->assertTrue($new_pos > $pos, 'Order of ' . $name . ' is correct on page');
|
||||
$pos = $new_pos;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field_ui\Functional;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\field_ui\Traits\FieldUiTestTrait;
|
||||
use Drupal\views\Entity\View;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
|
||||
/**
|
||||
* Tests deletion of a field and their dependencies in the UI.
|
||||
*
|
||||
* @group field_ui
|
||||
*/
|
||||
class FieldUIDeleteTest extends BrowserTestBase {
|
||||
|
||||
use FieldUiTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'field_ui', 'field_test', 'block', 'field_test_views'];
|
||||
|
||||
/**
|
||||
* Test views to enable
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public static $testViews = ['test_view_field_delete'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
|
||||
// Create a test user.
|
||||
$admin_user = $this->drupalCreateUser(['access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer users', 'administer account settings', 'administer user display', 'bypass node access']);
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that deletion removes field storages and fields as expected.
|
||||
*/
|
||||
public function testDeleteField() {
|
||||
$field_label = $this->randomMachineName();
|
||||
$field_name_input = 'test';
|
||||
$field_name = 'field_test';
|
||||
|
||||
// Create an additional node type.
|
||||
$type_name1 = strtolower($this->randomMachineName(8)) . '_test';
|
||||
$type1 = $this->drupalCreateContentType(['name' => $type_name1, 'type' => $type_name1]);
|
||||
$type_name1 = $type1->id();
|
||||
|
||||
// Create a new field.
|
||||
$bundle_path1 = 'admin/structure/types/manage/' . $type_name1;
|
||||
$this->fieldUIAddNewField($bundle_path1, $field_name_input, $field_label);
|
||||
|
||||
// Create an additional node type.
|
||||
$type_name2 = strtolower($this->randomMachineName(8)) . '_test';
|
||||
$type2 = $this->drupalCreateContentType(['name' => $type_name2, 'type' => $type_name2]);
|
||||
$type_name2 = $type2->id();
|
||||
|
||||
// Add a field to the second node type.
|
||||
$bundle_path2 = 'admin/structure/types/manage/' . $type_name2;
|
||||
$this->fieldUIAddExistingField($bundle_path2, $field_name, $field_label);
|
||||
|
||||
\Drupal::service('module_installer')->install(['views']);
|
||||
ViewTestData::createTestViews(get_class($this), ['field_test_views']);
|
||||
|
||||
$view = View::load('test_view_field_delete');
|
||||
$this->assertNotNull($view);
|
||||
$this->assertTrue($view->status());
|
||||
// Test that the View depends on the field.
|
||||
$dependencies = $view->getDependencies() + ['config' => []];
|
||||
$this->assertTrue(in_array("field.storage.node.$field_name", $dependencies['config']));
|
||||
|
||||
// Check the config dependencies of the first field, the field storage must
|
||||
// not be shown as being deleted yet.
|
||||
$this->drupalGet("$bundle_path1/fields/node.$type_name1.$field_name/delete");
|
||||
$this->assertNoText(t('The listed configuration will be deleted.'));
|
||||
$this->assertNoText(t('View'));
|
||||
$this->assertNoText('test_view_field_delete');
|
||||
|
||||
// Delete the first field.
|
||||
$this->fieldUIDeleteField($bundle_path1, "node.$type_name1.$field_name", $field_label, $type_name1);
|
||||
|
||||
// Check that the field was deleted.
|
||||
$this->assertNull(FieldConfig::loadByName('node', $type_name1, $field_name), 'Field was deleted.');
|
||||
// Check that the field storage was not deleted
|
||||
$this->assertNotNull(FieldStorageConfig::loadByName('node', $field_name), 'Field storage was not deleted.');
|
||||
|
||||
// Check the config dependencies of the first field.
|
||||
$this->drupalGet("$bundle_path2/fields/node.$type_name2.$field_name/delete");
|
||||
$this->assertText(t('The listed configuration will be updated.'));
|
||||
$this->assertText(t('View'));
|
||||
$this->assertText('test_view_field_delete');
|
||||
|
||||
$xml = $this->cssSelect('#edit-entity-deletes');
|
||||
// Test that nothing is scheduled for deletion.
|
||||
$this->assertFalse(isset($xml[0]), 'The field currently being deleted is not shown in the entity deletions.');
|
||||
|
||||
// Delete the second field.
|
||||
$this->fieldUIDeleteField($bundle_path2, "node.$type_name2.$field_name", $field_label, $type_name2);
|
||||
|
||||
// Check that the field was deleted.
|
||||
$this->assertNull(FieldConfig::loadByName('node', $type_name2, $field_name), 'Field was deleted.');
|
||||
// Check that the field storage was deleted too.
|
||||
$this->assertNull(FieldStorageConfig::loadByName('node', $field_name), 'Field storage was deleted.');
|
||||
|
||||
// Test that the View isn't deleted and has been disabled.
|
||||
$view = View::load('test_view_field_delete');
|
||||
$this->assertNotNull($view);
|
||||
$this->assertFalse($view->status());
|
||||
// Test that the View no longer depends on the deleted field.
|
||||
$dependencies = $view->getDependencies() + ['config' => []];
|
||||
$this->assertFalse(in_array("field.storage.node.$field_name", $dependencies['config']));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,766 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field_ui\Functional;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
|
||||
use Drupal\Tests\field_ui\Traits\FieldUiTestTrait;
|
||||
|
||||
/**
|
||||
* Tests the Field UI "Manage fields" screen.
|
||||
*
|
||||
* @group field_ui
|
||||
*/
|
||||
class ManageFieldsFunctionalTest extends BrowserTestBase {
|
||||
|
||||
use FieldUiTestTrait;
|
||||
use EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'field_ui', 'field_test', 'taxonomy', 'image', 'block'];
|
||||
|
||||
/**
|
||||
* The ID of the custom content type created for testing.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $contentType;
|
||||
|
||||
/**
|
||||
* The label for a random field to be created for testing.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldLabel;
|
||||
|
||||
/**
|
||||
* The input name of a random field to be created for testing.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldNameInput;
|
||||
|
||||
/**
|
||||
* The name of a random field to be created for testing.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
$this->drupalPlaceBlock('local_actions_block');
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
|
||||
// Create a test user.
|
||||
$admin_user = $this->drupalCreateUser(['access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer taxonomy', 'administer taxonomy_term fields', 'administer taxonomy_term display', 'administer users', 'administer account settings', 'administer user display', 'bypass node access']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Create content type, with underscores.
|
||||
$type_name = strtolower($this->randomMachineName(8)) . '_test';
|
||||
$type = $this->drupalCreateContentType(['name' => $type_name, 'type' => $type_name]);
|
||||
$this->contentType = $type->id();
|
||||
|
||||
// Create random field name with markup to test escaping.
|
||||
$this->fieldLabel = '<em>' . $this->randomMachineName(8) . '</em>';
|
||||
$this->fieldNameInput = strtolower($this->randomMachineName(8));
|
||||
$this->fieldName = 'field_' . $this->fieldNameInput;
|
||||
|
||||
// Create Basic page and Article node types.
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
// Create a vocabulary named "Tags".
|
||||
$vocabulary = Vocabulary::create([
|
||||
'name' => 'Tags',
|
||||
'vid' => 'tags',
|
||||
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
]);
|
||||
$vocabulary->save();
|
||||
|
||||
$handler_settings = [
|
||||
'target_bundles' => [
|
||||
$vocabulary->id() => $vocabulary->id(),
|
||||
],
|
||||
];
|
||||
$this->createEntityReferenceField('node', 'article', 'field_' . $vocabulary->id(), 'Tags', 'taxonomy_term', 'default', $handler_settings);
|
||||
|
||||
entity_get_form_display('node', 'article', 'default')
|
||||
->setComponent('field_' . $vocabulary->id())
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the field CRUD tests.
|
||||
*
|
||||
* In order to act on the same fields, and not create the fields over and over
|
||||
* again the following tests create, update and delete the same fields.
|
||||
*/
|
||||
public function testCRUDFields() {
|
||||
$this->manageFieldsPage();
|
||||
$this->createField();
|
||||
$this->updateField();
|
||||
$this->addExistingField();
|
||||
$this->cardinalitySettings();
|
||||
$this->fieldListAdminPage();
|
||||
$this->deleteField();
|
||||
$this->addPersistentFieldStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the manage fields page.
|
||||
*
|
||||
* @param string $type
|
||||
* (optional) The name of a content type.
|
||||
*/
|
||||
public function manageFieldsPage($type = '') {
|
||||
$type = empty($type) ? $this->contentType : $type;
|
||||
$this->drupalGet('admin/structure/types/manage/' . $type . '/fields');
|
||||
// Check all table columns.
|
||||
$table_headers = [
|
||||
t('Label'),
|
||||
t('Machine name'),
|
||||
t('Field type'),
|
||||
t('Operations'),
|
||||
];
|
||||
foreach ($table_headers as $table_header) {
|
||||
// We check that the label appear in the table headings.
|
||||
$this->assertRaw($table_header . '</th>', format_string('%table_header table header was found.', ['%table_header' => $table_header]));
|
||||
}
|
||||
|
||||
// Test the "Add field" action link.
|
||||
$this->assertLink('Add field');
|
||||
|
||||
// Assert entity operations for all fields.
|
||||
$number_of_links = 3;
|
||||
$number_of_links_found = 0;
|
||||
$operation_links = $this->xpath('//ul[@class = "dropbutton"]/li/a');
|
||||
$url = base_path() . "admin/structure/types/manage/$type/fields/node.$type.body";
|
||||
|
||||
foreach ($operation_links as $link) {
|
||||
switch ($link->getAttribute('title')) {
|
||||
case 'Edit field settings.':
|
||||
$this->assertIdentical($url, $link->getAttribute('href'));
|
||||
$number_of_links_found++;
|
||||
break;
|
||||
case 'Edit storage settings.':
|
||||
$this->assertIdentical("$url/storage", $link->getAttribute('href'));
|
||||
$number_of_links_found++;
|
||||
break;
|
||||
case 'Delete field.':
|
||||
$this->assertIdentical("$url/delete", $link->getAttribute('href'));
|
||||
$number_of_links_found++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertEqual($number_of_links, $number_of_links_found);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding a new field.
|
||||
*
|
||||
* @todo Assert properties can bet set in the form and read back in
|
||||
* $field_storage and $fields.
|
||||
*/
|
||||
public function createField() {
|
||||
// Create a test field.
|
||||
$this->fieldUIAddNewField('admin/structure/types/manage/' . $this->contentType, $this->fieldNameInput, $this->fieldLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests editing an existing field.
|
||||
*/
|
||||
public function updateField() {
|
||||
$field_id = 'node.' . $this->contentType . '.' . $this->fieldName;
|
||||
// Go to the field edit page.
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/' . $field_id . '/storage');
|
||||
$this->assertEscaped($this->fieldLabel);
|
||||
|
||||
// Populate the field settings with new settings.
|
||||
$string = 'updated dummy test string';
|
||||
$edit = [
|
||||
'settings[test_field_storage_setting]' => $string,
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save field settings'));
|
||||
|
||||
// Go to the field edit page.
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/' . $field_id);
|
||||
$edit = [
|
||||
'settings[test_field_setting]' => $string,
|
||||
];
|
||||
$this->assertText(t('Default value'), 'Default value heading is shown');
|
||||
$this->drupalPostForm(NULL, $edit, t('Save settings'));
|
||||
|
||||
// Assert the field settings are correct.
|
||||
$this->assertFieldSettings($this->contentType, $this->fieldName, $string);
|
||||
|
||||
// Assert redirection back to the "manage fields" page.
|
||||
$this->assertUrl('admin/structure/types/manage/' . $this->contentType . '/fields');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding an existing field in another content type.
|
||||
*/
|
||||
public function addExistingField() {
|
||||
// Check "Re-use existing field" appears.
|
||||
$this->drupalGet('admin/structure/types/manage/page/fields/add-field');
|
||||
$this->assertRaw(t('Re-use an existing field'), '"Re-use existing field" was found.');
|
||||
|
||||
// Check that fields of other entity types (here, the 'comment_body' field)
|
||||
// do not show up in the "Re-use existing field" list.
|
||||
$this->assertFalse($this->xpath('//select[@id="edit-existing-storage-name"]//option[@value="comment"]'), 'The list of options respects entity type restrictions.');
|
||||
// Validate the FALSE assertion above by also testing a valid one.
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-existing-storage-name"]//option[@value=:field_name]', [':field_name' => $this->fieldName]), 'The list of options shows a valid option.');
|
||||
|
||||
// Add a new field based on an existing field.
|
||||
$this->fieldUIAddExistingField("admin/structure/types/manage/page", $this->fieldName, $this->fieldLabel . '_2');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the cardinality settings of a field.
|
||||
*
|
||||
* We do not test if the number can be submitted with anything else than a
|
||||
* numeric value. That is tested already in FormTest::testNumber().
|
||||
*/
|
||||
public function cardinalitySettings() {
|
||||
$field_edit_path = 'admin/structure/types/manage/article/fields/node.article.body/storage';
|
||||
|
||||
// Assert the cardinality other field cannot be empty when cardinality is
|
||||
// set to 'number'.
|
||||
$edit = [
|
||||
'cardinality' => 'number',
|
||||
'cardinality_number' => '',
|
||||
];
|
||||
$this->drupalPostForm($field_edit_path, $edit, t('Save field settings'));
|
||||
$this->assertText('Number of values is required.');
|
||||
|
||||
// Submit a custom number.
|
||||
$edit = [
|
||||
'cardinality' => 'number',
|
||||
'cardinality_number' => 6,
|
||||
];
|
||||
$this->drupalPostForm($field_edit_path, $edit, t('Save field settings'));
|
||||
$this->assertText('Updated field Body field settings.');
|
||||
$this->drupalGet($field_edit_path);
|
||||
$this->assertFieldByXPath("//select[@name='cardinality']", 'number');
|
||||
$this->assertFieldByXPath("//input[@name='cardinality_number']", 6);
|
||||
|
||||
// Check that tabs displayed.
|
||||
$this->assertLink(t('Edit'));
|
||||
$this->assertLinkByHref('admin/structure/types/manage/article/fields/node.article.body');
|
||||
$this->assertLink(t('Field settings'));
|
||||
$this->assertLinkByHref($field_edit_path);
|
||||
|
||||
// Add two entries in the body.
|
||||
$edit = ['title[0][value]' => 'Cardinality', 'body[0][value]' => 'Body 1', 'body[1][value]' => 'Body 2'];
|
||||
$this->drupalPostForm('node/add/article', $edit, 'Save');
|
||||
|
||||
// Assert that you can't set the cardinality to a lower number than the
|
||||
// highest delta of this field.
|
||||
$edit = [
|
||||
'cardinality' => 'number',
|
||||
'cardinality_number' => 1,
|
||||
];
|
||||
$this->drupalPostForm($field_edit_path, $edit, t('Save field settings'));
|
||||
$this->assertRaw(t('There is @count entity with @delta or more values in this field.', ['@count' => 1, '@delta' => 2]), 'Correctly failed to set cardinality lower than highest delta.');
|
||||
|
||||
// Create a second entity with three values.
|
||||
$edit = ['title[0][value]' => 'Cardinality 3', 'body[0][value]' => 'Body 1', 'body[1][value]' => 'Body 2', 'body[2][value]' => 'Body 3'];
|
||||
$this->drupalPostForm('node/add/article', $edit, 'Save');
|
||||
|
||||
// Set to unlimited.
|
||||
$edit = [
|
||||
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
|
||||
];
|
||||
$this->drupalPostForm($field_edit_path, $edit, t('Save field settings'));
|
||||
$this->assertText('Updated field Body field settings.');
|
||||
$this->drupalGet($field_edit_path);
|
||||
$this->assertFieldByXPath("//select[@name='cardinality']", FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
$this->assertFieldByXPath("//input[@name='cardinality_number']", 1);
|
||||
|
||||
// Assert that you can't set the cardinality to a lower number then the
|
||||
// highest delta of this field but can set it to the same.
|
||||
$edit = [
|
||||
'cardinality' => 'number',
|
||||
'cardinality_number' => 1,
|
||||
];
|
||||
$this->drupalPostForm($field_edit_path, $edit, t('Save field settings'));
|
||||
$this->assertRaw(t('There are @count entities with @delta or more values in this field.', ['@count' => 2, '@delta' => 2]), 'Correctly failed to set cardinality lower than highest delta.');
|
||||
|
||||
$edit = [
|
||||
'cardinality' => 'number',
|
||||
'cardinality_number' => 2,
|
||||
];
|
||||
$this->drupalPostForm($field_edit_path, $edit, t('Save field settings'));
|
||||
$this->assertRaw(t('There is @count entity with @delta or more values in this field.', ['@count' => 1, '@delta' => 3]), 'Correctly failed to set cardinality lower than highest delta.');
|
||||
|
||||
$edit = [
|
||||
'cardinality' => 'number',
|
||||
'cardinality_number' => 3,
|
||||
];
|
||||
$this->drupalPostForm($field_edit_path, $edit, t('Save field settings'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deleting a field from the field edit form.
|
||||
*/
|
||||
protected function deleteField() {
|
||||
// Delete the field.
|
||||
$field_id = 'node.' . $this->contentType . '.' . $this->fieldName;
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/' . $field_id);
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that persistent field storage appears in the field UI.
|
||||
*/
|
||||
protected function addPersistentFieldStorage() {
|
||||
$field_storage = FieldStorageConfig::loadByName('node', $this->fieldName);
|
||||
// Persist the field storage even if there are no fields.
|
||||
$field_storage->set('persist_with_no_fields', TRUE)->save();
|
||||
// Delete all instances of the field.
|
||||
foreach ($field_storage->getBundles() as $node_type) {
|
||||
// Delete all the body field instances.
|
||||
$this->drupalGet('admin/structure/types/manage/' . $node_type . '/fields/node.' . $node_type . '.' . $this->fieldName);
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
}
|
||||
// Check "Re-use existing field" appears.
|
||||
$this->drupalGet('admin/structure/types/manage/page/fields/add-field');
|
||||
$this->assertRaw(t('Re-use an existing field'), '"Re-use existing field" was found.');
|
||||
|
||||
// Ensure that we test with a label that contains HTML.
|
||||
$label = $this->randomString(4) . '<br/>' . $this->randomString(4);
|
||||
// Add a new field for the orphaned storage.
|
||||
$this->fieldUIAddExistingField("admin/structure/types/manage/page", $this->fieldName, $label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts field settings are as expected.
|
||||
*
|
||||
* @param $bundle
|
||||
* The bundle name for the field.
|
||||
* @param $field_name
|
||||
* The field name for the field.
|
||||
* @param $string
|
||||
* The settings text.
|
||||
* @param $entity_type
|
||||
* The entity type for the field.
|
||||
*/
|
||||
public function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') {
|
||||
// Assert field storage settings.
|
||||
$field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);
|
||||
$this->assertTrue($field_storage->getSetting('test_field_storage_setting') == $string, 'Field storage settings were found.');
|
||||
|
||||
// Assert field settings.
|
||||
$field = FieldConfig::loadByName($entity_type, $bundle, $field_name);
|
||||
$this->assertTrue($field->getSetting('test_field_setting') == $string, 'Field settings were found.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the 'field_prefix' setting works on Field UI.
|
||||
*/
|
||||
public function testFieldPrefix() {
|
||||
// Change default field prefix.
|
||||
$field_prefix = strtolower($this->randomMachineName(10));
|
||||
$this->config('field_ui.settings')->set('field_prefix', $field_prefix)->save();
|
||||
|
||||
// Create a field input and label exceeding the new maxlength, which is 22.
|
||||
$field_exceed_max_length_label = $this->randomString(23);
|
||||
$field_exceed_max_length_input = $this->randomMachineName(23);
|
||||
|
||||
// Try to create the field.
|
||||
$edit = [
|
||||
'label' => $field_exceed_max_length_label,
|
||||
'field_name' => $field_exceed_max_length_input,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/types/manage/' . $this->contentType . '/fields/add-field', $edit, t('Save and continue'));
|
||||
$this->assertText('Machine-readable name cannot be longer than 22 characters but is currently 23 characters long.');
|
||||
|
||||
// Create a valid field.
|
||||
$this->fieldUIAddNewField('admin/structure/types/manage/' . $this->contentType, $this->fieldNameInput, $this->fieldLabel);
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/node.' . $this->contentType . '.' . $field_prefix . $this->fieldNameInput);
|
||||
$this->assertText(format_string('@label settings for @type', ['@label' => $this->fieldLabel, '@type' => $this->contentType]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that default value is correctly validated and saved.
|
||||
*/
|
||||
public function testDefaultValue() {
|
||||
// Create a test field storage and field.
|
||||
$field_name = 'test';
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'test_field',
|
||||
])->save();
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $this->contentType,
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
entity_get_form_display('node', $this->contentType, 'default')
|
||||
->setComponent($field_name)
|
||||
->save();
|
||||
|
||||
$admin_path = 'admin/structure/types/manage/' . $this->contentType . '/fields/' . $field->id();
|
||||
$element_id = "edit-default-value-input-$field_name-0-value";
|
||||
$element_name = "default_value_input[{$field_name}][0][value]";
|
||||
$this->drupalGet($admin_path);
|
||||
$this->assertFieldById($element_id, '', 'The default value widget was empty.');
|
||||
|
||||
// Check that invalid default values are rejected.
|
||||
$edit = [$element_name => '-1'];
|
||||
$this->drupalPostForm($admin_path, $edit, t('Save settings'));
|
||||
$this->assertText("$field_name does not accept the value -1", 'Form validation failed.');
|
||||
|
||||
// Check that the default value is saved.
|
||||
$edit = [$element_name => '1'];
|
||||
$this->drupalPostForm($admin_path, $edit, t('Save settings'));
|
||||
$this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
|
||||
$field = FieldConfig::loadByName('node', $this->contentType, $field_name);
|
||||
$this->assertEqual($field->getDefaultValueLiteral(), [['value' => 1]], 'The default value was correctly saved.');
|
||||
|
||||
// Check that the default value shows up in the form
|
||||
$this->drupalGet($admin_path);
|
||||
$this->assertFieldById($element_id, '1', 'The default value widget was displayed with the correct value.');
|
||||
|
||||
// Check that the default value can be emptied.
|
||||
$edit = [$element_name => ''];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save settings'));
|
||||
$this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
|
||||
$field = FieldConfig::loadByName('node', $this->contentType, $field_name);
|
||||
$this->assertEqual($field->getDefaultValueLiteral(), [], 'The default value was correctly saved.');
|
||||
|
||||
// Check that the default value can be empty when the field is marked as
|
||||
// required and can store unlimited values.
|
||||
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
|
||||
$field_storage->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
$field_storage->save();
|
||||
|
||||
$this->drupalGet($admin_path);
|
||||
$edit = [
|
||||
'required' => 1,
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save settings'));
|
||||
|
||||
$this->drupalGet($admin_path);
|
||||
$this->drupalPostForm(NULL, [], t('Save settings'));
|
||||
$this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
|
||||
$field = FieldConfig::loadByName('node', $this->contentType, $field_name);
|
||||
$this->assertEqual($field->getDefaultValueLiteral(), [], 'The default value was correctly saved.');
|
||||
|
||||
// Check that the default widget is used when the field is hidden.
|
||||
entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
|
||||
->removeComponent($field_name)->save();
|
||||
$this->drupalGet($admin_path);
|
||||
$this->assertFieldById($element_id, '', 'The default value widget was displayed when field is hidden.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that deletion removes field storages and fields as expected.
|
||||
*/
|
||||
public function testDeleteField() {
|
||||
// Create a new field.
|
||||
$bundle_path1 = 'admin/structure/types/manage/' . $this->contentType;
|
||||
$this->fieldUIAddNewField($bundle_path1, $this->fieldNameInput, $this->fieldLabel);
|
||||
|
||||
// Create an additional node type.
|
||||
$type_name2 = strtolower($this->randomMachineName(8)) . '_test';
|
||||
$type2 = $this->drupalCreateContentType(['name' => $type_name2, 'type' => $type_name2]);
|
||||
$type_name2 = $type2->id();
|
||||
|
||||
// Add a field to the second node type.
|
||||
$bundle_path2 = 'admin/structure/types/manage/' . $type_name2;
|
||||
$this->fieldUIAddExistingField($bundle_path2, $this->fieldName, $this->fieldLabel);
|
||||
|
||||
// Delete the first field.
|
||||
$this->fieldUIDeleteField($bundle_path1, "node.$this->contentType.$this->fieldName", $this->fieldLabel, $this->contentType);
|
||||
|
||||
// Check that the field was deleted.
|
||||
$this->assertNull(FieldConfig::loadByName('node', $this->contentType, $this->fieldName), 'Field was deleted.');
|
||||
// Check that the field storage was not deleted
|
||||
$this->assertNotNull(FieldStorageConfig::loadByName('node', $this->fieldName), 'Field storage was not deleted.');
|
||||
|
||||
// Delete the second field.
|
||||
$this->fieldUIDeleteField($bundle_path2, "node.$type_name2.$this->fieldName", $this->fieldLabel, $type_name2);
|
||||
|
||||
// Check that the field was deleted.
|
||||
$this->assertNull(FieldConfig::loadByName('node', $type_name2, $this->fieldName), 'Field was deleted.');
|
||||
// Check that the field storage was deleted too.
|
||||
$this->assertNull(FieldStorageConfig::loadByName('node', $this->fieldName), 'Field storage was deleted.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Field UI respects disallowed field names.
|
||||
*/
|
||||
public function testDisallowedFieldNames() {
|
||||
// Reset the field prefix so we can test properly.
|
||||
$this->config('field_ui.settings')->set('field_prefix', '')->save();
|
||||
|
||||
$label = 'Disallowed field';
|
||||
$edit = [
|
||||
'label' => $label,
|
||||
'new_storage_type' => 'test_field',
|
||||
];
|
||||
|
||||
// Try with an entity key.
|
||||
$edit['field_name'] = 'title';
|
||||
$bundle_path = 'admin/structure/types/manage/' . $this->contentType;
|
||||
$this->drupalPostForm("$bundle_path/fields/add-field", $edit, t('Save and continue'));
|
||||
$this->assertText(t('The machine-readable name is already in use. It must be unique.'));
|
||||
|
||||
// Try with a base field.
|
||||
$edit['field_name'] = 'sticky';
|
||||
$bundle_path = 'admin/structure/types/manage/' . $this->contentType;
|
||||
$this->drupalPostForm("$bundle_path/fields/add-field", $edit, t('Save and continue'));
|
||||
$this->assertText(t('The machine-readable name is already in use. It must be unique.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Field UI respects locked fields.
|
||||
*/
|
||||
public function testLockedField() {
|
||||
// Create a locked field and attach it to a bundle. We need to do this
|
||||
// programmatically as there's no way to create a locked field through UI.
|
||||
$field_name = strtolower($this->randomMachineName(8));
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'test_field',
|
||||
'cardinality' => 1,
|
||||
'locked' => TRUE,
|
||||
]);
|
||||
$field_storage->save();
|
||||
FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => $this->contentType,
|
||||
])->save();
|
||||
entity_get_form_display('node', $this->contentType, 'default')
|
||||
->setComponent($field_name, [
|
||||
'type' => 'test_field_widget',
|
||||
])
|
||||
->save();
|
||||
|
||||
// Check that the links for edit and delete are not present.
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields');
|
||||
$locked = $this->xpath('//tr[@id=:field_name]/td[4]', [':field_name' => $field_name]);
|
||||
$this->assertSame('Locked', $locked[0]->getHtml(), 'Field is marked as Locked in the UI');
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/node.' . $this->contentType . '.' . $field_name . '/delete');
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Field UI respects the 'no_ui' flag in the field type definition.
|
||||
*/
|
||||
public function testHiddenFields() {
|
||||
// Check that the field type is not available in the 'add new field' row.
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/add-field');
|
||||
$this->assertFalse($this->xpath('//select[@id="edit-new-storage-type"]//option[@value="hidden_test_field"]'), "The 'add new field' select respects field types 'no_ui' property.");
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-new-storage-type"]//option[@value="shape"]'), "The 'add new field' select shows a valid option.");
|
||||
|
||||
// Create a field storage and a field programmatically.
|
||||
$field_name = 'hidden_test_field';
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'node',
|
||||
'type' => $field_name,
|
||||
])->save();
|
||||
$field = [
|
||||
'field_name' => $field_name,
|
||||
'bundle' => $this->contentType,
|
||||
'entity_type' => 'node',
|
||||
'label' => t('Hidden field'),
|
||||
];
|
||||
FieldConfig::create($field)->save();
|
||||
entity_get_form_display('node', $this->contentType, 'default')
|
||||
->setComponent($field_name)
|
||||
->save();
|
||||
$this->assertTrue(FieldConfig::load('node.' . $this->contentType . '.' . $field_name), format_string('A field of the field storage %field was created programmatically.', ['%field' => $field_name]));
|
||||
|
||||
// Check that the newly added field appears on the 'Manage Fields'
|
||||
// screen.
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields');
|
||||
$this->assertFieldByXPath('//table[@id="field-overview"]//tr[@id="hidden-test-field"]//td[1]', $field['label'], 'Field was created and appears in the overview page.');
|
||||
|
||||
// Check that the field does not appear in the 're-use existing field' row
|
||||
// on other bundles.
|
||||
$this->drupalGet('admin/structure/types/manage/page/fields/add-field');
|
||||
$this->assertFalse($this->xpath('//select[@id="edit-existing-storage-name"]//option[@value=:field_name]', [':field_name' => $field_name]), "The 're-use existing field' select respects field types 'no_ui' property.");
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-existing-storage-name"]//option[@value=:field_name]', [':field_name' => 'field_tags']), "The 're-use existing field' select shows a valid option.");
|
||||
|
||||
// Check that non-configurable fields are not available.
|
||||
$field_types = \Drupal::service('plugin.manager.field.field_type')->getDefinitions();
|
||||
foreach ($field_types as $field_type => $definition) {
|
||||
if (empty($definition['no_ui'])) {
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-new-storage-type"]//option[@value=:field_type]', [':field_type' => $field_type]), new FormattableMarkup('Configurable field type @field_type is available.', ['@field_type' => $field_type]));
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($this->xpath('//select[@id="edit-new-storage-type"]//option[@value=:field_type]', [':field_type' => $field_type]), new FormattableMarkup('Non-configurable field type @field_type is not available.', ['@field_type' => $field_type]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a duplicate field name is caught by validation.
|
||||
*/
|
||||
public function testDuplicateFieldName() {
|
||||
// field_tags already exists, so we're expecting an error when trying to
|
||||
// create a new field with the same name.
|
||||
$edit = [
|
||||
'field_name' => 'tags',
|
||||
'label' => $this->randomMachineName(),
|
||||
'new_storage_type' => 'entity_reference',
|
||||
];
|
||||
$url = 'admin/structure/types/manage/' . $this->contentType . '/fields/add-field';
|
||||
$this->drupalPostForm($url, $edit, t('Save and continue'));
|
||||
|
||||
$this->assertText(t('The machine-readable name is already in use. It must be unique.'));
|
||||
$this->assertUrl($url, [], 'Stayed on the same page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that external URLs in the 'destinations' query parameter are blocked.
|
||||
*/
|
||||
public function testExternalDestinations() {
|
||||
$options = [
|
||||
'query' => ['destinations' => ['http://example.com']],
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.body/storage', [], 'Save field settings', $options);
|
||||
// The external redirect should not fire.
|
||||
$this->assertUrl('admin/structure/types/manage/article/fields/node.article.body/storage', $options);
|
||||
$this->assertResponse(200);
|
||||
$this->assertRaw('Attempt to update field <em class="placeholder">Body</em> failed: <em class="placeholder">The internal path component 'http://example.com' is external. You are not allowed to specify an external URL together with internal:/.</em>.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that deletion removes field storages and fields as expected for a term.
|
||||
*/
|
||||
public function testDeleteTaxonomyField() {
|
||||
// Create a new field.
|
||||
$bundle_path = 'admin/structure/taxonomy/manage/tags/overview';
|
||||
|
||||
$this->fieldUIAddNewField($bundle_path, $this->fieldNameInput, $this->fieldLabel);
|
||||
|
||||
// Delete the field.
|
||||
$this->fieldUIDeleteField($bundle_path, "taxonomy_term.tags.$this->fieldName", $this->fieldLabel, 'Tags');
|
||||
|
||||
// Check that the field was deleted.
|
||||
$this->assertNull(FieldConfig::loadByName('taxonomy_term', 'tags', $this->fieldName), 'Field was deleted.');
|
||||
// Check that the field storage was deleted too.
|
||||
$this->assertNull(FieldStorageConfig::loadByName('taxonomy_term', $this->fieldName), 'Field storage was deleted.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that help descriptions render valid HTML.
|
||||
*/
|
||||
public function testHelpDescriptions() {
|
||||
// Create an image field
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => 'field_image',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'image',
|
||||
])->save();
|
||||
|
||||
FieldConfig::create([
|
||||
'field_name' => 'field_image',
|
||||
'entity_type' => 'node',
|
||||
'label' => 'Image',
|
||||
'bundle' => 'article',
|
||||
])->save();
|
||||
|
||||
entity_get_form_display('node', 'article', 'default')->setComponent('field_image')->save();
|
||||
|
||||
$edit = [
|
||||
'description' => '<strong>Test with an upload field.',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_image', $edit, t('Save settings'));
|
||||
|
||||
// Check that hook_field_widget_form_alter() does believe this is the
|
||||
// default value form.
|
||||
$this->drupalGet('admin/structure/types/manage/article/fields/node.article.field_tags');
|
||||
$this->assertText('From hook_field_widget_form_alter(): Default form is true.', 'Default value form in hook_field_widget_form_alter().');
|
||||
|
||||
$edit = [
|
||||
'description' => '<em>Test with a non upload field.',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_tags', $edit, t('Save settings'));
|
||||
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertRaw('<strong>Test with an upload field.</strong>');
|
||||
$this->assertRaw('<em>Test with a non upload field.</em>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the field list administration page operates correctly.
|
||||
*/
|
||||
public function fieldListAdminPage() {
|
||||
$this->drupalGet('admin/reports/fields');
|
||||
$this->assertText($this->fieldName, 'Field name is displayed in field list.');
|
||||
$this->assertLinkByHref('admin/structure/types/manage/' . $this->contentType . '/fields');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the "preconfigured field" functionality.
|
||||
*
|
||||
* @see \Drupal\Core\Field\PreconfiguredFieldUiOptionsInterface
|
||||
*/
|
||||
public function testPreconfiguredFields() {
|
||||
$this->drupalGet('admin/structure/types/manage/article/fields/add-field');
|
||||
|
||||
// Check that the preconfigured field option exist alongside the regular
|
||||
// field type option.
|
||||
$this->assertOption('edit-new-storage-type', 'field_ui:test_field_with_preconfigured_options:custom_options');
|
||||
$this->assertOption('edit-new-storage-type', 'test_field_with_preconfigured_options');
|
||||
|
||||
// Add a field with every possible preconfigured value.
|
||||
$this->fieldUIAddNewField(NULL, 'test_custom_options', 'Test label', 'field_ui:test_field_with_preconfigured_options:custom_options');
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'field_test_custom_options');
|
||||
$this->assertEqual($field_storage->getCardinality(), FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
$this->assertEqual($field_storage->getSetting('test_field_storage_setting'), 'preconfigured_storage_setting');
|
||||
|
||||
$field = FieldConfig::loadByName('node', 'article', 'field_test_custom_options');
|
||||
$this->assertTrue($field->isRequired());
|
||||
$this->assertEqual($field->getSetting('test_field_setting'), 'preconfigured_field_setting');
|
||||
|
||||
$form_display = entity_get_form_display('node', 'article', 'default');
|
||||
$this->assertEqual($form_display->getComponent('field_test_custom_options')['type'], 'test_field_widget_multiple');
|
||||
$view_display = entity_get_display('node', 'article', 'default');
|
||||
$this->assertEqual($view_display->getComponent('field_test_custom_options')['type'], 'field_test_multiple');
|
||||
$this->assertEqual($view_display->getComponent('field_test_custom_options')['settings']['test_formatter_setting_multiple'], 'altered dummy test string');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the access to non-existent field URLs.
|
||||
*/
|
||||
public function testNonExistentFieldUrls() {
|
||||
$field_id = 'node.foo.bar';
|
||||
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/' . $field_id);
|
||||
$this->assertResponse(404);
|
||||
|
||||
$this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/' . $field_id . '/storage');
|
||||
$this->assertResponse(404);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,14 +3,14 @@
|
|||
namespace Drupal\Tests\field_ui\FunctionalJavascript;
|
||||
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
|
||||
|
||||
/**
|
||||
* Tests the UI for entity displays.
|
||||
*
|
||||
* @group field_ui
|
||||
*/
|
||||
class EntityDisplayTest extends JavascriptTestBase {
|
||||
class EntityDisplayTest extends WebDriverTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -25,9 +25,9 @@ class EntityDisplayTest extends JavascriptTestBase {
|
|||
|
||||
$entity = EntityTest::create([
|
||||
'name' => 'The name for this entity',
|
||||
'field_test_text' => [[
|
||||
'value' => 'The field test text value',
|
||||
]],
|
||||
'field_test_text' => [
|
||||
['value' => 'The field test text value'],
|
||||
],
|
||||
]);
|
||||
$entity->save();
|
||||
$this->drupalLogin($this->drupalCreateUser([
|
||||
|
@ -50,7 +50,8 @@ class EntityDisplayTest extends JavascriptTestBase {
|
|||
|
||||
$this->drupalGet('entity_test/structure/entity_test/form-display');
|
||||
$this->assertTrue($this->assertSession()->optionExists('fields[field_test_text][region]', 'content')->isSelected());
|
||||
|
||||
$this->getSession()->getPage()->pressButton('Show row weights');
|
||||
$this->assertSession()->waitForElementVisible('css', '[name="fields[field_test_text][region]"]');
|
||||
$this->getSession()->getPage()->selectFieldOption('fields[field_test_text][region]', 'hidden');
|
||||
$this->assertSession()->assertWaitOnAjaxRequest();
|
||||
$this->assertTrue($this->assertSession()->optionExists('fields[field_test_text][region]', 'hidden')->isSelected());
|
||||
|
@ -72,6 +73,8 @@ class EntityDisplayTest extends JavascriptTestBase {
|
|||
|
||||
$this->drupalGet('entity_test/structure/entity_test/display');
|
||||
$this->assertSession()->elementExists('css', '.region-content-message.region-empty');
|
||||
$this->getSession()->getPage()->pressButton('Show row weights');
|
||||
$this->assertSession()->waitForElementVisible('css', '[name="fields[field_test_text][region]"]');
|
||||
$this->assertTrue($this->assertSession()->optionExists('fields[field_test_text][region]', 'hidden')->isSelected());
|
||||
|
||||
$this->getSession()->getPage()->selectFieldOption('fields[field_test_text][region]', 'content');
|
||||
|
@ -92,12 +95,16 @@ class EntityDisplayTest extends JavascriptTestBase {
|
|||
public function testExtraFields() {
|
||||
entity_test_create_bundle('bundle_with_extra_fields');
|
||||
$this->drupalGet('entity_test/structure/bundle_with_extra_fields/display');
|
||||
$this->assertSession()->waitForElement('css', '.tabledrag-handle');
|
||||
$id = $this->getSession()->getPage()->find('css', '[name="form_build_id"]')->getValue();
|
||||
|
||||
$extra_field_row = $this->getSession()->getPage()->find('css', '#display-extra-field');
|
||||
$disabled_region_row = $this->getSession()->getPage()->find('css', '.region-hidden-title');
|
||||
|
||||
$extra_field_row->find('css', '.handle')->dragTo($disabled_region_row);
|
||||
$this->assertSession()->assertWaitOnAjaxRequest();
|
||||
$this->assertSession()
|
||||
->waitForElement('css', "[name='form_build_id']:not([value='$id'])");
|
||||
|
||||
$this->submitForm([], 'Save');
|
||||
$this->assertSession()->pageTextContains('Your settings have been saved.');
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace Drupal\Tests\field_ui\Kernel;
|
||||
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Entity\Display\EntityDisplayInterface;
|
||||
|
@ -87,7 +86,7 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
'link_to_entity' => FALSE,
|
||||
],
|
||||
'third_party_settings' => [],
|
||||
'region' => 'content'
|
||||
'region' => 'content',
|
||||
];
|
||||
$this->assertEqual($display->getComponents(), $expected);
|
||||
|
||||
|
@ -129,7 +128,7 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
$display->save();
|
||||
$components = array_keys($display->getComponents());
|
||||
// The name field is not configurable so will be added automatically.
|
||||
$expected = [ 0 => 'component_1', 1 => 'component_2', 2 => 'component_3', 'name'];
|
||||
$expected = [0 => 'component_1', 1 => 'component_2', 2 => 'component_3', 'name'];
|
||||
$this->assertIdentical($components, $expected);
|
||||
}
|
||||
|
||||
|
@ -150,7 +149,7 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
$display = entity_get_display('entity_test', 'entity_test', 'default');
|
||||
$this->assertFalse($display->isNew());
|
||||
$this->assertEqual($display->id(), 'entity_test.entity_test.default');
|
||||
$this->assertEqual($display->getComponent('component_1'), [ 'weight' => 10, 'settings' => [], 'third_party_settings' => [], 'region' => 'content']);
|
||||
$this->assertEqual($display->getComponent('component_1'), ['weight' => 10, 'settings' => [], 'third_party_settings' => [], 'region' => 'content']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,7 +165,15 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
|
||||
// Check that the default visibility taken into account for extra fields
|
||||
// unknown in the display.
|
||||
$this->assertEqual($display->getComponent('display_extra_field'), ['weight' => 5, 'region' => 'content']);
|
||||
$this->assertEqual(
|
||||
$display->getComponent('display_extra_field'),
|
||||
[
|
||||
'weight' => 5,
|
||||
'region' => 'content',
|
||||
'settings' => [],
|
||||
'third_party_settings' => [],
|
||||
]
|
||||
);
|
||||
$this->assertNull($display->getComponent('display_extra_field_hidden'));
|
||||
|
||||
// Check that setting explicit options overrides the defaults.
|
||||
|
@ -214,7 +221,7 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'test_field'
|
||||
'type' => 'test_field',
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
|
@ -360,7 +367,7 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'test_field'
|
||||
'type' => 'test_field',
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
|
@ -409,7 +416,7 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'text'
|
||||
'type' => 'text',
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
|
@ -515,14 +522,14 @@ class EntityDisplayTest extends KernelTestBase {
|
|||
// Create two arbitrary user roles.
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$roles[$i] = Role::create([
|
||||
'id' => Unicode::strtolower($this->randomMachineName()),
|
||||
'id' => mb_strtolower($this->randomMachineName()),
|
||||
'label' => $this->randomString(),
|
||||
]);
|
||||
$roles[$i]->save();
|
||||
}
|
||||
|
||||
// Create a field of type 'test_field' attached to 'entity_test'.
|
||||
$field_name = Unicode::strtolower($this->randomMachineName());
|
||||
$field_name = mb_strtolower($this->randomMachineName());
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
|
|
|
@ -55,7 +55,7 @@ class EntityFormDisplayTest extends KernelTestBase {
|
|||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'test_field'
|
||||
'type' => 'test_field',
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
|
@ -185,7 +185,7 @@ class EntityFormDisplayTest extends KernelTestBase {
|
|||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'test_field'
|
||||
'type' => 'test_field',
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
|
@ -234,7 +234,7 @@ class EntityFormDisplayTest extends KernelTestBase {
|
|||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'entity_test',
|
||||
'type' => 'text'
|
||||
'type' => 'text',
|
||||
]);
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
|
|
125
web/core/modules/field_ui/tests/src/Traits/FieldUiTestTrait.php
Normal file
125
web/core/modules/field_ui/tests/src/Traits/FieldUiTestTrait.php
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field_ui\Traits;
|
||||
|
||||
/**
|
||||
* Provides common functionality for the Field UI test classes.
|
||||
*/
|
||||
trait FieldUiTestTrait {
|
||||
|
||||
/**
|
||||
* Creates a new field through the Field UI.
|
||||
*
|
||||
* @param string $bundle_path
|
||||
* Admin path of the bundle that the new field is to be attached to.
|
||||
* @param string $field_name
|
||||
* The field name of the new field storage.
|
||||
* @param string $label
|
||||
* (optional) The label of the new field. Defaults to a random string.
|
||||
* @param string $field_type
|
||||
* (optional) The field type of the new field storage. Defaults to
|
||||
* 'test_field'.
|
||||
* @param array $storage_edit
|
||||
* (optional) $edit parameter for drupalPostForm() on the second step
|
||||
* ('Storage settings' form).
|
||||
* @param array $field_edit
|
||||
* (optional) $edit parameter for drupalPostForm() on the third step ('Field
|
||||
* settings' form).
|
||||
*/
|
||||
public function fieldUIAddNewField($bundle_path, $field_name, $label = NULL, $field_type = 'test_field', array $storage_edit = [], array $field_edit = []) {
|
||||
$label = $label ?: $this->randomString();
|
||||
$initial_edit = [
|
||||
'new_storage_type' => $field_type,
|
||||
'label' => $label,
|
||||
'field_name' => $field_name,
|
||||
];
|
||||
|
||||
// Allow the caller to set a NULL path in case they navigated to the right
|
||||
// page before calling this method.
|
||||
if ($bundle_path !== NULL) {
|
||||
$bundle_path = "$bundle_path/fields/add-field";
|
||||
}
|
||||
|
||||
// First step: 'Add field' page.
|
||||
$this->drupalPostForm($bundle_path, $initial_edit, t('Save and continue'));
|
||||
$this->assertRaw(t('These settings apply to the %label field everywhere it is used.', ['%label' => $label]), 'Storage settings page was displayed.');
|
||||
// Test Breadcrumbs.
|
||||
$this->assertLink($label, 0, 'Field label is correct in the breadcrumb of the storage settings page.');
|
||||
|
||||
// Second step: 'Storage settings' form.
|
||||
$this->drupalPostForm(NULL, $storage_edit, t('Save field settings'));
|
||||
$this->assertRaw(t('Updated field %label field settings.', ['%label' => $label]), 'Redirected to field settings page.');
|
||||
|
||||
// Third step: 'Field settings' form.
|
||||
$this->drupalPostForm(NULL, $field_edit, t('Save settings'));
|
||||
$this->assertRaw(t('Saved %label configuration.', ['%label' => $label]), 'Redirected to "Manage fields" page.');
|
||||
|
||||
// Check that the field appears in the overview form.
|
||||
$this->assertFieldByXPath('//table[@id="field-overview"]//tr/td[1]', $label, 'Field was created and appears in the overview page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an existing field through the Field UI.
|
||||
*
|
||||
* @param string $bundle_path
|
||||
* Admin path of the bundle that the field is to be attached to.
|
||||
* @param string $existing_storage_name
|
||||
* The name of the existing field storage for which we want to add a new
|
||||
* field.
|
||||
* @param string $label
|
||||
* (optional) The label of the new field. Defaults to a random string.
|
||||
* @param array $field_edit
|
||||
* (optional) $edit parameter for drupalPostForm() on the second step
|
||||
* ('Field settings' form).
|
||||
*/
|
||||
public function fieldUIAddExistingField($bundle_path, $existing_storage_name, $label = NULL, array $field_edit = []) {
|
||||
$label = $label ?: $this->randomString();
|
||||
$initial_edit = [
|
||||
'existing_storage_name' => $existing_storage_name,
|
||||
'existing_storage_label' => $label,
|
||||
];
|
||||
|
||||
// First step: 'Re-use existing field' on the 'Add field' page.
|
||||
$this->drupalPostForm("$bundle_path/fields/add-field", $initial_edit, t('Save and continue'));
|
||||
// Set the main content to only the content region because the label can
|
||||
// contain HTML which will be auto-escaped by Twig.
|
||||
$this->assertRaw('field-config-edit-form', 'The field config edit form is present.');
|
||||
$this->assertNoRaw('&lt;', 'The page does not have double escaped HTML tags.');
|
||||
|
||||
// Second step: 'Field settings' form.
|
||||
$this->drupalPostForm(NULL, $field_edit, t('Save settings'));
|
||||
$this->assertRaw(t('Saved %label configuration.', ['%label' => $label]), 'Redirected to "Manage fields" page.');
|
||||
|
||||
// Check that the field appears in the overview form.
|
||||
$this->assertFieldByXPath('//table[@id="field-overview"]//tr/td[1]', $label, 'Field was created and appears in the overview page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a field through the Field UI.
|
||||
*
|
||||
* @param string $bundle_path
|
||||
* Admin path of the bundle that the field is to be deleted from.
|
||||
* @param string $field_name
|
||||
* The name of the field.
|
||||
* @param string $label
|
||||
* The label of the field.
|
||||
* @param string $bundle_label
|
||||
* The label of the bundle.
|
||||
*/
|
||||
public function fieldUIDeleteField($bundle_path, $field_name, $label, $bundle_label) {
|
||||
// Display confirmation form.
|
||||
$this->drupalGet("$bundle_path/fields/$field_name/delete");
|
||||
$this->assertRaw(t('Are you sure you want to delete the field %label', ['%label' => $label]), 'Delete confirmation was found.');
|
||||
|
||||
// Test Breadcrumbs.
|
||||
$this->assertLink($label, 0, 'Field label is correct in the breadcrumb of the field delete page.');
|
||||
|
||||
// Submit confirmation form.
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertRaw(t('The field %label has been deleted from the %type content type.', ['%label' => $label, '%type' => $bundle_label]), 'Delete message was found.');
|
||||
|
||||
// Check that the field does not appear in the overview form.
|
||||
$this->assertNoFieldByXPath('//table[@id="field-overview"]//span[@class="label-field"]', $label, 'Field does not appear in the overview page.');
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue