Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -8,6 +8,8 @@ use Drupal\views\Views;
/**
* Form builder for the advanced admin settings page.
*
* @internal
*/
class AdvancedSettingsForm extends ConfigFormBase {
@ -76,7 +78,7 @@ class AdvancedSettingsForm extends ConfigFormBase {
'#default_value' => array_filter($config->get('display_extenders')),
'#options' => $options,
'#type' => 'checkboxes',
'#description' => $this->t('Select extensions of the views interface.')
'#description' => $this->t('Select extensions of the views interface.'),
];
}
@ -101,7 +103,7 @@ class AdvancedSettingsForm extends ConfigFormBase {
*/
public function cacheSubmit() {
views_invalidate_cache();
drupal_set_message($this->t('The cache has been cleared.'));
$this->messenger()->addStatus($this->t('The cache has been cleared.'));
}
}

View file

@ -9,6 +9,8 @@ use Drupal\views\Views;
/**
* Provides a form for adding an item in the Views UI.
*
* @internal
*/
class AddHandler extends ViewsFormBase {
@ -176,7 +178,7 @@ class AddHandler extends ViewsFormBase {
$view->getStandardButtons($form, $form_state, 'views_ui_add_handler_form', $this->t('Add and configure @types', ['@types' => $ltitle]));
// Remove the default submit function.
$form['actions']['submit']['#submit'] = array_filter($form['actions']['submit']['#submit'], function($var) {
$form['actions']['submit']['#submit'] = array_filter($form['actions']['submit']['#submit'], function ($var) {
return !(is_array($var) && isset($var[1]) && $var[1] == 'standardSubmit');
});
$form['actions']['submit']['#submit'][] = [$view, 'submitItemAdd'];

View file

@ -7,6 +7,8 @@ use Drupal\views\Views;
/**
* Displays analysis information for a view.
*
* @internal
*/
class Analyze extends ViewsFormBase {

View file

@ -10,6 +10,8 @@ use Symfony\Component\HttpFoundation\Request;
/**
* Provides a form for configuring an item in the Views UI.
*
* @internal
*/
class ConfigHandler extends ViewsFormBase {

View file

@ -8,6 +8,8 @@ use Drupal\views\ViewExecutable;
/**
* Provides a form for configuring extra information for a Views UI item.
*
* @internal
*/
class ConfigHandlerExtra extends ViewsFormBase {

View file

@ -9,6 +9,8 @@ use Drupal\views\ViewExecutable;
/**
* Provides a form for configuring grouping information for a Views UI handler.
*
* @internal
*/
class ConfigHandlerGroup extends ViewsFormBase {

View file

@ -7,6 +7,8 @@ use Drupal\views\ViewEntityInterface;
/**
* Provides a form for editing the Views display.
*
* @internal
*/
class Display extends ViewsFormBase {

View file

@ -7,6 +7,8 @@ use Drupal\views\Views;
/**
* Provides a form for editing the details of a View.
*
* @internal
*/
class EditDetails extends ViewsFormBase {

View file

@ -2,7 +2,7 @@
namespace Drupal\views_ui\Form\Ajax;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\views\ViewEntityInterface;
@ -10,6 +10,8 @@ use Drupal\views\ViewExecutable;
/**
* Provides a rearrange form for Views handlers.
*
* @internal
*/
class Rearrange extends ViewsFormBase {
@ -83,7 +85,7 @@ class Rearrange extends ViewsFormBase {
'action' => 'order',
'relationship' => 'sibling',
'group' => 'weight',
]
],
],
'#tree' => TRUE,
'#prefix' => '<div class="scroll" data-drupal-views-scroll>',
@ -124,12 +126,14 @@ class Rearrange extends ViewsFormBase {
'#id' => 'views-removed-' . $id,
'#attributes' => ['class' => ['views-remove-checkbox']],
'#default_value' => 0,
'#suffix' => \Drupal::l(SafeMarkup::format('<span>@text</span>', ['@text' => $this->t('Remove')]),
Url::fromRoute('<none>', [], ['attributes' => [
'id' => 'views-remove-link-' . $id,
'class' => ['views-hidden', 'views-button-remove', 'views-remove-link'],
'alt' => $this->t('Remove this item'),
'title' => $this->t('Remove this item')],
'#suffix' => \Drupal::l(new FormattableMarkup('<span>@text</span>', ['@text' => $this->t('Remove')]),
Url::fromRoute('<none>', [], [
'attributes' => [
'id' => 'views-remove-link-' . $id,
'class' => ['views-hidden', 'views-button-remove', 'views-remove-link'],
'alt' => $this->t('Remove this item'),
'title' => $this->t('Remove this item'),
],
])
),
];

View file

@ -8,6 +8,8 @@ use Drupal\views\ViewExecutable;
/**
* Provides a rearrange form for Views filters.
*
* @internal
*/
class RearrangeFilter extends ViewsFormBase {
@ -119,7 +121,8 @@ class RearrangeFilter extends ViewsFormBase {
],
];
$form['remove_groups'][$id] = []; // to prevent a notice
// To prevent a notice.
$form['remove_groups'][$id] = [];
if ($id != 1) {
$form['remove_groups'][$id] = [
'#type' => 'submit',

View file

@ -2,12 +2,14 @@
namespace Drupal\views_ui\Form\Ajax;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
/**
* Displays the display reorder form.
*
* @internal
*/
class ReorderDisplays extends ViewsFormBase {
@ -42,7 +44,7 @@ class ReorderDisplays extends ViewsFormBase {
]);
$form['view'] = [
'#type' => 'value',
'#value' => $view
'#value' => $view,
];
$displays = $view->get('display');
@ -66,7 +68,7 @@ class ReorderDisplays extends ViewsFormBase {
'action' => 'order',
'relationship' => 'sibling',
'group' => 'weight',
]
],
],
'#tree' => TRUE,
'#prefix' => '<div class="scroll" data-drupal-views-scroll>',
@ -115,7 +117,7 @@ class ReorderDisplays extends ViewsFormBase {
],
'link' => [
'#type' => 'link',
'#title' => SafeMarkup::format('<span>@text</span>', ['@text' => $this->t('Remove')]),
'#title' => new FormattableMarkup('<span>@text</span>', ['@text' => $this->t('Remove')]),
'#url' => Url::fromRoute('<none>'),
'#attributes' => [
'id' => 'display-remove-link-' . $id,

View file

@ -104,7 +104,9 @@ abstract class ViewsFormBase extends FormBase implements ViewsFormInterface {
// Retrieve the first form from the stack without changing the integer keys,
// as they're being used for the "2 of 3" progress indicator.
reset($view->stack);
list($key, $top) = each($view->stack);
$key = key($view->stack);
$top = current($view->stack);
next($view->stack);
unset($view->stack[$key]);
if (array_shift($top) != $identifier) {

View file

@ -10,6 +10,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Form builder for the admin display defaults page.
*
* @internal
*/
class BasicSettingsForm extends ConfigFormBase {

View file

@ -5,11 +5,13 @@ namespace Drupal\views_ui\Form;
use Drupal\Core\Entity\EntityConfirmFormBase;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Builds the form to break the lock of an edited view.
*
* @internal
*/
class BreakLockForm extends EntityConfirmFormBase {
@ -21,9 +23,9 @@ class BreakLockForm extends EntityConfirmFormBase {
protected $entityManager;
/**
* Stores the user tempstore.
* Stores the shared tempstore.
*
* @var \Drupal\user\SharedTempStore
* @var \Drupal\Core\TempStore\SharedTempStore
*/
protected $tempStore;
@ -32,7 +34,7 @@ class BreakLockForm extends EntityConfirmFormBase {
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The Entity manager.
* @param \Drupal\user\SharedTempStoreFactory $temp_store_factory
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $temp_store_factory
* The factory for the temp store object.
*/
public function __construct(EntityManagerInterface $entity_manager, SharedTempStoreFactory $temp_store_factory) {
@ -46,7 +48,7 @@ class BreakLockForm extends EntityConfirmFormBase {
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager'),
$container->get('user.shared_tempstore')
$container->get('tempstore.shared')
);
}
@ -74,7 +76,7 @@ class BreakLockForm extends EntityConfirmFormBase {
'#theme' => 'username',
'#account' => $account,
];
return $this->t('By breaking this lock, any unsaved changes made by @user will be lost.', ['@user' => drupal_render($username)]);
return $this->t('By breaking this lock, any unsaved changes made by @user will be lost.', ['@user' => \Drupal::service('renderer')->render($username)]);
}
/**
@ -108,7 +110,7 @@ class BreakLockForm extends EntityConfirmFormBase {
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->tempStore->delete($this->entity->id());
$form_state->setRedirectUrl($this->entity->urlInfo('edit-form'));
drupal_set_message($this->t('The lock has been broken and you may now edit this view.'));
$this->messenger()->addStatus($this->t('The lock has been broken and you may now edit this view.'));
}
}

View file

@ -8,7 +8,7 @@ use Drupal\Core\ParamConverter\AdminPathConfigEntityConverter;
use Drupal\Core\Routing\AdminContext;
use Symfony\Component\Routing\Route;
use Drupal\Core\ParamConverter\ParamConverterInterface;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\views_ui\ViewUI;
/**
@ -32,7 +32,7 @@ class ViewUIConverter extends AdminPathConfigEntityConverter implements ParamCon
/**
* Stores the tempstore factory.
*
* @var \Drupal\user\SharedTempStoreFactory
* @var \Drupal\Core\TempStore\SharedTempStoreFactory
*/
protected $tempStoreFactory;
@ -41,7 +41,7 @@ class ViewUIConverter extends AdminPathConfigEntityConverter implements ParamCon
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\user\SharedTempStoreFactory $temp_store_factory
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $temp_store_factory
* The factory for the temp store object.
*/
public function __construct(EntityManagerInterface $entity_manager, SharedTempStoreFactory $temp_store_factory, ConfigFactoryInterface $config_factory = NULL, AdminContext $admin_context = NULL) {

View file

@ -1,59 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Tests\ViewTestBase;
/**
* Tests the views analyze system.
*
* @group views_ui
*/
class AnalyzeTest extends ViewTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['views_ui'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
protected function setUp() {
parent::setUp();
$this->enableViewsTestModule();
// Add an admin user will full rights;
$this->admin = $this->drupalCreateUser(['administer views']);
}
/**
* Tests that analyze works in general.
*/
public function testAnalyzeBasic() {
$this->drupalLogin($this->admin);
$this->drupalGet('admin/structure/views/view/test_view/edit');
$this->assertLink(t('Analyze view'));
// This redirects the user to the analyze form.
$this->clickLink(t('Analyze view'));
$this->assertText(t('View analysis'));
foreach (['ok', 'warning', 'error'] as $type) {
$xpath = $this->xpath('//div[contains(@class, :class)]', [':class' => $type]);
$this->assertTrue(count($xpath), format_string('Analyse messages with @type found', ['@type' => $type]));
}
// This redirects the user back to the main views edit page.
$this->drupalPostForm(NULL, [], t('Ok'));
}
}

View file

@ -1,101 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\block\Entity\Block;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\views\Entity\View;
/**
* Tests the entity area UI test.
*
* @see \Drupal\views\Plugin\views\area\Entity
* @group views_ui
*/
class AreaEntityUITest extends UITestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['entity_test'];
public function testUI() {
// Set up a block and a entity_test entity.
$block = Block::create(['id' => 'test_id', 'plugin' => 'system_main_block']);
$block->save();
$entity_test = EntityTest::create(['bundle' => 'entity_test']);
$entity_test->save();
$default = $this->randomView([]);
$id = $default['id'];
$view = View::load($id);
$this->drupalGet($view->urlInfo('edit-form'));
// Add a global NULL argument to the view for testing argument placeholders.
$this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/argument", ['name[views.null]' => 1], 'Add and configure contextual filters');
$this->drupalPostForm(NULL, [], 'Apply');
// Configure both the entity_test area header and the block header to
// reference the given entities.
$this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/header", ['name[views.entity_block]' => 1], 'Add and configure header');
$this->drupalPostForm(NULL, ['options[target]' => $block->id()], 'Apply');
$this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/header", ['name[views.entity_entity_test]' => 1], 'Add and configure header');
$this->drupalPostForm(NULL, ['options[target]' => $entity_test->id()], 'Apply');
$this->drupalPostForm(NULL, [], 'Save');
// Confirm the correct target identifiers were saved for both entities.
$view = View::load($id);
$header = $view->getDisplay('default')['display_options']['header'];
$this->assertEqual(['entity_block', 'entity_entity_test'], array_keys($header));
$this->assertEqual($block->id(), $header['entity_block']['target']);
$this->assertEqual($entity_test->uuid(), $header['entity_entity_test']['target']);
// Confirm that the correct serial ID (for the entity_test) and config ID
// (for the block) are displayed in the form.
$this->drupalGet("admin/structure/views/nojs/handler/$id/page_1/header/entity_block");
$this->assertFieldByName('options[target]', $block->id());
$this->drupalGet("admin/structure/views/nojs/handler/$id/page_1/header/entity_entity_test");
$this->assertFieldByName('options[target]', $entity_test->id());
// Replace the header target entities with argument placeholders.
$this->drupalPostForm("admin/structure/views/nojs/handler/$id/page_1/header/entity_block", ['options[target]' => '{{ raw_arguments.null }}'], 'Apply');
$this->drupalPostForm("admin/structure/views/nojs/handler/$id/page_1/header/entity_entity_test", ['options[target]' => '{{ raw_arguments.null }}'], 'Apply');
$this->drupalPostForm(NULL, [], 'Save');
// Confirm that the argument placeholders are saved.
$view = View::load($id);
$header = $view->getDisplay('default')['display_options']['header'];
$this->assertEqual(['entity_block', 'entity_entity_test'], array_keys($header));
$this->assertEqual('{{ raw_arguments.null }}', $header['entity_block']['target']);
$this->assertEqual('{{ raw_arguments.null }}', $header['entity_entity_test']['target']);
// Confirm that the argument placeholders are still displayed in the form.
$this->drupalGet("admin/structure/views/nojs/handler/$id/page_1/header/entity_block");
$this->assertFieldByName('options[target]', '{{ raw_arguments.null }}');
$this->drupalGet("admin/structure/views/nojs/handler/$id/page_1/header/entity_entity_test");
$this->assertFieldByName('options[target]', '{{ raw_arguments.null }}');
// Change the targets for both headers back to the entities.
$this->drupalPostForm("admin/structure/views/nojs/handler/$id/page_1/header/entity_block", ['options[target]' => $block->id()], 'Apply');
$this->drupalPostForm("admin/structure/views/nojs/handler/$id/page_1/header/entity_entity_test", ['options[target]' => $entity_test->id()], 'Apply');
$this->drupalPostForm(NULL, [], 'Save');
// Confirm the targets were again saved correctly and not skipped based on
// the previous form value.
$view = View::load($id);
$header = $view->getDisplay('default')['display_options']['header'];
$this->assertEqual(['entity_block', 'entity_entity_test'], array_keys($header));
$this->assertEqual($block->id(), $header['entity_block']['target']);
$this->assertEqual($entity_test->uuid(), $header['entity_entity_test']['target']);
}
}

View file

@ -1,57 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Views;
/**
* Tests the Argument validator through the UI.
*
* @group views_ui
*/
class ArgumentValidatorTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_argument'];
/**
* Tests the 'Specify validation criteria' checkbox functionality.
*/
public function testSpecifyValidation() {
// Specify a validation based on Node for the 'id' argument on the default
// display and assert that this works.
$this->saveArgumentHandlerWithValidationOptions(TRUE);
$view = Views::getView('test_argument');
$handler = $view->getHandler('default', 'argument', 'id');
$this->assertTrue($handler['specify_validation'], 'Validation for this argument has been turned on.');
$this->assertEqual('entity:node', $handler['validate']['type'], 'Validation for the argument is based on the node.');
// Uncheck the 'Specify validation criteria' checkbox and expect the
// validation type to be reset back to 'none'.
$this->saveArgumentHandlerWithValidationOptions(FALSE);
$view = Views::getView('test_argument');
$handler = $view->getHandler('default', 'argument', 'id');
$this->assertFalse($handler['specify_validation'], 'Validation for this argument has been turned off.');
$this->assertEqual('none', $handler['validate']['type'], 'Validation for the argument has been reverted to Basic Validation.');
}
/**
* Saves the test_argument view with changes made to the argument handler
* both with and without specify_validation turned on.
*
* @param bool $specify_validation
*/
protected function saveArgumentHandlerWithValidationOptions($specify_validation) {
$options = [
'options[validate][type]' => 'entity---node',
'options[specify_validation]' => $specify_validation,
];
$this->drupalPostForm('admin/structure/views/nojs/handler/test_argument/default/argument/id', $options, t('Apply'));
$this->drupalPostForm('admin/structure/views/view/test_argument', [], t('Save'));
}
}

View file

@ -1,74 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests the user tempstore cache in the UI.
*
* @group views_ui
*/
class CachedDataUITest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Tests the user tempstore views data in the UI.
*/
public function testCacheData() {
$views_admin_user_uid = $this->fullAdminUser->id();
$temp_store = $this->container->get('user.shared_tempstore')->get('views');
// The view should not be locked.
$this->assertEqual($temp_store->getMetadata('test_view'), NULL, 'The view is not locked.');
$this->drupalGet('admin/structure/views/view/test_view/edit');
// Make sure we have 'changes' to the view.
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/default/title', [], t('Apply'));
$this->assertText('You have unsaved changes.');
$this->assertEqual($temp_store->getMetadata('test_view')->owner, $views_admin_user_uid, 'View cache has been saved.');
$view_cache = $temp_store->get('test_view');
// The view should be enabled.
$this->assertTrue($view_cache->status(), 'The view is enabled.');
// The view should now be locked.
$this->assertEqual($temp_store->getMetadata('test_view')->owner, $views_admin_user_uid, 'The view is locked.');
// Cancel the view edit and make sure the cache is deleted.
$this->drupalPostForm(NULL, [], t('Cancel'));
$this->assertEqual($temp_store->getMetadata('test_view'), NULL, 'User tempstore data has been removed.');
// Test we are redirected to the view listing page.
$this->assertUrl('admin/structure/views', [], 'Redirected back to the view listing page.');
// Log in with another user and make sure the view is locked and break.
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/default/title', [], t('Apply'));
$this->drupalLogin($this->adminUser);
$this->drupalGet('admin/structure/views/view/test_view/edit');
// Test that save and cancel buttons are not shown.
$this->assertNoFieldById('edit-actions-submit', t('Save'));
$this->assertNoFieldById('edit-actions-cancel', t('Cancel'));
// Test we have the break lock link.
$this->assertLinkByHref('admin/structure/views/view/test_view/break-lock');
// Break the lock.
$this->clickLink(t('break this lock'));
$this->drupalPostForm(NULL, [], t('Break lock'));
// Test that save and cancel buttons are shown.
$this->assertFieldById('edit-actions-submit', t('Save'));
$this->assertFieldById('edit-actions-cancel', t('Cancel'));
// Test we can save the view.
$this->drupalPostForm('admin/structure/views/view/test_view/edit', [], t('Save'));
$this->assertRaw(t('The view %view has been saved.', ['%view' => 'Test view']));
// Test that a deleted view has no tempstore data.
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/default/title', [], t('Apply'));
$this->drupalPostForm('admin/structure/views/view/test_view/delete', [], t('Delete'));
// No view tempstore data should be returned for this view after deletion.
$this->assertEqual($temp_store->getMetadata('test_view'), NULL, 'View tempstore data has been removed after deletion.');
}
}

View file

@ -1,181 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\views\Views;
/**
* Tests the UI and functionality for the Custom boolean field handler options.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\field\Boolean
*/
class CustomBooleanTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* \Drupal\views\Tests\ViewTestBase::viewsData().
*/
public function viewsData() {
$data = parent::viewsData();
$data['views_test_data']['age']['field']['id'] = 'boolean';
return $data;
}
/**
* {@inheritdoc}
*/
public function dataSet() {
$data = parent::dataSet();
$data[0]['age'] = 0;
$data[3]['age'] = 0;
return $data;
}
/**
* Tests the setting and output of custom labels for boolean values.
*/
public function testCustomOption() {
// Add the boolean field handler to the test view.
$view = Views::getView('test_view');
$view->setDisplay();
$view->displayHandlers->get('default')->overrideOption('fields', [
'age' => [
'id' => 'age',
'table' => 'views_test_data',
'field' => 'age',
'relationship' => 'none',
'plugin_id' => 'boolean',
],
]);
$view->save();
$this->executeView($view);
$custom_true = 'Yay';
$custom_false = 'Nay';
// Set up some custom value mappings for different types.
$custom_values = [
'plain' => [
'true' => $custom_true,
'false' => $custom_false,
'test' => 'assertTrue',
],
'allowed tag' => [
'true' => '<p>' . $custom_true . '</p>',
'false' => '<p>' . $custom_false . '</p>',
'test' => 'assertTrue',
],
'disallowed tag' => [
'true' => '<script>' . $custom_true . '</script>',
'false' => '<script>' . $custom_false . '</script>',
'test' => 'assertFalse',
],
];
// Run the same tests on each type.
foreach ($custom_values as $type => $values) {
$options = [
'options[type]' => 'custom',
'options[type_custom_true]' => $values['true'],
'options[type_custom_false]' => $values['false'],
];
$this->drupalPostForm('admin/structure/views/nojs/handler/test_view/default/field/age', $options, 'Apply');
// Save the view.
$this->drupalPostForm('admin/structure/views/view/test_view', [], 'Save');
$view = Views::getView('test_view');
$output = $view->preview();
$output = \Drupal::service('renderer')->renderRoot($output);
$this->{$values['test']}(strpos($output, $values['true']), SafeMarkup::format('Expected custom boolean TRUE value %value in output for %type', ['%value' => $values['true'], '%type' => $type]));
$this->{$values['test']}(strpos($output, $values['false']), SafeMarkup::format('Expected custom boolean FALSE value %value in output for %type', ['%value' => $values['false'], '%type' => $type]));
}
}
/**
* Tests the setting and output of custom labels for boolean values.
*/
public function testCustomOptionTemplate() {
// Install theme to test with template system.
\Drupal::service('theme_handler')->install(['views_test_theme']);
// Set the default theme for Views preview.
$this->config('system.theme')
->set('default', 'views_test_theme')
->save();
$this->assertEqual($this->config('system.theme')->get('default'), 'views_test_theme');
// Add the boolean field handler to the test view.
$view = Views::getView('test_view');
$view->setDisplay();
$view->displayHandlers->get('default')->overrideOption('fields', [
'age' => [
'id' => 'age',
'table' => 'views_test_data',
'field' => 'age',
'relationship' => 'none',
'plugin_id' => 'boolean',
],
]);
$view->save();
$this->executeView($view);
$custom_true = 'Yay';
$custom_false = 'Nay';
// Set up some custom value mappings for different types.
$custom_values = [
'plain' => [
'true' => $custom_true,
'false' => $custom_false,
'test' => 'assertTrue',
],
'allowed tag' => [
'true' => '<p>' . $custom_true . '</p>',
'false' => '<p>' . $custom_false . '</p>',
'test' => 'assertTrue',
],
'disallowed tag' => [
'true' => '<script>' . $custom_true . '</script>',
'false' => '<script>' . $custom_false . '</script>',
'test' => 'assertFalse',
],
];
// Run the same tests on each type.
foreach ($custom_values as $type => $values) {
$options = [
'options[type]' => 'custom',
'options[type_custom_true]' => $values['true'],
'options[type_custom_false]' => $values['false'],
];
$this->drupalPostForm('admin/structure/views/nojs/handler/test_view/default/field/age', $options, 'Apply');
// Save the view.
$this->drupalPostForm('admin/structure/views/view/test_view', [], 'Save');
$view = Views::getView('test_view');
$output = $view->preview();
$output = \Drupal::service('renderer')->renderRoot($output);
$this->{$values['test']}(strpos($output, $values['true']), SafeMarkup::format('Expected custom boolean TRUE value %value in output for %type', ['%value' => $values['true'], '%type' => $type]));
$this->{$values['test']}(strpos($output, $values['false']), SafeMarkup::format('Expected custom boolean FALSE value %value in output for %type', ['%value' => $values['false'], '%type' => $type]));
// Assert that we are using the correct template.
$this->setRawContent($output);
$this->assertText('llama', 'Loaded the correct views-view-field.html.twig template');
}
}
}

View file

@ -1,248 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\Core\Url;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
/**
* Tests enabling, disabling, and reverting default views via the listing page.
*
* @group views_ui
*/
class DefaultViewsTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view_status', 'test_page_display_menu', 'test_page_display_arguments'];
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('page_title_block');
}
/**
* Tests default views.
*/
public function testDefaultViews() {
// Make sure the view starts off as disabled (does not appear on the listing
// page).
$edit_href = 'admin/structure/views/view/glossary';
$this->drupalGet('admin/structure/views');
// @todo Disabled default views do now appear on the front page. Test this
// behavior with templates instead.
// $this->assertNoLinkByHref($edit_href);
// Enable the view, and make sure it is now visible on the main listing
// page.
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Enable'), '/glossary/');
$this->assertUrl('admin/structure/views');
$this->assertLinkByHref($edit_href);
// It should not be possible to revert the view yet.
// @todo Figure out how to handle this with the new configuration system.
// $this->assertNoLink(t('Revert'));
// $revert_href = 'admin/structure/views/view/glossary/revert';
// $this->assertNoLinkByHref($revert_href);
// Edit the view and change the title. Make sure that the new title is
// displayed.
$new_title = $this->randomMachineName(16);
$edit = ['title' => $new_title];
$this->drupalPostForm('admin/structure/views/nojs/display/glossary/page_1/title', $edit, t('Apply'));
$this->drupalPostForm('admin/structure/views/view/glossary/edit/page_1', [], t('Save'));
$this->drupalGet('glossary');
$this->assertResponse(200);
$this->assertText($new_title);
// Save another view in the UI.
$this->drupalPostForm('admin/structure/views/nojs/display/archive/page_1/title', [], t('Apply'));
$this->drupalPostForm('admin/structure/views/view/archive/edit/page_1', [], t('Save'));
// Check there is an enable link. i.e. The view has not been enabled after
// editing.
$this->drupalGet('admin/structure/views');
$this->assertLinkByHref('admin/structure/views/view/archive/enable');
// Enable it again so it can be tested for access permissions.
$this->clickViewsOperationLink(t('Enable'), '/archive/');
// It should now be possible to revert the view. Do that, and make sure the
// view title we added above no longer is displayed.
// $this->drupalGet('admin/structure/views');
// $this->assertLink(t('Revert'));
// $this->assertLinkByHref($revert_href);
// $this->drupalPostForm($revert_href, array(), t('Revert'));
// $this->drupalGet('glossary');
// $this->assertNoText($new_title);
// Duplicate the view and check that the normal schema of duplicated views is used.
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Duplicate'), '/glossary');
$edit = [
'id' => 'duplicate_of_glossary',
];
$this->assertTitle(t('Duplicate of @label | @site-name', ['@label' => 'Glossary', '@site-name' => $this->config('system.site')->get('name')]));
$this->drupalPostForm(NULL, $edit, t('Duplicate'));
$this->assertUrl('admin/structure/views/view/duplicate_of_glossary', [], 'The normal duplicating name schema is applied.');
// Duplicate a view and set a custom name.
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Duplicate'), '/glossary');
$random_name = strtolower($this->randomMachineName());
$this->drupalPostForm(NULL, ['id' => $random_name], t('Duplicate'));
$this->assertUrl("admin/structure/views/view/$random_name", [], 'The custom view name got saved.');
// Now disable the view, and make sure it stops appearing on the main view
// listing page but instead goes back to displaying on the disabled views
// listing page.
// @todo Test this behavior with templates instead.
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Disable'), '/glossary/');
// $this->assertUrl('admin/structure/views');
// $this->assertNoLinkByHref($edit_href);
// The easiest way to verify it appears on the disabled views listing page
// is to try to click the "enable" link from there again.
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Enable'), '/glossary/');
$this->assertUrl('admin/structure/views');
$this->assertLinkByHref($edit_href);
// Clear permissions for anonymous users to check access for default views.
Role::load(RoleInterface::ANONYMOUS_ID)->revokePermission('access content')->save();
// Test the default views disclose no data by default.
$this->drupalLogout();
$this->drupalGet('glossary');
$this->assertResponse(403);
$this->drupalGet('archive');
$this->assertResponse(403);
// Test deleting a view.
$this->drupalLogin($this->fullAdminUser);
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Delete'), '/glossary/');
// Submit the confirmation form.
$this->drupalPostForm(NULL, [], t('Delete'));
// Ensure the view is no longer listed.
$this->assertUrl('admin/structure/views');
$this->assertNoLinkByHref($edit_href);
// Ensure the view is no longer available.
$this->drupalGet($edit_href);
$this->assertResponse(404);
$this->assertText('Page not found');
// Delete all duplicated Glossary views.
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Delete'), 'duplicate_of_glossary');
// Submit the confirmation form.
$this->drupalPostForm(NULL, [], t('Delete'));
$this->drupalGet('glossary');
$this->assertResponse(200);
$this->drupalGet('admin/structure/views');
$this->clickViewsOperationLink(t('Delete'), $random_name);
// Submit the confirmation form.
$this->drupalPostForm(NULL, [], t('Delete'));
$this->drupalGet('glossary');
$this->assertResponse(404);
$this->assertText('Page not found');
}
/**
* Tests that enabling views moves them to the correct table.
*/
public function testSplitListing() {
// Build a re-usable xpath query.
$xpath = '//div[@id="views-entity-list"]/div[@class = :status]/table//td/text()[contains(., :title)]';
$arguments = [
':status' => 'views-list-section enabled',
':title' => 'test_view_status',
];
$this->drupalGet('admin/structure/views');
$elements = $this->xpath($xpath, $arguments);
$this->assertIdentical(count($elements), 0, 'A disabled view is not found in the enabled views table.');
$arguments[':status'] = 'views-list-section disabled';
$elements = $this->xpath($xpath, $arguments);
$this->assertIdentical(count($elements), 1, 'A disabled view is found in the disabled views table.');
// Enable the view.
$this->clickViewsOperationLink(t('Enable'), '/test_view_status/');
$elements = $this->xpath($xpath, $arguments);
$this->assertIdentical(count($elements), 0, 'After enabling a view, it is not found in the disabled views table.');
$arguments[':status'] = 'views-list-section enabled';
$elements = $this->xpath($xpath, $arguments);
$this->assertIdentical(count($elements), 1, 'After enabling a view, it is found in the enabled views table.');
// Attempt to disable the view by path directly, with no token.
$this->drupalGet('admin/structure/views/view/test_view_status/disable');
$this->assertResponse(403);
}
/**
* Tests that page displays show the correct path.
*/
public function testPathDestination() {
$this->drupalGet('admin/structure/views');
// Check that links to views on default tabs are rendered correctly.
$this->assertLinkByHref('test_page_display_menu');
$this->assertNoLinkByHref('test_page_display_menu/default');
$this->assertLinkByHref('test_page_display_menu/local');
// Check that a dynamic path is shown as text.
$this->assertRaw('test_route_with_suffix/%/suffix');
$this->assertNoLinkByHref(Url::fromUri('base:test_route_with_suffix/%/suffix')->toString());
}
/**
* Click a link to perform an operation on a view.
*
* In general, we expect lots of links titled "enable" or "disable" on the
* various views listing pages, and they might have tokens in them. So we
* need special code to find the correct one to click.
*
* @param $label
* Text between the anchor tags of the desired link.
* @param $unique_href_part
* A unique string that is expected to occur within the href of the desired
* link. For example, if the link URL is expected to look like
* "admin/structure/views/view/glossary/*", then "/glossary/" could be
* passed as the expected unique string.
*
* @return
* The page content that results from clicking on the link, or FALSE on
* failure. Failure also results in a failed assertion.
*/
public function clickViewsOperationLink($label, $unique_href_part) {
$links = $this->xpath('//a[normalize-space(text())=:label]', [':label' => $label]);
foreach ($links as $link_index => $link) {
$position = strpos($link['href'], $unique_href_part);
if ($position !== FALSE) {
$index = $link_index;
break;
}
}
$this->assertTrue(isset($index), format_string('Link to "@label" containing @part found.', ['@label' => $label, '@part' => $unique_href_part]));
if (isset($index)) {
return $this->clickLink($label, $index);
}
else {
return FALSE;
}
}
}

View file

@ -1,96 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Views;
/**
* Tests the UI for the attachment display plugin.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\display\Attachment
*/
class DisplayAttachmentTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_attachment_ui'];
/**
* Tests the attachment UI.
*/
public function testAttachmentUI() {
$this->drupalGet('admin/structure/views/view/test_attachment_ui/edit/attachment_1');
$this->assertText(t('Not defined'), 'The right text appears if there is no attachment selection yet.');
$attachment_display_url = 'admin/structure/views/nojs/display/test_attachment_ui/attachment_1/displays';
$this->drupalGet($attachment_display_url);
// Display labels should be escaped.
$this->assertEscaped('<em>Page</em>');
foreach (['default', 'page-1'] as $display_id) {
$this->assertNoFieldChecked("edit-displays-$display_id", format_string('Make sure the @display_id can be marked as attached', ['@display_id' => $display_id]));
}
// Save the attachments and test the value on the view.
$this->drupalPostForm($attachment_display_url, ['displays[page_1]' => 1], t('Apply'));
// Options summary should be escaped.
$this->assertEscaped('<em>Page</em>');
$this->assertNoRaw('<em>Page</em>');
$result = $this->xpath('//a[@id = :id]', [':id' => 'views-attachment-1-displays']);
$this->assertEqual($result[0]->attributes()->title, t('Page'));
$this->drupalPostForm(NULL, [], t('Save'));
$view = Views::getView('test_attachment_ui');
$view->initDisplay();
$this->assertEqual(array_keys(array_filter($view->displayHandlers->get('attachment_1')->getOption('displays'))), ['page_1'], 'The attached displays got saved as expected');
$this->drupalPostForm($attachment_display_url, ['displays[default]' => 1, 'displays[page_1]' => 1], t('Apply'));
$result = $this->xpath('//a[@id = :id]', [':id' => 'views-attachment-1-displays']);
$this->assertEqual($result[0]->attributes()->title, t('Multiple displays'));
$this->drupalPostForm(NULL, [], t('Save'));
$view = Views::getView('test_attachment_ui');
$view->initDisplay();
$this->assertEqual(array_keys($view->displayHandlers->get('attachment_1')->getOption('displays')), ['default', 'page_1'], 'The attached displays got saved as expected');
}
/**
* Tests the attachment working after the attached page was deleted.
*/
public function testRemoveAttachedDisplay() {
// Create a view.
$view = $this->randomView();
$path_prefix = 'admin/structure/views/view/' . $view['id'] . '/edit';
$attachment_display_url = 'admin/structure/views/nojs/display/' . $view['id'] . '/attachment_1/displays';
// Open the Page display and create the attachment display.
$this->drupalGet($path_prefix . '/page_1');
$this->drupalPostForm(NULL, [], 'Add Attachment');
$this->assertText(t('Not defined'), 'The right text appears if there is no attachment selection yet.');
// Attach the Attachment to the Page display.
$this->drupalPostForm($attachment_display_url, ['displays[page_1]' => 1], t('Apply'));
$this->drupalPostForm(NULL, [], t('Save'));
// Open the Page display and mark it as deleted.
$this->drupalGet($path_prefix . '/page_1');
$this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-delete', 'Delete Page', 'Make sure there is a delete button on the page display.');
$this->drupalPostForm($path_prefix . '/page_1', [], 'Delete Page');
// Open the attachment display and save it.
$this->drupalGet($path_prefix . '/attachment_1');
$this->drupalPostForm(NULL, [], t('Save'));
// Check that there is no warning for the removed page display.
$this->assertNoText("Plugin ID &#039;page_1&#039; was not found.");
// Check that the attachment is no longer linked to the removed display.
$this->assertText(t('Not defined'), 'The right text appears if there is no attachment selection yet.');
}
}

View file

@ -1,148 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Views;
/**
* Tests creation, retrieval, updating, and deletion of displays in the Web UI.
*
* @group views_ui
*/
class DisplayCRUDTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_display'];
/**
* Modules to enable
*
* @var array
*/
public static $modules = ['contextual'];
/**
* Tests adding a display.
*/
public function testAddDisplay() {
// Show the master display.
$this->config('views.settings')->set('ui.show.master_display', TRUE)->save();
$settings['page[create]'] = FALSE;
$view = $this->randomView($settings);
$path_prefix = 'admin/structure/views/view/' . $view['id'] . '/edit';
$this->drupalGet($path_prefix);
// Add a new display.
$this->drupalPostForm(NULL, [], 'Add Page');
$this->assertLinkByHref($path_prefix . '/page_1', 0, 'Make sure after adding a display the new display appears in the UI');
$this->assertNoLink('Master*', 'Make sure the master display is not marked as changed.');
$this->assertLink('Page*', 0, 'Make sure the added display is marked as changed.');
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/page_1/path", ['path' => 'test/path'], t('Apply'));
$this->drupalPostForm(NULL, [], t('Save'));
}
/**
* Tests removing a display.
*/
public function testRemoveDisplay() {
$view = $this->randomView();
$path_prefix = 'admin/structure/views/view/' . $view['id'] . '/edit';
$this->drupalGet($path_prefix . '/default');
$this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-delete', 'Delete Page', 'Make sure there is no delete button on the default display.');
$this->drupalGet($path_prefix . '/page_1');
$this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-delete', 'Delete Page', 'Make sure there is a delete button on the page display.');
// Delete the page, so we can test the undo process.
$this->drupalPostForm($path_prefix . '/page_1', [], 'Delete Page');
$this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-undo-delete', 'Undo delete of Page', 'Make sure there a undo button on the page display after deleting.');
$element = $this->xpath('//a[contains(@href, :href) and contains(@class, :class)]', [':href' => $path_prefix . '/page_1', ':class' => 'views-display-deleted-link']);
$this->assertTrue(!empty($element), 'Make sure the display link is marked as to be deleted.');
$element = $this->xpath('//a[contains(@href, :href) and contains(@class, :class)]', [':href' => $path_prefix . '/page_1', ':class' => 'views-display-deleted-link']);
$this->assertTrue(!empty($element), 'Make sure the display link is marked as to be deleted.');
// Undo the deleting of the display.
$this->drupalPostForm($path_prefix . '/page_1', [], 'Undo delete of Page');
$this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-undo-delete', 'Undo delete of Page', 'Make sure there is no undo button on the page display after reverting.');
$this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-delete', 'Delete Page', 'Make sure there is a delete button on the page display after the reverting.');
// Now delete again and save the view.
$this->drupalPostForm($path_prefix . '/page_1', [], 'Delete Page');
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertNoLinkByHref($path_prefix . '/page_1', 'Make sure there is no display tab for the deleted display.');
// Test deleting a display that has a modified machine name.
$view = $this->randomView();
$machine_name = 'new_machine_name';
$path_prefix = 'admin/structure/views/view/' . $view['id'] . '/edit';
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/page_1/display_id", ['display_id' => $machine_name], 'Apply');
$this->drupalPostForm(NULL, [], 'Delete Page');
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertResponse(200);
$this->assertNoLinkByHref($path_prefix . '/new_machine_name', 'Make sure there is no display tab for the deleted display.');
}
/**
* Tests that the correct display is loaded by default.
*/
public function testDefaultDisplay() {
$this->drupalGet('admin/structure/views/view/test_display');
$elements = $this->xpath('//*[@id="views-page-1-display-title"]');
$this->assertEqual(count($elements), 1, 'The page display is loaded as the default display.');
}
/**
* Tests the duplicating of a display.
*/
public function testDuplicateDisplay() {
$view = $this->randomView();
$path_prefix = 'admin/structure/views/view/' . $view['id'] . '/edit';
$path = $view['page[path]'];
$this->drupalGet($path_prefix);
$this->drupalPostForm(NULL, [], 'Duplicate Page');
$this->assertLinkByHref($path_prefix . '/page_2', 0, 'Make sure after duplicating the new display appears in the UI');
$this->assertUrl($path_prefix . '/page_2', [], 'The user got redirected to the new display.');
// Set the title and override the css classes.
$random_title = $this->randomMachineName();
$random_css = $this->randomMachineName();
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/page_2/title", ['title' => $random_title], t('Apply'));
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/page_2/css_class", ['override[dropdown]' => 'page_2', 'css_class' => $random_css], t('Apply'));
// Duplicate as a different display type.
$this->drupalPostForm(NULL, [], 'Duplicate as Block');
$this->assertLinkByHref($path_prefix . '/block_1', 0, 'Make sure after duplicating the new display appears in the UI');
$this->assertUrl($path_prefix . '/block_1', [], 'The user got redirected to the new display.');
$this->assertText(t('Block settings'));
$this->assertNoText(t('Page settings'));
$this->drupalPostForm(NULL, [], t('Save'));
$view = Views::getView($view['id']);
$view->initDisplay();
$page_2 = $view->displayHandlers->get('page_2');
$this->assertTrue($page_2, 'The new page display got saved.');
$this->assertEqual($page_2->display['display_title'], 'Page');
$this->assertEqual($page_2->display['display_options']['path'], $path);
$block_1 = $view->displayHandlers->get('block_1');
$this->assertTrue($block_1, 'The new block display got saved.');
$this->assertEqual($block_1->display['display_plugin'], 'block');
$this->assertEqual($block_1->display['display_title'], 'Block', 'The new display title got generated as expected.');
$this->assertFalse(isset($block_1->display['display_options']['path']));
$this->assertEqual($block_1->getOption('title'), $random_title, 'The overridden title option from the display got copied into the duplicate');
$this->assertEqual($block_1->getOption('css_class'), $random_css, 'The overridden css_class option from the display got copied into the duplicate');
}
}

View file

@ -1,44 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Views;
/**
* Tests the display extender UI.
*
* @group views_ui
*/
class DisplayExtenderUITest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Tests the display extender UI.
*/
public function testDisplayExtenderUI() {
$this->config('views.settings')->set('display_extenders', ['display_extender_test'])->save();
$view = Views::getView('test_view');
$view_edit_url = "admin/structure/views/view/{$view->storage->id()}/edit";
$display_option_url = 'admin/structure/views/nojs/display/test_view/default/test_extender_test_option';
$this->drupalGet($view_edit_url);
$this->assertLinkByHref($display_option_url, 0, 'Make sure the option defined by the test display extender appears in the UI.');
$random_text = $this->randomMachineName();
$this->drupalPostForm($display_option_url, ['test_extender_test_option' => $random_text], t('Apply'));
$this->assertLink($random_text);
$this->drupalPostForm(NULL, [], t('Save'));
$view = Views::getView($view->storage->id());
$view->initDisplay();
$display_extender_options = $view->display_handler->getOption('display_extenders');
$this->assertEqual($display_extender_options['display_extender_test']['test_extender_test_option'], $random_text, 'Make sure that the display extender option got saved.');
}
}

View file

@ -1,84 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests the UI for feed display plugin.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\display\Feed
*/
class DisplayFeedTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_display_feed', 'test_style_opml'];
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['views_ui', 'aggregator'];
/**
* Tests feed display admin UI.
*/
public function testFeedUI() {
// Test both RSS and OPML feeds.
foreach (self::$testViews as $view_name) {
$this->checkFeedViewUi($view_name);
}
}
/**
* Checks views UI for a specific feed view.
*
* @param string $view_name
* The view name to check against.
*/
protected function checkFeedViewUi($view_name) {
$this->drupalGet('admin/structure/views');
// Verify that the page lists the $view_name view.
// Regression test: ViewListBuilder::getDisplayPaths() did not properly
// check whether a DisplayPluginCollection was returned in iterating over
// all displays.
$this->assertText($view_name);
// Check the attach TO interface.
$this->drupalGet('admin/structure/views/nojs/display/' . $view_name . '/feed_1/displays');
// Display labels should be escaped.
$this->assertEscaped('<em>Page</em>');
// Load all the options of the checkbox.
$result = $this->xpath('//div[@id="edit-displays"]/div');
$options = [];
foreach ($result as $item) {
foreach ($item->input->attributes() as $attribute => $value) {
if ($attribute == 'value') {
$options[] = (string) $value;
}
}
}
$this->assertEqual($options, ['default', 'page'], 'Make sure all displays appears as expected.');
// Post and save this and check the output.
$this->drupalPostForm('admin/structure/views/nojs/display/' . $view_name . '/feed_1/displays', ['displays[page]' => 'page'], t('Apply'));
// Options summary should be escaped.
$this->assertEscaped('<em>Page</em>');
$this->assertNoRaw('<em>Page</em>');
$this->drupalGet('admin/structure/views/view/' . $view_name . '/edit/feed_1');
$this->assertFieldByXpath('//*[@id="views-feed-1-displays"]', '<em>Page</em>');
// Add the default display, so there should now be multiple displays.
$this->drupalPostForm('admin/structure/views/nojs/display/' . $view_name . '/feed_1/displays', ['displays[default]' => 'default'], t('Apply'));
$this->drupalGet('admin/structure/views/view/' . $view_name . '/edit/feed_1');
$this->assertFieldByXpath('//*[@id="views-feed-1-displays"]', 'Multiple displays');
}
}

View file

@ -1,248 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\menu_link_content\Entity\MenuLinkContent;
/**
* Tests the UI of generic display path plugin.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\display\PathPluginBase
*/
class DisplayPathTest extends UITestBase {
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('page_title_block');
}
/**
* {@inheritdoc}
*/
public static $modules = ['menu_ui'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view', 'test_page_display_menu'];
/**
* Runs the tests.
*/
public function testPathUI() {
$this->doBasicPathUITest();
$this->doAdvancedPathsValidationTest();
$this->doPathXssFilterTest();
}
/**
* Tests basic functionality in configuring a view.
*/
protected function doBasicPathUITest() {
$this->drupalGet('admin/structure/views/view/test_view');
// Add a new page display and check the appearing text.
$this->drupalPostForm(NULL, [], 'Add Page');
$this->assertText(t('No path is set'), 'The right text appears if no path was set.');
$this->assertNoLink(t('View @display', ['@display' => 'page']), 'No view page link found on the page.');
// Save a path and make sure the summary appears as expected.
$random_path = $this->randomMachineName();
// @todo Once https://www.drupal.org/node/2351379 is resolved, Views will no
// longer use Url::fromUri(), and this path will be able to contain ':'.
$random_path = str_replace(':', '', $random_path);
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => $random_path], t('Apply'));
$this->assertText('/' . $random_path, 'The custom path appears in the summary.');
$display_link_text = t('View @display', ['@display' => 'Page']);
$this->assertLink($display_link_text, 0, 'view page link found on the page.');
$this->clickLink($display_link_text);
$this->assertUrl($random_path);
}
/**
* Tests that View paths are properly filtered for XSS.
*/
public function doPathXssFilterTest() {
$this->drupalGet('admin/structure/views/view/test_view');
$this->drupalPostForm(NULL, [], 'Add Page');
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_2/path', ['path' => '<object>malformed_path</object>'], t('Apply'));
$this->drupalPostForm(NULL, [], 'Add Page');
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_3/path', ['path' => '<script>alert("hello");</script>'], t('Apply'));
$this->drupalPostForm(NULL, [], 'Add Page');
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_4/path', ['path' => '<script>alert("hello I have placeholders %");</script>'], t('Apply'));
$this->drupalPostForm('admin/structure/views/view/test_view', [], t('Save'));
$this->drupalGet('admin/structure/views');
// The anchor text should be escaped.
$this->assertEscaped('/<object>malformed_path</object>');
$this->assertEscaped('/<script>alert("hello");</script>');
$this->assertEscaped('/<script>alert("hello I have placeholders %");</script>');
// Links should be url-encoded.
$this->assertRaw('/%3Cobject%3Emalformed_path%3C/object%3E');
$this->assertRaw('/%3Cscript%3Ealert%28%22hello%22%29%3B%3C/script%3E');
}
/**
* Tests a couple of invalid path patterns.
*/
protected function doAdvancedPathsValidationTest() {
$url = 'admin/structure/views/nojs/display/test_view/page_1/path';
$this->drupalPostForm($url, ['path' => '%/magrathea'], t('Apply'));
$this->assertUrl($url);
$this->assertText('"%" may not be used for the first segment of a path.');
$this->drupalPostForm($url, ['path' => 'user/%1/example'], t('Apply'));
$this->assertUrl($url);
$this->assertText("Numeric placeholders may not be used. Please use plain placeholders (%).");
}
/**
* Tests deleting a page display that has no path.
*/
public function testDeleteWithNoPath() {
$this->drupalGet('admin/structure/views/view/test_view');
$this->drupalPostForm(NULL, [], t('Add Page'));
$this->drupalPostForm(NULL, [], t('Delete Page'));
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertRaw(t('The view %view has been saved.', ['%view' => 'Test view']));
}
/**
* Tests the menu and tab option form.
*/
public function testMenuOptions() {
$this->container->get('module_installer')->install(['menu_ui']);
$this->drupalGet('admin/structure/views/view/test_view');
// Add a new page display.
$this->drupalPostForm(NULL, [], 'Add Page');
// Add an invalid path (only fragment).
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => '#foo'], t('Apply'));
$this->assertText('Path is empty');
// Add an invalid path with a query.
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => 'foo?bar'], t('Apply'));
$this->assertText('No query allowed.');
// Add an invalid path with just a query.
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => '?bar'], t('Apply'));
$this->assertText('Path is empty');
// Provide a random, valid path string.
$random_string = $this->randomMachineName();
// Save a path.
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => $random_string], t('Apply'));
$this->drupalGet('admin/structure/views/view/test_view');
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/menu', ['menu[type]' => 'default tab', 'menu[title]' => 'Test tab title'], t('Apply'));
$this->assertResponse(200);
$this->assertUrl('admin/structure/views/nojs/display/test_view/page_1/tab_options');
$this->drupalPostForm(NULL, ['tab_options[type]' => 'tab', 'tab_options[title]' => $this->randomString()], t('Apply'));
$this->assertResponse(200);
$this->assertUrl('admin/structure/views/view/test_view/edit/page_1');
$this->drupalGet('admin/structure/views/view/test_view');
$this->assertLink(t('Tab: @title', ['@title' => 'Test tab title']));
// If it's a default tab, it should also have an additional settings link.
$this->assertLinkByHref('admin/structure/views/nojs/display/test_view/page_1/tab_options');
// Ensure that you can select a parent in case the parent does not exist.
$this->drupalGet('admin/structure/views/nojs/display/test_page_display_menu/page_5/menu');
$this->assertResponse(200);
$menu_parent = $this->xpath('//select[@id="edit-menu-parent"]');
$menu_options = (array) $menu_parent[0]->option;
unset($menu_options['@attributes']);
$this->assertEqual([
'<User account menu>',
'-- My account',
'-- Log out',
'<Administration>',
'<Footer>',
'<Main navigation>',
'<Tools>',
'-- Compose tips (disabled)',
'-- Test menu link',
], $menu_options);
// The cache contexts associated with the (in)accessible menu links are
// bubbled.
$this->assertCacheContext('user.permissions');
}
/**
* Tests the regression in https://www.drupal.org/node/2532490.
*/
public function testDefaultMenuTabRegression() {
$this->container->get('module_installer')->install(['menu_ui', 'menu_link_content', 'toolbar', 'system']);
$admin_user = $this->drupalCreateUser([
'administer views',
'administer blocks',
'bypass node access',
'access user profiles',
'view all revisions',
'administer permissions',
'administer menu',
'link to any page',
'access toolbar',
]);
$this->drupalLogin($admin_user);
$edit = [
'title[0][value]' => 'Menu title',
'link[0][uri]' => '/admin/foo',
'menu_parent' => 'admin:system.admin'
];
$this->drupalPostForm('admin/structure/menu/manage/admin/add', $edit, t('Save'));
$menu_items = \Drupal::entityManager()->getStorage('menu_link_content')->getQuery()
->sort('id', 'DESC')
->pager(1)
->execute();
$menu_item = end($menu_items);
/** @var \Drupal\menu_link_content\MenuLinkContentInterface $menu_link_content */
$menu_link_content = MenuLinkContent::load($menu_item);
$edit = [];
$edit['label'] = $this->randomMachineName(16);
$view_id = $edit['id'] = strtolower($this->randomMachineName(16));
$edit['description'] = $this->randomMachineName(16);
$edit['page[create]'] = TRUE;
$edit['page[path]'] = 'admin/foo';
$this->drupalPostForm('admin/structure/views/add', $edit, t('Save and edit'));
$parameters = new MenuTreeParameters();
$parameters->addCondition('id', $menu_link_content->getPluginId());
$result = \Drupal::menuTree()->load('admin', $parameters);
$plugin_definition = end($result)->link->getPluginDefinition();
$this->assertEqual('view.' . $view_id . '.page_1', $plugin_definition['route_name']);
$this->clickLink(t('No menu'));
$this->drupalPostForm(NULL, [
'menu[type]' => 'default tab',
'menu[title]' => 'Menu title',
], t('Apply'));
$this->assertText('Default tab options');
$this->drupalPostForm(NULL, [
'tab_options[type]' => 'normal',
'tab_options[title]' => 'Parent title',
], t('Apply'));
$this->drupalPostForm(NULL, [], t('Save'));
// Assert that saving the view will not cause an exception.
$this->assertResponse(200);
}
}

View file

@ -1,331 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Template\Attribute;
use Drupal\views\Entity\View;
use Drupal\views\Views;
/**
* Tests the display UI.
*
* @group views_ui
*/
class DisplayTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_display'];
/**
* Modules to enable
*
* @var array
*/
public static $modules = ['contextual'];
/**
* Tests adding a display.
*/
public function testAddDisplay() {
$view = $this->randomView();
$this->assertNoText('Block');
$this->assertNoText('Block 2');
$this->drupalPostForm(NULL, [], t('Add @display', ['@display' => 'Block']));
$this->assertText('Block');
$this->assertNoText('Block 2');
// Views has special form handling in views_ui_form_button_was_clicked()
// to be able to change the submit button text via JS, this simulates what
// the JS is doing.
$this->drupalPostForm(NULL, [], NULL, [], [], NULL, '&op=Block');
$this->assertText('Block');
$this->assertText('Block 2');
}
/**
* Tests reordering of displays.
*/
public function testReorderDisplay() {
$view = [
'block[create]' => TRUE
];
$view = $this->randomView($view);
$this->clickLink(t('Reorder displays'));
$this->assertTrue($this->xpath('//tr[@id="display-row-default"]'), 'Make sure the default display appears on the reorder listing');
$this->assertTrue($this->xpath('//tr[@id="display-row-page_1"]'), 'Make sure the page display appears on the reorder listing');
$this->assertTrue($this->xpath('//tr[@id="display-row-block_1"]'), 'Make sure the block display appears on the reorder listing');
// Ensure the view displays are in the expected order in configuration.
$expected_display_order = ['default', 'block_1', 'page_1'];
$this->assertEqual(array_keys(Views::getView($view['id'])->storage->get('display')), $expected_display_order, 'The correct display names are present.');
// Put the block display in front of the page display.
$edit = [
'displays[page_1][weight]' => 2,
'displays[block_1][weight]' => 1
];
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalPostForm(NULL, [], t('Save'));
$view = Views::getView($view['id']);
$displays = $view->storage->get('display');
$this->assertEqual($displays['default']['position'], 0, 'Make sure the master display comes first.');
$this->assertEqual($displays['block_1']['position'], 1, 'Make sure the block display comes before the page display.');
$this->assertEqual($displays['page_1']['position'], 2, 'Make sure the page display comes after the block display.');
// Ensure the view displays are in the expected order in configuration.
$this->assertEqual(array_keys($view->storage->get('display')), $expected_display_order, 'The correct display names are present.');
}
/**
* Tests disabling of a display.
*/
public function testDisableDisplay() {
$view = $this->randomView();
$path_prefix = 'admin/structure/views/view/' . $view['id'] . '/edit';
$this->drupalGet($path_prefix);
$this->assertFalse($this->xpath('//div[contains(@class, :class)]', [':class' => 'views-display-disabled']), 'Make sure the disabled display css class does not appear after initial adding of a view.');
$this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-disable', '', 'Make sure the disable button is visible.');
$this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-enable', '', 'Make sure the enable button is not visible.');
$this->drupalPostForm(NULL, [], 'Disable Page');
$this->assertTrue($this->xpath('//div[contains(@class, :class)]', [':class' => 'views-display-disabled']), 'Make sure the disabled display css class appears once the display is marked as such.');
$this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-disable', '', 'Make sure the disable button is not visible.');
$this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-enable', '', 'Make sure the enable button is visible.');
$this->drupalPostForm(NULL, [], 'Enable Page');
$this->assertFalse($this->xpath('//div[contains(@class, :class)]', [':class' => 'views-display-disabled']), 'Make sure the disabled display css class does not appears once the display is enabled again.');
}
/**
* Tests views_ui_views_plugins_display_alter is altering plugin definitions.
*/
public function testDisplayPluginsAlter() {
$definitions = Views::pluginManager('display')->getDefinitions();
$expected = [
'route_name' => 'entity.view.edit_form',
'route_parameters_names' => ['view' => 'id'],
];
// Test the expected views_ui array exists on each definition.
foreach ($definitions as $definition) {
$this->assertIdentical($definition['contextual links']['entity.view.edit_form'], $expected, 'Expected views_ui array found in plugin definition.');
}
}
/**
* Tests display areas.
*/
public function testDisplayAreas() {
// Show the advanced column.
$this->config('views.settings')->set('ui.show.advanced_column', TRUE)->save();
// Add a new data display to the view.
$view = Views::getView('test_display');
$view->storage->addDisplay('display_no_area_test');
$view->save();
$this->drupalGet('admin/structure/views/view/test_display/edit/display_no_area_test_1');
$areas = [
'header',
'footer',
'empty',
];
// Assert that the expected text is found in each area category.
foreach ($areas as $type) {
$element = $this->xpath('//div[contains(@class, :class)]/div', [':class' => $type]);
$this->assertEqual((string) $element[0], SafeMarkup::format('The selected display type does not use @type plugins', ['@type' => $type]));
}
}
/**
* Tests the link-display setting.
*/
public function testLinkDisplay() {
// Test setting the link display in the UI form.
$path = 'admin/structure/views/view/test_display/edit/block_1';
$link_display_path = 'admin/structure/views/nojs/display/test_display/block_1/link_display';
// Test the link text displays 'None' and not 'Block 1'
$this->drupalGet($path);
$result = $this->xpath("//a[contains(@href, :path)]", [':path' => $link_display_path]);
$this->assertEqual($result[0], t('None'), 'Make sure that the link option summary shows "None" by default.');
$this->drupalGet($link_display_path);
$this->assertFieldChecked('edit-link-display-0');
// Test the default radio option on the link display form.
$this->drupalPostForm($link_display_path, ['link_display' => 'page_1'], t('Apply'));
// The form redirects to the master display.
$this->drupalGet($path);
$result = $this->xpath("//a[contains(@href, :path)]", [':path' => $link_display_path]);
$this->assertEqual($result[0], 'Page', 'Make sure that the link option summary shows the right linked display.');
$this->drupalPostForm($link_display_path, ['link_display' => 'custom_url', 'link_url' => 'a-custom-url'], t('Apply'));
// The form redirects to the master display.
$this->drupalGet($path);
$this->assertLink(t('Custom URL'), 0, 'The link option has custom URL as summary.');
// Test the default link_url value for new display
$this->drupalPostForm(NULL, [], t('Add Block'));
$this->assertUrl('admin/structure/views/view/test_display/edit/block_2');
$this->clickLink(t('Custom URL'));
$this->assertFieldByName('link_url', 'a-custom-url');
}
/**
* Tests contextual links on Views page displays.
*/
public function testPageContextualLinks() {
$this->drupalLogin($this->drupalCreateUser(['administer views', 'access contextual links']));
$view = View::load('test_display');
$view->enable()->save();
$this->container->get('router.builder')->rebuildIfNeeded();
// When no "main content" block is placed, we find a contextual link
// placeholder for editing just the view.
$this->drupalGet('test-display');
$id = 'entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1&langcode=en';
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder()
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id]));
// Get server-rendered contextual links.
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks()
$post = ['ids[0]' => $id];
$response = $this->drupalPostWithFormat('contextual/render', 'json', $post, ['query' => ['destination' => 'test-display']]);
$this->assertResponse(200);
$json = Json::decode($response);
$this->assertIdentical($json[$id], '<ul class="contextual-links"><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_display/edit/page_1">Edit view</a></li></ul>');
// When a "main content" is placed, we still find a contextual link
// placeholder for editing just the view (not the main content block).
// @see system_block_view_system_main_block_alter()
$this->drupalPlaceBlock('system_main_block', ['id' => 'main_content']);
$this->drupalGet('test-display');
$id = 'entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1&langcode=en';
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder()
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id]));
}
/**
* Tests that the view status is correctly reflected on the edit form.
*/
public function testViewStatus() {
$view = $this->randomView();
$id = $view['id'];
// The view should initially have the enabled class on it's form wrapper.
$this->drupalGet('admin/structure/views/view/' . $id);
$elements = $this->xpath('//div[contains(@class, :edit) and contains(@class, :status)]', [':edit' => 'views-edit-view', ':status' => 'enabled']);
$this->assertTrue($elements, 'The enabled class was found on the form wrapper');
$view = Views::getView($id);
$view->storage->disable()->save();
$this->drupalGet('admin/structure/views/view/' . $id);
$elements = $this->xpath('//div[contains(@class, :edit) and contains(@class, :status)]', [':edit' => 'views-edit-view', ':status' => 'disabled']);
$this->assertTrue($elements, 'The disabled class was found on the form wrapper.');
}
/**
* Ensures that no XSS is possible for buttons.
*/
public function testDisplayTitleInButtonsXss() {
$xss_markup = '"><script>alert(123)</script>';
$view = $this->randomView();
$view = View::load($view['id']);
\Drupal::configFactory()->getEditable('views.settings')->set('ui.show.master_display', TRUE)->save();
foreach ([$xss_markup, '&quot;><script>alert(123)</script>'] as $input) {
$display =& $view->getDisplay('page_1');
$display['display_title'] = $input;
$view->save();
$this->drupalGet("admin/structure/views/view/{$view->id()}");
$escaped = views_ui_truncate($input, 25);
$this->assertEscaped($escaped);
$this->assertNoRaw($xss_markup);
$this->drupalGet("admin/structure/views/view/{$view->id()}/edit/page_1");
$this->assertEscaped("View $escaped");
$this->assertNoRaw("View $xss_markup");
$this->assertEscaped("Duplicate $escaped");
$this->assertNoRaw("Duplicate $xss_markup");
$this->assertEscaped("Delete $escaped");
$this->assertNoRaw("Delete $xss_markup");
}
}
/**
* Tests the action links on the edit display UI.
*/
public function testActionLinks() {
// Change the display title of a display so it contains characters that will
// be escaped when rendered.
$display_title = "'<test>'";
$this->drupalGet('admin/structure/views/view/test_display');
$display_title_path = 'admin/structure/views/nojs/display/test_display/block_1/display_title';
$this->drupalPostForm($display_title_path, ['display_title' => $display_title], t('Apply'));
// Ensure that the title is escaped as expected.
$this->assertEscaped($display_title);
$this->assertNoRaw($display_title);
// Ensure that the dropdown buttons are displayed correctly.
$this->assertFieldByXpath('//input[@type="submit"]', 'Duplicate ' . $display_title);
$this->assertFieldByXpath('//input[@type="submit"]', 'Delete ' . $display_title);
$this->assertFieldByXpath('//input[@type="submit"]', 'Disable ' . $display_title);
$this->assertNoFieldByXpath('//input[@type="submit"]', 'Enable ' . $display_title);
// Disable the display so we can test the rendering of the "Enable" button.
$this->drupalPostForm(NULL, NULL, 'Disable ' . $display_title);
$this->assertFieldByXpath('//input[@type="submit"]', 'Enable ' . $display_title);
$this->assertNoFieldByXpath('//input[@type="submit"]', 'Disable ' . $display_title);
// Ensure that the title is escaped as expected.
$this->assertEscaped($display_title);
$this->assertNoRaw($display_title);
}
/**
* Tests that the override option is hidden when it's not needed.
*/
public function testHideDisplayOverride() {
// Test that the override option appears with two displays.
$this->drupalGet('admin/structure/views/nojs/handler/test_display/page_1/field/title');
$this->assertText('All displays');
// Remove a display and test if the override option is hidden.
$this->drupalPostForm('admin/structure/views/view/test_display/edit/block_1', [], t('Delete @display', ['@display' => 'Block']));
$this->drupalPostForm(NULL, [], t('Save'));
$this->drupalGet('admin/structure/views/nojs/handler/test_display/page_1/field/title');
$this->assertNoText('All displays');
// Test that the override option is shown when display master is on.
\Drupal::configFactory()->getEditable('views.settings')->set('ui.show.master_display', TRUE)->save();
$this->drupalGet('admin/structure/views/nojs/handler/test_display/page_1/field/title');
$this->assertText('All displays');
// Test that the override option is shown if the current display is
// overridden so that the option to revert is available.
$this->drupalPostForm(NULL, ['override[dropdown]' => 'page_1'], t('Apply'));
\Drupal::configFactory()->getEditable('views.settings')->set('ui.show.master_display', FALSE)->save();
$this->drupalGet('admin/structure/views/nojs/handler/test_display/page_1/field/title');
$this->assertText('Revert to default');
}
}

View file

@ -1,43 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests the UI for view duplicate tool.
*
* @group views_ui
*/
class DuplicateTest extends UITestBase {
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('page_title_block');
}
/**
* Checks if duplicated view exists and has correct label.
*/
public function testDuplicateView() {
// Create random view.
$random_view = $this->randomView();
// Initialize array for duplicated view.
$view = [];
// Generate random label and id for new view.
$view['label'] = $this->randomMachineName(255);
$view['id'] = strtolower($this->randomMachineName(128));
// Duplicate view.
$this->drupalPostForm('admin/structure/views/view/' . $random_view['id'] . '/duplicate', $view, t('Duplicate'));
// Assert that the page url is correct.
$this->assertUrl('admin/structure/views/view/' . $view['id'], [], 'Make sure the view saving was successful and the browser got redirected to the edit page.');
// Assert that the page title is correctly displayed.
$this->assertText($view['label']);
}
}

View file

@ -1,320 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Entity\View;
/**
* Tests exposed forms UI functionality.
*
* @group views_ui
*/
class ExposedFormUITest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_exposed_admin_ui'];
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'views_ui', 'block', 'taxonomy', 'field_ui', 'datetime'];
/**
* Array of error message strings raised by the grouped form.
*
* @var array
*
* @see FilterPluginBase::buildGroupValidate
*/
protected $groupFormUiErrors = [];
protected function setUp() {
parent::setUp();
$this->drupalCreateContentType(['type' => 'article']);
$this->drupalCreateContentType(['type' => 'page']);
// Create some random nodes.
for ($i = 0; $i < 5; $i++) {
$this->drupalCreateNode();
}
// Error strings used in the grouped filter form validation.
$this->groupFormUiErrors['missing_value'] = t('A value is required if the label for this item is defined.');
$this->groupFormUiErrors['missing_title'] = t('A label is required if the value for this item is defined.');
$this->groupFormUiErrors['missing_title_empty_operator'] = t('A label is required for the specified operator.');
}
/**
* Tests the admin interface of exposed filter and sort items.
*/
public function testExposedAdminUi() {
$edit = [];
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type');
// Be sure that the button is called exposed.
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose filter'));
// The first time the filter UI is displayed, the operator and the
// value forms should be shown.
$this->assertFieldById('edit-options-operator-in', '', 'Operator In exists');
$this->assertFieldById('edit-options-operator-not-in', '', 'Operator Not In exists');
$this->assertFieldById('edit-options-value-page', '', 'Checkbox for Page exists');
$this->assertFieldById('edit-options-value-article', '', 'Checkbox for Article exists');
// Click the Expose filter button.
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type', $edit, t('Expose filter'));
// Check the label of the expose button.
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide filter'));
// After exposing the filter, Operator and Value should be still here.
$this->assertFieldById('edit-options-operator-in', '', 'Operator In exists');
$this->assertFieldById('edit-options-operator-not-in', '', 'Operator Not In exists');
$this->assertFieldById('edit-options-value-page', '', 'Checkbox for Page exists');
$this->assertFieldById('edit-options-value-article', '', 'Checkbox for Article exists');
// Check the validations of the filter handler.
$edit = [];
$edit['options[expose][identifier]'] = '';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertText(t('The identifier is required if the filter is exposed.'));
$edit = [];
$edit['options[expose][identifier]'] = 'value';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertText(t('This identifier is not allowed.'));
// Now check the sort criteria.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/sort/created');
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Expose sort'));
$this->assertNoFieldById('edit-options-expose-label', '', 'Make sure no label field is shown');
// Un-expose the filter.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type');
$this->drupalPostForm(NULL, [], t('Hide filter'));
// After Un-exposing the filter, Operator and Value should be shown again.
$this->assertFieldById('edit-options-operator-in', '', 'Operator In exists after hide filter');
$this->assertFieldById('edit-options-operator-not-in', '', 'Operator Not In exists after hide filter');
$this->assertFieldById('edit-options-value-page', '', 'Checkbox for Page exists after hide filter');
$this->assertFieldById('edit-options-value-article', '', 'Checkbox for Article exists after hide filter');
// Click the Expose sort button.
$edit = [];
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/sort/created', $edit, t('Expose sort'));
// Check the label of the expose button.
$this->helperButtonHasLabel('edit-options-expose-button-button', t('Hide sort'));
$this->assertFieldById('edit-options-expose-label', '', 'Make sure a label field is shown');
// Test adding a new exposed sort criteria.
$view_id = $this->randomView()['id'];
$this->drupalGet("admin/structure/views/nojs/add-handler/$view_id/default/sort");
$this->drupalPostForm(NULL, ['name[node_field_data.created]' => 1], t('Add and configure @handler', ['@handler' => t('sort criteria')]));
$this->assertFieldByXPath('//input[@name="options[order]" and @checked="checked"]', 'ASC', 'The default order is set.');
// Change the order and expose the sort.
$this->drupalPostForm(NULL, ['options[order]' => 'DESC'], t('Apply'));
$this->drupalPostForm("admin/structure/views/nojs/handler/$view_id/default/sort/created", [], t('Expose sort'));
$this->assertFieldByXPath('//input[@name="options[order]" and @checked="checked"]', 'DESC');
$this->assertFieldByName('options[expose][label]', 'Authored on', 'The default label is set.');
// Change the label and save the view.
$edit = ['options[expose][label]' => $this->randomString()];
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalPostForm(NULL, [], t('Save'));
// Check that the values were saved.
$display = View::load($view_id)->getDisplay('default');
$this->assertTrue($display['display_options']['sorts']['created']['exposed']);
$this->assertEqual($display['display_options']['sorts']['created']['expose'], ['label' => $edit['options[expose][label]']]);
$this->assertEqual($display['display_options']['sorts']['created']['order'], 'DESC');
}
/**
* Tests the admin interface of exposed grouped filters.
*/
public function testGroupedFilterAdminUi() {
$edit = [];
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type');
// Click the Expose filter button.
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type', $edit, t('Expose filter'));
// Check the label of the grouped filters button.
$this->helperButtonHasLabel('edit-options-group-button-button', t('Grouped filters'));
// Click the Grouped Filters button.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type');
$this->drupalPostForm(NULL, [], t('Grouped filters'));
// After click on 'Grouped Filters', the standard operator and value should
// not be displayed.
$this->assertNoFieldById('edit-options-operator-in', '', 'Operator In not exists');
$this->assertNoFieldById('edit-options-operator-not-in', '', 'Operator Not In not exists');
$this->assertNoFieldById('edit-options-value-page', '', 'Checkbox for Page not exists');
$this->assertNoFieldById('edit-options-value-article', '', 'Checkbox for Article not exists');
// Check that after click on 'Grouped Filters', a new button is shown to
// add more items to the list.
$this->helperButtonHasLabel('edit-options-group-info-add-group', t('Add another item'));
// Validate a single entry for a grouped filter.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type');
$edit = [];
$edit["options[group_info][group_items][1][title]"] = 'Is Article';
$edit["options[group_info][group_items][1][value][article]"] = 'article';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertUrl('admin/structure/views/view/test_exposed_admin_ui/edit/default');
$this->assertNoGroupedFilterErrors();
// Validate multiple entries for grouped filters.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type');
$edit = [];
$edit["options[group_info][group_items][1][title]"] = 'Is Article';
$edit["options[group_info][group_items][1][value][article]"] = 'article';
$edit["options[group_info][group_items][2][title]"] = 'Is Page';
$edit["options[group_info][group_items][2][value][page]"] = 'page';
$edit["options[group_info][group_items][3][title]"] = 'Is Page and Article';
$edit["options[group_info][group_items][3][value][article]"] = 'article';
$edit["options[group_info][group_items][3][value][page]"] = 'page';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertUrl('admin/structure/views/view/test_exposed_admin_ui/edit/default', [], 'Correct validation of the node type filter.');
$this->assertNoGroupedFilterErrors();
// Validate an "is empty" filter -- title without value is valid.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/body_value');
$edit = [];
$edit["options[group_info][group_items][1][title]"] = 'No body';
$edit["options[group_info][group_items][1][operator]"] = 'empty';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertUrl('admin/structure/views/view/test_exposed_admin_ui/edit/default', [], 'The "empty" operator validates correctly.');
$this->assertNoGroupedFilterErrors();
// Ensure the string "0" can be used as a value for numeric filters.
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_exposed_admin_ui/default/filter', ['name[node_field_data.nid]' => TRUE], t('Add and configure @handler', ['@handler' => t('filter criteria')]));
$this->drupalPostForm(NULL, [], t('Expose filter'));
$this->drupalPostForm(NULL, [], t('Grouped filters'));
$edit = [];
$edit['options[group_info][group_items][1][title]'] = 'Testing zero';
$edit['options[group_info][group_items][1][operator]'] = '>';
$edit['options[group_info][group_items][1][value][value]'] = '0';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertUrl('admin/structure/views/view/test_exposed_admin_ui/edit/default', [], 'A string "0" is a valid value.');
$this->assertNoGroupedFilterErrors();
// Ensure "between" filters validate correctly.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/nid');
$edit['options[group_info][group_items][1][title]'] = 'ID between test';
$edit['options[group_info][group_items][1][operator]'] = 'between';
$edit['options[group_info][group_items][1][value][min]'] = '0';
$edit['options[group_info][group_items][1][value][max]'] = '10';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertUrl('admin/structure/views/view/test_exposed_admin_ui/edit/default', [], 'The "between" filter validates correctly.');
$this->assertNoGroupedFilterErrors();
}
public function testGroupedFilterAdminUiErrors() {
// Select the empty operator without a title specified.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/body_value');
$edit = [];
$edit["options[group_info][group_items][1][title]"] = '';
$edit["options[group_info][group_items][1][operator]"] = 'empty';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertText($this->groupFormUiErrors['missing_title_empty_operator']);
// Specify a title without a value.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type');
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type', [], t('Expose filter'));
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type', [], t('Grouped filters'));
$edit = [];
$edit["options[group_info][group_items][1][title]"] = 'Is Article';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertText($this->groupFormUiErrors['missing_value']);
// Specify a value without a title.
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type');
$edit = [];
$edit["options[group_info][group_items][1][title]"] = '';
$edit["options[group_info][group_items][1][value][article]"] = 'article';
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertText($this->groupFormUiErrors['missing_title']);
}
/**
* Asserts that there are no Grouped Filters errors.
*
* @param string $message
* The assert message.
* @param string $group
* The assertion group.
*
* @return bool
* Result of the assertion.
*/
protected function assertNoGroupedFilterErrors($message = '', $group = 'Other') {
foreach ($this->groupFormUiErrors as $error) {
$err_message = $message;
if (empty($err_message)) {
$err_message = "Verify that '$error' is not in the HTML output.";
}
if (empty($message)) {
return $this->assertNoRaw($error, $err_message, $group);
}
}
return TRUE;
}
/**
* Tests the configuration of grouped exposed filters.
*/
public function testExposedGroupedFilter() {
// Click the Expose filter button.
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type', [], t('Expose filter'));
// Select 'Grouped filters' radio button.
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/type', [], t('Grouped filters'));
// Add 3 groupings.
$edit = [
'options[group_button][radios][radios]' => 1,
'options[group_info][group_items][1][title]' => '1st',
'options[group_info][group_items][1][value][all]' => 'all',
'options[group_info][group_items][2][title]' => '2nd',
'options[group_info][group_items][2][value][article]' => 'article',
'options[group_info][group_items][3][title]' => '3rd',
'options[group_info][group_items][3][value][page]' => 'page',
];
// Apply the filter settings.
$this->drupalPostForm(NULL, $edit, t('Apply'));
// Check that the view is saved without errors.
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertResponse(200);
// Click the Expose filter button.
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_exposed_admin_ui/default/filter', ['name[node_field_data.status]' => 1], t('Add and configure filter criteria'));
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/status', [], t('Expose filter'));
// Select 'Grouped filters' radio button.
$this->drupalPostForm('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/status', [], t('Grouped filters'));
// Add 3 groupings.
$edit = [
'options[group_button][radios][radios]' => 1,
'options[group_info][group_items][1][title]' => 'Any',
'options[group_info][group_items][1][value]' => 'All',
'options[group_info][group_items][2][title]' => 'Published',
'options[group_info][group_items][2][value]' => 1,
'options[group_info][group_items][3][title]' => 'Unpublished',
'options[group_info][group_items][3][value]' => 0,
];
// Apply the filter settings.
$this->drupalPostForm(NULL, $edit, t('Apply'));
// Check that the view is saved without errors.
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertResponse(200);
$this->drupalGet('admin/structure/views/nojs/handler/test_exposed_admin_ui/default/filter/status');
// Assert the same settings defined before still are there.
$this->assertFieldChecked('edit-options-group-info-group-items-1-value-all');
$this->assertFieldChecked('edit-options-group-info-group-items-2-value-1');
$this->assertFieldChecked('edit-options-group-info-group-items-3-value-0');
}
}

View file

@ -1,100 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\Component\Serialization\Json;
use Drupal\views\Views;
/**
* Tests the UI of field handlers.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\field\FieldPluginBase
*/
class FieldUITest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Tests the UI of field handlers.
*/
public function testFieldUI() {
// Ensure the field is not marked as hidden on the first run.
$this->drupalGet('admin/structure/views/view/test_view/edit');
$this->assertText('Views test: Name');
$this->assertNoText('Views test: Name [' . t('hidden') . ']');
// Hides the field and check whether the hidden label is appended.
$edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/name';
$this->drupalPostForm($edit_handler_url, ['options[exclude]' => TRUE], t('Apply'));
$this->assertText('Views test: Name [' . t('hidden') . ']');
// Ensure that the expected tokens appear in the UI.
$edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/age';
$this->drupalGet($edit_handler_url);
$result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li');
$this->assertEqual((string) $result[0], '{{ age }} == Age');
$edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/id';
$this->drupalGet($edit_handler_url);
$result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li');
$this->assertEqual((string) $result[0], '{{ age }} == Age');
$this->assertEqual((string) $result[1], '{{ id }} == ID');
$edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/name';
$this->drupalGet($edit_handler_url);
$result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li');
$this->assertEqual((string) $result[0], '{{ age }} == Age');
$this->assertEqual((string) $result[1], '{{ id }} == ID');
$this->assertEqual((string) $result[2], '{{ name }} == Name');
$result = $this->xpath('//details[@id="edit-options-more"]');
$this->assertEqual(empty($result), TRUE, "Container 'more' is empty and should not be displayed.");
// Ensure that dialog titles are not escaped.
$edit_groupby_url = 'admin/structure/views/nojs/handler/test_view/default/field/name';
$this->assertNoLinkByHref($edit_groupby_url, 0, 'No aggregation link found.');
// Enable aggregation on the view.
$edit = [
'group_by' => TRUE,
];
$this->drupalPostForm('/admin/structure/views/nojs/display/test_view/default/group_by', $edit, t('Apply'));
$this->assertLinkByHref($edit_groupby_url, 0, 'Aggregation link found.');
$edit_handler_url = '/admin/structure/views/ajax/handler-group/test_view/default/field/name';
$this->drupalGet($edit_handler_url);
$data = Json::decode($this->getRawContent());
$this->assertEqual($data[3]['dialogOptions']['title'], 'Configure aggregation settings for field Views test: Name');
}
/**
* Tests the field labels.
*/
public function testFieldLabel() {
// Create a view with unformatted style and make sure the fields have no
// labels by default.
$view = [];
$view['label'] = $this->randomMachineName(16);
$view['id'] = strtolower($this->randomMachineName(16));
$view['description'] = $this->randomMachineName(16);
$view['show[wizard_key]'] = 'node';
$view['page[create]'] = TRUE;
$view['page[style][style_plugin]'] = 'default';
$view['page[title]'] = $this->randomMachineName(16);
$view['page[path]'] = $view['id'];
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$view = Views::getView($view['id']);
$view->initHandlers();
$this->assertEqual($view->field['title']->options['label'], '', 'The field label for normal styles are empty.');
}
}

View file

@ -1,68 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests the boolean filter UI.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\filter\BooleanOperator
*/
class FilterBooleanWebTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Tests the filter boolean UI.
*/
public function testFilterBooleanUI() {
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_view/default/filter', ['name[views_test_data.status]' => TRUE], t('Add and configure @handler', ['@handler' => t('filter criteria')]));
// Check the field widget label. 'title' should be used as a fallback.
$result = $this->cssSelect('#edit-options-value--wrapper legend span');
$this->assertEqual((string) $result[0], 'Status');
$this->drupalPostForm(NULL, [], t('Expose filter'));
$this->drupalPostForm(NULL, [], t('Grouped filters'));
$edit = [];
$edit['options[group_info][group_items][1][title]'] = 'Published';
$edit['options[group_info][group_items][1][operator]'] = '=';
$edit['options[group_info][group_items][1][value]'] = 1;
$edit['options[group_info][group_items][2][title]'] = 'Not published';
$edit['options[group_info][group_items][2][operator]'] = '=';
$edit['options[group_info][group_items][2][value]'] = 0;
$edit['options[group_info][group_items][3][title]'] = 'Not published2';
$edit['options[group_info][group_items][3][operator]'] = '!=';
$edit['options[group_info][group_items][3][value]'] = 1;
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalGet('admin/structure/views/nojs/handler/test_view/default/filter/status');
$result = $this->xpath('//input[@name="options[group_info][group_items][1][value]"]');
$this->assertEqual((int) $result[1]->attributes()->checked, 'checked');
$result = $this->xpath('//input[@name="options[group_info][group_items][2][value]"]');
$this->assertEqual((int) $result[2]->attributes()->checked, 'checked');
$result = $this->xpath('//input[@name="options[group_info][group_items][3][value]"]');
$this->assertEqual((int) $result[1]->attributes()->checked, 'checked');
// Test that there is a remove link for each group.
$this->assertEqual(count($this->cssSelect('a.views-remove-link')), 3);
// Test selecting a default and removing an item.
$edit = [];
$edit['options[group_info][default_group]'] = 2;
$edit['options[group_info][group_items][3][remove]'] = 1;
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalGet('admin/structure/views/nojs/handler/test_view/default/filter/status');
$this->assertFieldByName('options[group_info][default_group]', 2, 'Second item was set as the default.');
$this->assertNoField('options[group_info][group_items][3][remove]', 'Third item was removed.');
}
}

View file

@ -1,112 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\Tests\SchemaCheckTestTrait;
/**
* Tests the numeric filter UI.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\filter\NumericFilter
*/
class FilterNumericWebTest extends UITestBase {
use SchemaCheckTestTrait;
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Tests the filter numeric UI.
*/
public function testFilterNumericUI() {
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_view/default/filter', ['name[views_test_data.age]' => TRUE], t('Add and configure @handler', ['@handler' => t('filter criteria')]));
$this->drupalPostForm(NULL, [], t('Expose filter'));
$this->drupalPostForm(NULL, [], t('Grouped filters'));
$edit = [];
$edit['options[group_info][group_items][1][title]'] = 'Old';
$edit['options[group_info][group_items][1][operator]'] = '>';
$edit['options[group_info][group_items][1][value][value]'] = 27;
$edit['options[group_info][group_items][2][title]'] = 'Young';
$edit['options[group_info][group_items][2][operator]'] = '<=';
$edit['options[group_info][group_items][2][value][value]'] = 27;
$edit['options[group_info][group_items][3][title]'] = 'From 26 to 28';
$edit['options[group_info][group_items][3][operator]'] = 'between';
$edit['options[group_info][group_items][3][value][min]'] = 26;
$edit['options[group_info][group_items][3][value][max]'] = 28;
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalGet('admin/structure/views/nojs/handler/test_view/default/filter/age');
foreach ($edit as $name => $value) {
$this->assertFieldByName($name, $value);
}
$this->drupalPostForm('admin/structure/views/view/test_view', [], t('Save'));
$this->assertConfigSchemaByName('views.view.test_view');
// Test that the exposed filter works as expected.
$this->drupalPostForm(NULL, [], t('Update preview'));
$this->assertText('John');
$this->assertText('Paul');
$this->assertText('Ringo');
$this->assertText('George');
$this->assertText('Meredith');
$this->drupalPostForm(NULL, ['age' => '2'], t('Update preview'));
$this->assertText('John');
$this->assertText('Paul');
$this->assertNoText('Ringo');
$this->assertText('George');
$this->assertNoText('Meredith');
// Change the filter to a single filter to test the schema when the operator
// is not exposed.
$this->drupalPostForm('admin/structure/views/nojs/handler/test_view/default/filter/age', [], t('Single filter'));
$edit = [];
$edit['options[value][value]'] = 25;
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalPostForm('admin/structure/views/view/test_view', [], t('Save'));
$this->assertConfigSchemaByName('views.view.test_view');
// Test that the filter works as expected.
$this->drupalPostForm(NULL, [], t('Update preview'));
$this->assertText('John');
$this->assertNoText('Paul');
$this->assertNoText('Ringo');
$this->assertNoText('George');
$this->assertNoText('Meredith');
$this->drupalPostForm(NULL, ['age' => '26'], t('Update preview'));
$this->assertNoText('John');
$this->assertText('Paul');
$this->assertNoText('Ringo');
$this->assertNoText('George');
$this->assertNoText('Meredith');
// Change the filter to a 'between' filter to test if the label and
// description are set for the 'minimum' filter element.
$this->drupalGet('admin/structure/views/nojs/handler/test_view/default/filter/age');
$edit = [];
$edit['options[expose][label]'] = 'Age between';
$edit['options[expose][description]'] = 'Description of the exposed filter';
$edit['options[operator]'] = 'between';
$edit['options[value][min]'] = 26;
$edit['options[value][max]'] = 28;
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalPostForm('admin/structure/views/view/test_view', [], t('Save'));
$this->assertConfigSchemaByName('views.view.test_view');
$this->drupalPostForm(NULL, [], t('Update preview'));
// Check the max field label.
$this->assertRaw('<label for="edit-age-max">And</label>', 'Max field label found');
$this->assertRaw('<label for="edit-age-min">Age between</label>', 'Min field label found');
// Check that the description is shown in the right place.
$this->assertEqual(trim($this->cssSelect('.form-item-age-min .description')[0]), 'Description of the exposed filter');
}
}

View file

@ -1,123 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Tests\ViewTestBase;
/**
* Tests for the filters from the UI.
*
* @group views_ui
*/
class FilterUITest extends ViewTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_filter_in_operator_ui', 'test_filter_groups'];
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['views_ui', 'node'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalCreateContentType(['type' => 'page']);
$this->enableViewsTestModule();
}
/**
* Tests that an option for a filter is saved as expected from the UI.
*/
public function testFilterInOperatorUi() {
$admin_user = $this->drupalCreateUser(['administer views', 'administer site configuration']);
$this->drupalLogin($admin_user);
$path = 'admin/structure/views/nojs/handler/test_filter_in_operator_ui/default/filter/type';
$this->drupalGet($path);
// Verifies that "Limit list to selected items" option is not selected.
$this->assertFieldByName('options[expose][reduce]', FALSE);
// Select "Limit list to selected items" option and apply.
$edit = [
'options[expose][reduce]' => TRUE,
];
$this->drupalPostForm($path, $edit, t('Apply'));
// Verifies that the option was saved as expected.
$this->drupalGet($path);
$this->assertFieldByName('options[expose][reduce]', TRUE);
}
/**
* Tests the filters from the UI.
*/
public function testFiltersUI() {
$admin_user = $this->drupalCreateUser(['administer views', 'administer site configuration']);
$this->drupalLogin($admin_user);
$this->drupalGet('admin/structure/views/view/test_filter_groups');
$this->assertLink('Content: ID (= 1)', 0, 'Content: ID (= 1) link appears correctly.');
// Tests that we can create a new filter group from UI.
$this->drupalGet('admin/structure/views/nojs/rearrange-filter/test_filter_groups/page');
$this->assertNoRaw('<span>Group 3</span>', 'Group 3 has not been added yet.');
// Create 2 new groups.
$this->drupalPostForm(NULL, [], t('Create new filter group'));
$this->drupalPostForm(NULL, [], t('Create new filter group'));
// Remove the new group 3.
$this->drupalPostForm(NULL, [], t('Remove group 3'));
// Verify that the group 4 is now named as 3.
$this->assertRaw('<span>Group 3</span>', 'Group 3 still exists.');
// Remove the group 3 again.
$this->drupalPostForm(NULL, [], t('Remove group 3'));
// Group 3 now does not exist.
$this->assertNoRaw('<span>Group 3</span>', 'Group 3 has not been added yet.');
}
/**
* Tests the identifier settings and restrictions.
*/
public function testFilterIdentifier() {
$admin_user = $this->drupalCreateUser(['administer views', 'administer site configuration']);
$this->drupalLogin($admin_user);
$path = 'admin/structure/views/nojs/handler/test_filter_in_operator_ui/default/filter/type';
// Set an empty identifier.
$edit = [
'options[expose][identifier]' => '',
];
$this->drupalPostForm($path, $edit, t('Apply'));
$this->assertText('The identifier is required if the filter is exposed.');
// Set the identifier to 'value'.
$edit = [
'options[expose][identifier]' => 'value',
];
$this->drupalPostForm($path, $edit, t('Apply'));
$this->assertText('This identifier is not allowed.');
// Set the identifier to a value with a restricted character.
$edit = [
'options[expose][identifier]' => 'value value',
];
$this->drupalPostForm($path, $edit, t('Apply'));
$this->assertText('This identifier has illegal characters.');
}
}

View file

@ -1,50 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests UI of aggregate functionality..
*
* @group views_ui
*/
class GroupByTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_views_groupby_save'];
/**
* Tests whether basic saving works.
*
* @todo This should check the change of the settings as well.
*/
public function testGroupBySave() {
$this->drupalGet('admin/structure/views/view/test_views_groupby_save/edit');
$edit_groupby_url = 'admin/structure/views/nojs/handler-group/test_views_groupby_save/default/field/id';
$this->assertNoLinkByHref($edit_groupby_url, 0, 'No aggregation link found.');
// Enable aggregation on the view.
$edit = [
'group_by' => TRUE,
];
$this->drupalPostForm('admin/structure/views/nojs/display/test_views_groupby_save/default/group_by', $edit, t('Apply'));
$this->assertLinkByHref($edit_groupby_url, 0, 'Aggregation link found.');
// Change the groupby type in the UI.
$this->drupalPostForm($edit_groupby_url, ['options[group_type]' => 'count'], t('Apply'));
$this->assertLink('COUNT(Views test: ID)', 0, 'The count setting is displayed in the UI');
$this->drupalPostForm(NULL, [], t('Save'));
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_views_groupby_save');
$display = $view->getDisplay('default');
$this->assertTrue($display['display_options']['group_by'], 'The groupby setting was saved on the view.');
$this->assertEqual($display['display_options']['fields']['id']['group_type'], 'count', 'Count groupby_type was saved on the view.');
}
}

View file

@ -1,282 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\views\Tests\ViewTestData;
use Drupal\views\ViewExecutable;
/**
* Tests handler UI for views.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\HandlerBase
*/
class HandlerTest extends UITestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['node_test_views'];
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view_empty', 'test_view_broken', 'node', 'test_node_view'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('page_title_block');
ViewTestData::createTestViews(get_class($this), ['node_test_views']);
}
/**
* Overrides \Drupal\views\Tests\ViewTestBase::schemaDefinition().
*
* Adds a uid column to test the relationships.
*/
protected function schemaDefinition() {
$schema = parent::schemaDefinition();
$schema['views_test_data']['fields']['uid'] = [
'description' => "The {users}.uid of the author of the beatle entry.",
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0
];
return $schema;
}
/**
* Overrides \Drupal\views\Tests\ViewTestBase::viewsData().
*
* Adds:
* - a relationship for the uid column.
* - a dummy field with no help text.
*/
protected function viewsData() {
$data = parent::viewsData();
$data['views_test_data']['uid'] = [
'title' => t('UID'),
'help' => t('The test data UID'),
'relationship' => [
'id' => 'standard',
'base' => 'users_field_data',
'base field' => 'uid'
]
];
// Create a dummy field with no help text.
$data['views_test_data']['no_help'] = $data['views_test_data']['name'];
$data['views_test_data']['no_help']['field']['title'] = t('No help');
$data['views_test_data']['no_help']['field']['real field'] = 'name';
unset($data['views_test_data']['no_help']['help']);
return $data;
}
/**
* Tests UI CRUD.
*/
public function testUICRUD() {
$handler_types = ViewExecutable::getHandlerTypes();
foreach ($handler_types as $type => $type_info) {
// Test adding handlers.
$add_handler_url = "admin/structure/views/nojs/add-handler/test_view_empty/default/$type";
// Area handler types need to use a different handler.
if (in_array($type, ['header', 'footer', 'empty'])) {
$this->drupalPostForm($add_handler_url, ['name[views.area]' => TRUE], t('Add and configure @handler', ['@handler' => $type_info['ltitle']]));
$id = 'area';
$edit_handler_url = "admin/structure/views/nojs/handler/test_view_empty/default/$type/$id";
}
elseif ($type == 'relationship') {
$this->drupalPostForm($add_handler_url, ['name[views_test_data.uid]' => TRUE], t('Add and configure @handler', ['@handler' => $type_info['ltitle']]));
$id = 'uid';
$edit_handler_url = "admin/structure/views/nojs/handler/test_view_empty/default/$type/$id";
}
else {
$this->drupalPostForm($add_handler_url, ['name[views_test_data.job]' => TRUE], t('Add and configure @handler', ['@handler' => $type_info['ltitle']]));
$id = 'job';
$edit_handler_url = "admin/structure/views/nojs/handler/test_view_empty/default/$type/$id";
}
$this->assertUrl($edit_handler_url, [], 'The user got redirected to the handler edit form.');
$random_label = $this->randomMachineName();
$this->drupalPostForm(NULL, ['options[admin_label]' => $random_label], t('Apply'));
$this->assertUrl('admin/structure/views/view/test_view_empty/edit/default', [], 'The user got redirected to the views edit form.');
$this->assertLinkByHref($edit_handler_url, 0, 'The handler edit link appears in the UI.');
$links = $this->xpath('//a[starts-with(normalize-space(text()), :label)]', [':label' => $random_label]);
$this->assertTrue(isset($links[0]), 'The handler edit link has the right label');
// Save the view and have a look whether the handler was added as expected.
$this->drupalPostForm(NULL, [], t('Save'));
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_view_empty');
$display = $view->getDisplay('default');
$this->assertTrue(isset($display['display_options'][$type_info['plural']][$id]), 'Ensure the field was added to the view itself.');
// Remove the item and check that it's removed
$this->drupalPostForm($edit_handler_url, [], t('Remove'));
$this->assertNoLinkByHref($edit_handler_url, 0, 'The handler edit link does not appears in the UI after removing.');
$this->drupalPostForm(NULL, [], t('Save'));
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_view_empty');
$display = $view->getDisplay('default');
$this->assertFalse(isset($display['display_options'][$type_info['plural']][$id]), 'Ensure the field was removed from the view itself.');
}
// Test adding a field of the user table using the uid relationship.
$type_info = $handler_types['relationship'];
$add_handler_url = "admin/structure/views/nojs/add-handler/test_view_empty/default/relationship";
$this->drupalPostForm($add_handler_url, ['name[views_test_data.uid]' => TRUE], t('Add and configure @handler', ['@handler' => $type_info['ltitle']]));
$add_handler_url = "admin/structure/views/nojs/add-handler/test_view_empty/default/field";
$type_info = $handler_types['field'];
$this->drupalPostForm($add_handler_url, ['name[users_field_data.name]' => TRUE], t('Add and configure @handler', ['@handler' => $type_info['ltitle']]));
$id = 'name';
$edit_handler_url = "admin/structure/views/nojs/handler/test_view_empty/default/field/$id";
$this->assertUrl($edit_handler_url, [], 'The user got redirected to the handler edit form.');
$this->assertFieldByName('options[relationship]', 'uid', 'Ensure the relationship select is filled with the UID relationship.');
$this->drupalPostForm(NULL, [], t('Apply'));
$this->drupalPostForm(NULL, [], t('Save'));
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_view_empty');
$display = $view->getDisplay('default');
$this->assertTrue(isset($display['display_options'][$type_info['plural']][$id]), 'Ensure the field was added to the view itself.');
}
/**
* Tests escaping of field labels in help text.
*/
public function testHandlerHelpEscaping() {
// Setup a field with two instances using a different label.
// Ensure that the label is escaped properly.
$this->drupalCreateContentType(['type' => 'article']);
$this->drupalCreateContentType(['type' => 'page']);
FieldStorageConfig::create([
'field_name' => 'field_test',
'entity_type' => 'node',
'type' => 'string',
])->save();
FieldConfig::create([
'field_name' => 'field_test',
'entity_type' => 'node',
'bundle' => 'page',
'label' => 'The giraffe" label'
])->save();
FieldConfig::create([
'field_name' => 'field_test',
'entity_type' => 'node',
'bundle' => 'article',
'label' => 'The <em>giraffe"</em> label <script>alert("the return of the xss")</script>'
])->save();
$this->drupalGet('admin/structure/views/nojs/add-handler/content/default/field');
$this->assertEscaped('The <em>giraffe"</em> label <script>alert("the return of the xss")</script>');
$this->assertEscaped('Appears in: page, article. Also known as: Content: The giraffe" label');
}
/**
* Tests broken handlers.
*/
public function testBrokenHandlers() {
$handler_types = ViewExecutable::getHandlerTypes();
foreach ($handler_types as $type => $type_info) {
$this->drupalGet('admin/structure/views/view/test_view_broken/edit');
$href = "admin/structure/views/nojs/handler/test_view_broken/default/$type/id_broken";
$result = $this->xpath('//a[contains(@href, :href)]', [':href' => $href]);
$this->assertEqual(count($result), 1, SafeMarkup::format('Handler (%type) edit link found.', ['%type' => $type]));
$text = 'Broken/missing handler';
$this->assertIdentical((string) $result[0], $text, 'Ensure the broken handler text was found.');
$this->drupalGet($href);
$result = $this->xpath('//h1[@class="page-title"]');
$this->assertTrue(strpos((string) $result[0], $text) !== FALSE, 'Ensure the broken handler text was found.');
$original_configuration = [
'field' => 'id_broken',
'id' => 'id_broken',
'relationship' => 'none',
'table' => 'views_test_data',
'plugin_id' => 'numeric',
];
foreach ($original_configuration as $key => $value) {
$this->assertText(SafeMarkup::format('@key: @value', ['@key' => $key, '@value' => $value]));
}
}
}
/**
* Ensures that neither node type or node ID appears multiple times.
*
* @see \Drupal\views\EntityViewsData
*/
public function testNoDuplicateFields() {
$handler_types = ['field', 'filter', 'sort', 'argument'];
foreach ($handler_types as $handler_type) {
$add_handler_url = 'admin/structure/views/nojs/add-handler/test_node_view/default/' . $handler_type;
$this->drupalGet($add_handler_url);
$this->assertNoDuplicateField('ID', 'Content');
$this->assertNoDuplicateField('ID', 'Content revision');
$this->assertNoDuplicateField('Content type', 'Content');
$this->assertNoDuplicateField('UUID', 'Content');
$this->assertNoDuplicateField('Revision ID', 'Content');
$this->assertNoDuplicateField('Revision ID', 'Content revision');
}
}
/**
* Ensures that no missing help text is shown.
*
* @see \Drupal\views\EntityViewsData
*/
public function testErrorMissingHelp() {
// Test that the error message is not shown for entity fields but an empty
// description field is shown instead.
$this->drupalGet('admin/structure/views/nojs/add-handler/test_node_view/default/field');
$this->assertNoText('Error: missing help');
$this->assertRaw('<td class="description"></td>', 'Empty description found');
// Test that no error message is shown for other fields.
$this->drupalGet('admin/structure/views/nojs/add-handler/test_view_empty/default/field');
$this->assertNoText('Error: missing help');
}
/**
* Asserts that fields only appear once.
*
* @param string $field_name
* The field name.
* @param string $entity_type
* The entity type to which the field belongs.
*/
public function assertNoDuplicateField($field_name, $entity_type) {
$elements = $this->xpath('//td[.=:entity_type]/preceding-sibling::td[@class="title" and .=:title]', [':title' => $field_name, ':entity_type' => $entity_type]);
$this->assertEqual(1, count($elements), $field_name . ' appears just once in ' . $entity_type . '.');
}
}

View file

@ -1,51 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests configuration schema against new views.
*
* @group views_ui
*/
class NewViewConfigSchemaTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['views_ui', 'node', 'comment', 'file', 'taxonomy', 'dblog', 'aggregator'];
/**
* Tests creating brand new views.
*/
public function testNewViews() {
$this->drupalLogin($this->drupalCreateUser(['administer views']));
// Create views with all core Views wizards.
$wizards = [
// Wizard with their own classes.
'node',
'node_revision',
'users',
'comment',
'file_managed',
'taxonomy_term',
'watchdog',
// Standard derivative classes.
'standard:aggregator_feed',
'standard:aggregator_item',
];
foreach ($wizards as $wizard_key) {
$edit = [];
$edit['label'] = $this->randomString();
$edit['id'] = strtolower($this->randomMachineName());
$edit['show[wizard_key]'] = $wizard_key;
$edit['description'] = $this->randomString();
$this->drupalPostForm('admin/structure/views/add', $edit, t('Save and edit'));
}
}
}

View file

@ -1,199 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests that displays can be correctly overridden via the user interface.
*
* @group views_ui
*/
class OverrideDisplaysTest extends UITestBase {
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('page_title_block');
}
/**
* Tests that displays can be overridden via the UI.
*/
public function testOverrideDisplays() {
// Create a basic view that shows all content, with a page and a block
// display.
$view['label'] = $this->randomMachineName(16);
$view['id'] = strtolower($this->randomMachineName(16));
$view['page[create]'] = 1;
$view['page[path]'] = $this->randomMachineName(16);
$view['block[create]'] = 1;
$view_path = $view['page[path]'];
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
// Configure its title. Since the page and block both started off with the
// same (empty) title in the views wizard, we expect the wizard to have set
// things up so that they both inherit from the default display, and we
// therefore only need to change that to have it take effect for both.
$edit = [];
$edit['title'] = $original_title = $this->randomMachineName(16);
$edit['override[dropdown]'] = 'default';
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/page_1/title", $edit, t('Apply'));
$this->drupalPostForm("admin/structure/views/view/{$view['id']}/edit/page_1", [], t('Save'));
// Add a node that will appear in the view, so that the block will actually
// be displayed.
$this->drupalCreateContentType(['type' => 'page']);
$this->drupalCreateNode();
// Make sure the title appears in the page.
$this->drupalGet($view_path);
$this->assertResponse(200);
$this->assertText($original_title);
// Confirm that the view block is available in the block administration UI.
$this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default'));
$this->clickLinkPartialName('Place block');
$this->assertText($view['label']);
// Place the block.
$this->drupalPlaceBlock("views_block:{$view['id']}-block_1");
// Make sure the title appears in the block.
$this->drupalGet('');
$this->assertText($original_title);
// Change the title for the page display only, and make sure that the
// original title still appears on the page.
$edit = [];
$edit['title'] = $new_title = $this->randomMachineName(16);
$edit['override[dropdown]'] = 'page_1';
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/page_1/title", $edit, t('Apply'));
$this->drupalPostForm("admin/structure/views/view/{$view['id']}/edit/page_1", [], t('Save'));
$this->drupalGet($view_path);
$this->assertResponse(200);
$this->assertText($new_title);
$this->assertText($original_title);
}
/**
* Tests that the wizard correctly sets up default and overridden displays.
*/
public function testWizardMixedDefaultOverriddenDisplays() {
// Create a basic view with a page, block, and feed. Give the page and feed
// identical titles, but give the block a different one, so we expect the
// page and feed to inherit their titles from the default display, but the
// block to override it.
$view['label'] = $this->randomMachineName(16);
$view['id'] = strtolower($this->randomMachineName(16));
$view['page[create]'] = 1;
$view['page[title]'] = $this->randomMachineName(16);
$view['page[path]'] = $this->randomMachineName(16);
$view['page[feed]'] = 1;
$view['page[feed_properties][path]'] = $this->randomMachineName(16);
$view['block[create]'] = 1;
$view['block[title]'] = $this->randomMachineName(16);
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
// Add a node that will appear in the view, so that the block will actually
// be displayed.
$this->drupalCreateContentType(['type' => 'page']);
$this->drupalCreateNode();
// Make sure that the feed, page and block all start off with the correct
// titles.
$this->drupalGet($view['page[path]']);
$this->assertResponse(200);
$this->assertText($view['page[title]']);
$this->assertNoText($view['block[title]']);
$this->drupalGet($view['page[feed_properties][path]']);
$this->assertResponse(200);
$this->assertText($view['page[title]']);
$this->assertNoText($view['block[title]']);
// Confirm that the block is available in the block administration UI.
$this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default'));
$this->clickLinkPartialName('Place block');
$this->assertText($view['label']);
// Put the block into the first sidebar region, and make sure it will not
// display on the view's page display (since we will be searching for the
// presence/absence of the view's title in both the page and the block).
$this->drupalPlaceBlock("views_block:{$view['id']}-block_1", [
'visibility' => [
'request_path' => [
'pages' => '/' . $view['page[path]'],
'negate' => TRUE,
],
],
]);
$this->drupalGet('');
$this->assertText($view['block[title]']);
$this->assertNoText($view['page[title]']);
// Edit the page and change the title. This should automatically change
// the feed's title also, but not the block.
$edit = [];
$edit['title'] = $new_default_title = $this->randomMachineName(16);
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/page_1/title", $edit, t('Apply'));
$this->drupalPostForm("admin/structure/views/view/{$view['id']}/edit/page_1", [], t('Save'));
$this->drupalGet($view['page[path]']);
$this->assertResponse(200);
$this->assertText($new_default_title);
$this->assertNoText($view['page[title]']);
$this->assertNoText($view['block[title]']);
$this->drupalGet($view['page[feed_properties][path]']);
$this->assertResponse(200);
$this->assertText($new_default_title);
$this->assertNoText($view['page[title]']);
$this->assertNoText($view['block[title]']);
$this->drupalGet('');
$this->assertNoText($new_default_title);
$this->assertNoText($view['page[title]']);
$this->assertText($view['block[title]']);
// Edit the block and change the title. This should automatically change
// the block title only, and leave the defaults alone.
$edit = [];
$edit['title'] = $new_block_title = $this->randomMachineName(16);
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/block_1/title", $edit, t('Apply'));
$this->drupalPostForm("admin/structure/views/view/{$view['id']}/edit/block_1", [], t('Save'));
$this->drupalGet($view['page[path]']);
$this->assertResponse(200);
$this->assertText($new_default_title);
$this->drupalGet($view['page[feed_properties][path]']);
$this->assertResponse(200);
$this->assertText($new_default_title);
$this->assertNoText($new_block_title);
$this->drupalGet('');
$this->assertText($new_block_title);
$this->assertNoText($view['block[title]']);
}
/**
* Tests that the revert to all displays select-option works as expected.
*/
public function testRevertAllDisplays() {
// Create a basic view with a page, block.
// Because there is both a title on page and block we expect the title on
// the block be overridden.
$view['label'] = $this->randomMachineName(16);
$view['id'] = strtolower($this->randomMachineName(16));
$view['page[create]'] = 1;
$view['page[title]'] = $this->randomMachineName(16);
$view['page[path]'] = $this->randomMachineName(16);
$view['block[create]'] = 1;
$view['block[title]'] = $this->randomMachineName(16);
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
// Revert the title of the block to the default ones, but submit some new
// values to be sure that the new value is not stored.
$edit = [];
$edit['title'] = $new_block_title = $this->randomMachineName();
$edit['override[dropdown]'] = 'default_revert';
$this->drupalPostForm("admin/structure/views/nojs/display/{$view['id']}/block_1/title", $edit, t('Apply'));
$this->drupalPostForm("admin/structure/views/view/{$view['id']}/edit/block_1", [], t('Save'));
$this->assertText($view['page[title]']);
}
}

View file

@ -105,7 +105,13 @@ class PreviewTest extends UITestBase {
$this->assertText(t('Query execute time'));
$this->assertText(t('View render time'));
$this->assertRaw('<strong>Query</strong>');
$this->assertText("SELECT views_test_data.name AS views_test_data_name\nFROM \n{views_test_data} views_test_data\nWHERE (views_test_data.id = &#039;100&#039; )");
$query_string = <<<SQL
SELECT views_test_data.name AS views_test_data_name
FROM
{views_test_data} views_test_data
WHERE (views_test_data.id = '100')
SQL;
$this->assertEscaped($query_string);
// Test that the statistics and query are rendered above the preview.
$this->assertTrue(strpos($this->getRawContent(), 'views-query-info') < strpos($this->getRawContent(), 'view-test-preview'), 'Statistics shown above the preview.');
@ -114,6 +120,12 @@ class PreviewTest extends UITestBase {
$settings->set('ui.show.sql_query.where', 'below')->save();
$this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview'));
$this->assertTrue(strpos($this->getRawContent(), 'view-test-preview') < strpos($this->getRawContent(), 'views-query-info'), 'Statistics shown below the preview.');
// Test that the preview title isn't double escaped.
$this->drupalPostForm("admin/structure/views/nojs/display/test_preview/default/title", $edit = ['title' => 'Double & escaped'], t('Apply'));
$this->drupalPostForm(NULL, [], t('Update preview'));
$elements = $this->xpath('//div[@id="views-live-preview"]/div[contains(@class, views-query-info)]//td[text()=:text]', [':text' => t('Double & escaped')]);
$this->assertEqual(1, count($elements));
}
/**

View file

@ -1,54 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Views;
use Drupal\views\Entity\View;
/**
* Tests query plugins.
*
* @group views_ui
*/
class QueryTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* {@inheritdoc}
*/
protected function viewsData() {
$data = parent::viewsData();
$data['views_test_data']['table']['base']['query_id'] = 'query_test';
return $data;
}
/**
* Tests query plugins settings.
*/
public function testQueryUI() {
$view = View::load('test_view');
$display = &$view->getDisplay('default');
$display['display_options']['query'] = ['type' => 'query_test'];
$view->save();
// Save some query settings.
$query_settings_path = "admin/structure/views/nojs/display/test_view/default/query";
$random_value = $this->randomMachineName();
$this->drupalPostForm($query_settings_path, ['query[options][test_setting]' => $random_value], t('Apply'));
$this->drupalPostForm(NULL, [], t('Save'));
// Check that the settings are saved into the view itself.
$view = Views::getView('test_view');
$view->initDisplay();
$view->initQuery();
$this->assertEqual($random_value, $view->query->options['test_setting'], 'Query settings got saved');
}
}

View file

@ -1,78 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Views;
/**
* Tests the reordering of fields via AJAX.
*
* @group views_ui
* @see \Drupal\views_ui\Form\Ajax\Rearrange
*/
class RearrangeFieldsTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Gets the fields from the View.
*/
protected function getViewFields($view_name = 'test_view', $display_id = 'default') {
$view = Views::getView($view_name);
$view->setDisplay($display_id);
$fields = [];
foreach ($view->displayHandlers->get('default')->getHandlers('field') as $field => $handler) {
$fields[] = $field;
}
return $fields;
}
/**
* Check if the fields are in the correct order.
*
* @param $view_name
* The name of the view.
* @param $fields
* Array of field names.
*/
protected function assertFieldOrder($view_name, $fields) {
$this->drupalGet('admin/structure/views/nojs/rearrange/' . $view_name . '/default/field');
foreach ($fields as $idx => $field) {
$this->assertFieldById('edit-fields-' . $field . '-weight', $idx + 1);
}
}
/**
* Tests field sorting.
*/
public function testRearrangeFields() {
$view_name = 'test_view';
// Checks that the order on the rearrange form matches the creation order.
$this->assertFieldOrder($view_name, $this->getViewFields($view_name));
// Checks that a field is not deleted if a value is not passed back.
$fields = [];
$this->drupalPostForm('admin/structure/views/nojs/rearrange/' . $view_name . '/default/field', $fields, t('Apply'));
$this->assertFieldOrder($view_name, $this->getViewFields($view_name));
// Checks that revers the new field order is respected.
$reversedFields = array_reverse($this->getViewFields($view_name));
$fields = [];
foreach ($reversedFields as $delta => $field) {
$fields['fields[' . $field . '][weight]'] = $delta;
}
$this->drupalPostForm('admin/structure/views/nojs/rearrange/' . $view_name . '/default/field', $fields, t('Apply'));
$this->assertFieldOrder($view_name, $reversedFields);
// Checks that there is a remove link for each field.
$this->assertEqual(count($this->cssSelect('a.views-remove-link')), count($fields));
}
}

View file

@ -1,45 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests the redirecting after saving a views.
*
* @group views_ui
*/
class RedirectTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view', 'test_redirect_view'];
/**
* Tests the redirecting.
*/
public function testRedirect() {
$view_name = 'test_view';
$random_destination = $this->randomMachineName();
$edit_path = "admin/structure/views/view/$view_name/edit";
$this->drupalPostForm($edit_path, [], t('Save'), ['query' => ['destination' => $random_destination]]);
$this->assertUrl($random_destination, [], 'Make sure the user got redirected to the expected page defined in the destination.');
// Setup a view with a certain page display path. If you change the path
// but have the old url in the destination the user should be redirected to
// the new path.
$view_name = 'test_redirect_view';
$new_path = $this->randomMachineName();
$edit_path = "admin/structure/views/view/$view_name/edit";
$path_edit_path = "admin/structure/views/nojs/display/$view_name/page_1/path";
$this->drupalPostForm($path_edit_path, ['path' => $new_path], t('Apply'));
$this->drupalPostForm($edit_path, [], t('Save'), ['query' => ['destination' => 'test-redirect-view']]);
$this->assertUrl($new_path, [], 'Make sure the user got redirected to the expected page after changing the URL of a page display.');
}
}

View file

@ -1,55 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Tests the Views fields report page.
*
* @group views_ui
*/
class ReportFieldsTest extends UITestBase {
/**
* {@inheritdoc}
*/
public static $testViews = ['test_field_field_test'];
/**
* {@inheritdoc}
*/
public static $modules = ['entity_test'];
/**
* Tests the Views fields report page.
*/
public function testReportFields() {
$this->drupalGet('admin/reports/fields/views-fields');
$this->assertRaw('Used in views', 'Title appears correctly');
$this->assertRaw('No fields have been used in views yet.', 'No results message appears correctly.');
// Set up the field_test field.
$field_storage = FieldStorageConfig::create([
'field_name' => 'field_test',
'type' => 'integer',
'entity_type' => 'entity_test',
]);
$field_storage->save();
$field = FieldConfig::create([
'field_name' => 'field_test',
'entity_type' => 'entity_test',
'bundle' => 'entity_test',
]);
$field->save();
$this->drupalGet('admin/reports/fields/views-fields');
// Assert that the newly created field appears in the overview.
$this->assertRaw('<td>field_test</td>', 'Field name appears correctly');
$this->assertRaw('>test_field_field_test</a>', 'View name appears correctly');
$this->assertRaw('Used in views', 'Title appears correctly');
}
}

View file

@ -1,43 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests existence of the views plugin report.
*
* @group views_ui
*/
class ReportTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['views', 'views_ui'];
/**
* Stores an admin user used by the different tests.
*
* @var \Drupal\user\User
*/
protected $adminUser;
protected function setUp() {
parent::setUp();
$this->adminUser = $this->drupalCreateUser(['administer views']);
}
/**
* Tests the existence of the views plugin report.
*/
public function testReport() {
$this->drupalLogin($this->adminUser);
// Test the report page.
$this->drupalGet('admin/reports/views-plugins');
$this->assertResponse(200, "Views report page exists");
}
}

View file

@ -1,95 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\Core\Entity\Entity\EntityViewMode;
use Drupal\views\Views;
/**
* Tests the UI of row plugins.
*
* @group views_ui
* @see \Drupal\views_test_data\Plugin\views\row\RowTest.
*/
class RowUITest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Tests changing the row plugin and changing some options of a row.
*/
public function testRowUI() {
$view_name = 'test_view';
$view_edit_url = "admin/structure/views/view/$view_name/edit";
$row_plugin_url = "admin/structure/views/nojs/display/$view_name/default/row";
$row_options_url = "admin/structure/views/nojs/display/$view_name/default/row_options";
$this->drupalGet($row_plugin_url);
$this->assertFieldByName('row[type]', 'fields', 'The default row plugin selected in the UI should be fields.');
$edit = [
'row[type]' => 'test_row'
];
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertFieldByName('row_options[test_option]', NULL, 'Make sure the custom settings form from the test plugin appears.');
$random_name = $this->randomMachineName();
$edit = [
'row_options[test_option]' => $random_name
];
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalGet($row_options_url);
$this->assertFieldByName('row_options[test_option]', $random_name, 'Make sure the custom settings form field has the expected value stored.');
$this->drupalPostForm($view_edit_url, [], t('Save'));
$this->assertLink(t('Test row plugin'), 0, 'Make sure the test row plugin is shown in the UI');
$view = Views::getView($view_name);
$view->initDisplay();
$row = $view->display_handler->getOption('row');
$this->assertEqual($row['type'], 'test_row', 'Make sure that the test_row got saved as used row plugin.');
$this->assertEqual($row['options']['test_option'], $random_name, 'Make sure that the custom settings field got saved as expected.');
// Change the row plugin to fields using ajax.
// Note: this is the best approximation we can achieve, because we cannot
// simulate the 'openDialog' command in
// WebTestBase::drupalProcessAjaxResponse(), hence we have to make do.
$row_plugin_url_ajax = str_replace('/nojs/', '/ajax/', $row_plugin_url);
$ajax_settings = [
'accepts' => 'application/vnd.drupal-ajax',
'submit' => [
'_triggering_element_name' => 'op',
'_triggering_element_value' => 'Apply',
],
'url' => $row_plugin_url_ajax,
];
$this->drupalPostAjaxForm($row_plugin_url, ['row[type]' => 'fields'], NULL, $row_plugin_url_ajax, [], [], NULL, $ajax_settings);
$this->drupalGet($row_plugin_url);
$this->assertResponse(200);
$this->assertFieldByName('row[type]', 'fields', 'Make sure that the fields got saved as used row plugin.');
// Ensure that entity row plugins appear.
$view_name = 'content';
$row_plugin_url = "admin/structure/views/nojs/display/$view_name/default/row";
$row_options_url = "admin/structure/views/nojs/display/$view_name/default/row_options";
$this->drupalGet($row_plugin_url);
$this->assertFieldByName('row[type]', 'entity:node');
$this->drupalPostForm(NULL, ['row[type]' => 'entity:node'], t('Apply'));
$this->assertUrl($row_options_url);
$this->assertFieldByName('row_options[view_mode]', 'teaser');
// Change the teaser label to have markup so we can test escaping.
$teaser = EntityViewMode::load('node.teaser');
$teaser->set('label', 'Teaser <em>markup</em>');
$teaser->save();
$this->drupalGet('admin/structure/views/view/frontpage/edit/default');
$this->assertEscaped('Teaser <em>markup</em>');
}
}

View file

@ -1,142 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests all ui related settings under admin/structure/views/settings.
*
* @group views_ui
*/
class SettingsTest extends UITestBase {
/**
* Stores an admin user used by the different tests.
*
* @var \Drupal\user\User
*/
protected $adminUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('local_tasks_block');
}
/**
* Tests the settings for the edit ui.
*/
public function testEditUI() {
$this->drupalLogin($this->adminUser);
// Test the settings tab exists.
$this->drupalGet('admin/structure/views');
$this->assertLinkByHref('admin/structure/views/settings');
// Test the confirmation message.
$this->drupalPostForm('admin/structure/views/settings', [], t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'));
// Configure to always show the master display.
$edit = [
'ui_show_master_display' => TRUE,
];
$this->drupalPostForm('admin/structure/views/settings', $edit, t('Save configuration'));
$view = [];
$view['label'] = $this->randomMachineName(16);
$view['id'] = strtolower($this->randomMachineName(16));
$view['description'] = $this->randomMachineName(16);
$view['page[create]'] = TRUE;
$view['page[title]'] = $this->randomMachineName(16);
$view['page[path]'] = $this->randomMachineName(16);
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
// Configure to not always show the master display.
// If you have a view without a page or block the master display should be
// still shown.
$edit = [
'ui_show_master_display' => FALSE,
];
$this->drupalPostForm('admin/structure/views/settings', $edit, t('Save configuration'));
$view['page[create]'] = FALSE;
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
// Create a view with an additional display, so master should be hidden.
$view['page[create]'] = TRUE;
$view['id'] = strtolower($this->randomMachineName());
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$this->assertNoLink(t('Master'));
// Configure to always show the advanced settings.
// @todo It doesn't seem to be a way to test this as this works just on js.
// Configure to show the embeddable display.
$edit = [
'ui_show_display_embed' => TRUE,
];
$this->drupalPostForm('admin/structure/views/settings', $edit, t('Save configuration'));
$view['id'] = strtolower($this->randomMachineName());
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$this->assertFieldById('edit-displays-top-add-display-embed');
$edit = [
'ui_show_display_embed' => FALSE,
];
$this->drupalPostForm('admin/structure/views/settings', $edit, t('Save configuration'));
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$this->assertNoFieldById('edit-displays-top-add-display-embed');
// Configure to hide/show the sql at the preview.
$edit = [
'ui_show_sql_query_enabled' => FALSE,
];
$this->drupalPostForm('admin/structure/views/settings', $edit, t('Save configuration'));
$view['id'] = strtolower($this->randomMachineName());
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$this->drupalPostForm(NULL, [], t('Update preview'));
$xpath = $this->xpath('//div[@class="views-query-info"]/pre');
$this->assertEqual(count($xpath), 0, 'The views sql is hidden.');
$edit = [
'ui_show_sql_query_enabled' => TRUE,
];
$this->drupalPostForm('admin/structure/views/settings', $edit, t('Save configuration'));
$view['id'] = strtolower($this->randomMachineName());
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$this->drupalPostForm(NULL, [], t('Update preview'));
$xpath = $this->xpath('//div[@class="views-query-info"]//pre');
$this->assertEqual(count($xpath), 1, 'The views sql is shown.');
$this->assertFalse(strpos($xpath[0], 'db_condition_placeholder') !== FALSE, 'No placeholders are shown in the views sql.');
$this->assertTrue(strpos($xpath[0], "node_field_data.status = '1'") !== FALSE, 'The placeholders in the views sql is replace by the actual value.');
// Test the advanced settings form.
// Test the confirmation message.
$this->drupalPostForm('admin/structure/views/settings/advanced', [], t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'));
$edit = [
'skip_cache' => TRUE,
'sql_signature' => TRUE,
];
$this->drupalPostForm('admin/structure/views/settings/advanced', $edit, t('Save configuration'));
$this->assertFieldChecked('edit-skip-cache', 'The skip_cache option is checked.');
$this->assertFieldChecked('edit-sql-signature', 'The sql_signature option is checked.');
// Test the "Clear Views' cache" button.
$this->drupalPostForm('admin/structure/views/settings/advanced', [], t("Clear Views' cache"));
$this->assertText(t('The cache has been cleared.'));
}
}

View file

@ -1,56 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\views\Views;
/**
* Tests the UI of storage properties of views.
*
* @group views_ui
*/
class StorageTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['views_ui', 'language'];
/**
* Tests changing label, description and tag.
*
* @see views_ui_edit_details_form
*/
public function testDetails() {
$view_name = 'test_view';
ConfigurableLanguage::createFromLangcode('fr')->save();
$edit = [
'label' => $this->randomMachineName(),
'tag' => $this->randomMachineName(),
'description' => $this->randomMachineName(30),
'langcode' => 'fr',
];
$this->drupalPostForm("admin/structure/views/nojs/edit-details/$view_name/default", $edit, t('Apply'));
$this->drupalPostForm(NULL, [], t('Save'));
$view = Views::getView($view_name);
foreach (['label', 'tag', 'description', 'langcode'] as $property) {
$this->assertEqual($view->storage->get($property), $edit[$property], format_string('Make sure the property @property got probably saved.', ['@property' => $property]));
}
}
}

View file

@ -1,35 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Views;
/**
* Tests the UI of views when using the table style.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\style\Table.
*/
class StyleTableTest extends UITestBase {
/**
* Tests created a table style view.
*/
public function testWizard() {
// Create a new view and check that the first field has a label.
$view = [];
$view['label'] = $this->randomMachineName(16);
$view['id'] = strtolower($this->randomMachineName(16));
$view['show[wizard_key]'] = 'node';
$view['page[create]'] = TRUE;
$view['page[style][style_plugin]'] = 'table';
$view['page[title]'] = $this->randomMachineName(16);
$view['page[path]'] = $view['id'];
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$view = Views::getView($view['id']);
$view->initHandlers();
$this->assertEqual($view->field['title']->options['label'], 'Title', 'The field label for table styles is not empty.');
}
}

View file

@ -1,65 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Views;
/**
* Tests the UI of style plugins.
*
* @group views_ui
* @see \Drupal\views_test_data\Plugin\views\style\StyleTest.
*/
class StyleUITest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view'];
/**
* Tests changing the style plugin and changing some options of a style.
*/
public function testStyleUI() {
$view_name = 'test_view';
$view_edit_url = "admin/structure/views/view/$view_name/edit";
$style_plugin_url = "admin/structure/views/nojs/display/$view_name/default/style";
$style_options_url = "admin/structure/views/nojs/display/$view_name/default/style_options";
$this->drupalGet($style_plugin_url);
$this->assertFieldByName('style[type]', 'default', 'The default style plugin selected in the UI should be unformatted list.');
$edit = [
'style[type]' => 'test_style'
];
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->assertFieldByName('style_options[test_option]', NULL, 'Make sure the custom settings form from the test plugin appears.');
$random_name = $this->randomMachineName();
$edit = [
'style_options[test_option]' => $random_name
];
$this->drupalPostForm(NULL, $edit, t('Apply'));
$this->drupalGet($style_options_url);
$this->assertFieldByName('style_options[test_option]', $random_name, 'Make sure the custom settings form field has the expected value stored.');
$this->drupalPostForm($view_edit_url, [], t('Save'));
$this->assertLink(t('Test style plugin'), 0, 'Make sure the test style plugin is shown in the UI');
$view = Views::getView($view_name);
$view->initDisplay();
$style = $view->display_handler->getOption('style');
$this->assertEqual($style['type'], 'test_style', 'Make sure that the test_style got saved as used style plugin.');
$this->assertEqual($style['options']['test_option'], $random_name, 'Make sure that the custom settings field got saved as expected.');
// Test that fields are working correctly in the UI for style plugins when
// a field row plugin is selected.
$this->drupalPostForm("admin/structure/views/view/$view_name/edit", [], 'Add Page');
$this->drupalPostForm("admin/structure/views/nojs/display/$view_name/page_1/row", ['row[type]' => 'fields'], t('Apply'));
// If fields are being used this text will not be shown.
$this->assertNoText(t('The selected style or row format does not use fields.'));
}
}

View file

@ -1,45 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\views\Entity\View;
/**
* Tests the token display for the TokenizeAreaPluginBase UI.
*
* @see \Drupal\views\Plugin\views\area\Entity
* @group views_ui
*/
class TokenizeAreaUITest extends UITestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['entity_test'];
/**
* Test that the right tokens are shown as available for replacement.
*/
public function testTokenUI() {
$entity_test = EntityTest::create(['bundle' => 'entity_test']);
$entity_test->save();
$default = $this->randomView([]);
$id = $default['id'];
$view = View::load($id);
$this->drupalGet($view->toUrl('edit-form'));
// Add a global NULL argument to the view for testing argument tokens.
$this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/argument", ['name[views.null]' => 1], 'Add and configure contextual filters');
$this->drupalPostForm(NULL, [], 'Apply');
$this->drupalPostForm("admin/structure/views/nojs/add-handler/$id/page_1/header", ['name[views.area]' => 'views.area'], 'Add and configure header');
// Test that field tokens are shown.
$this->assertText('{{ title }} == Content: Title');
// Test that argument tokens are shown.
$this->assertText('{{ arguments.null }} == Global: Null title');
}
}

View file

@ -1,84 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\WebTestBase;
/**
* Tests that translated strings in views UI don't override original strings.
*
* @group views_ui
*/
class TranslatedViewTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'config_translation',
'views_ui',
];
/**
* Languages to enable.
*
* @var array
*/
protected $langcodes = [
'fr',
];
/**
* Administrator user for tests.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
protected function setUp() {
parent::setUp();
$permissions = [
'administer site configuration',
'administer views',
'translate configuration',
'translate interface',
];
// Create and log in user.
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
// Add languages.
foreach ($this->langcodes as $langcode) {
ConfigurableLanguage::createFromLangcode($langcode)->save();
}
$this->resetAll();
$this->rebuildContainer();
}
public function testTranslatedStrings() {
$translation_url = 'admin/structure/views/view/files/translate/fr/add';
$edit_url = 'admin/structure/views/view/files';
// Check origial string.
$this->drupalGet($edit_url);
$this->assertTitle('Files (File) | Drupal');
// Translate the label of the view.
$this->drupalGet($translation_url);
$edit = [
'translation[config_names][views.view.files][label]' => 'Fichiers',
];
$this->drupalPostForm(NULL, $edit, t('Save translation'));
// Check if the label is translated.
$this->drupalGet($edit_url, ['language' => \Drupal::languageManager()->getLanguage('fr')]);
$this->assertTitle('Files (File) | Drupal');
$this->assertNoText('Fichiers');
}
}

View file

@ -6,6 +6,9 @@ use Drupal\views\Tests\ViewTestBase;
/**
* Provides a base class for testing the Views UI.
*
* @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.x.
* Use \Drupal\Tests\views_ui\Functional\UITestBase.
*/
abstract class UITestBase extends ViewTestBase {
@ -33,8 +36,8 @@ abstract class UITestBase extends ViewTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->enableViewsTestModule();
@ -48,6 +51,8 @@ abstract class UITestBase extends ViewTestBase {
'administer permissions',
]);
$this->drupalLogin($this->fullAdminUser);
@trigger_error('\Drupal\views_ui\Tests\UITestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.x. Instead, use \Drupal\Tests\views_ui\Functional\UITestBase', E_USER_DEPRECATED);
}
/**

View file

@ -1,79 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Tests\ViewTestBase;
/**
* Tests covering Preview of unsaved Views.
*
* @group views_ui
*/
class UnsavedPreviewTest extends ViewTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['content'];
/**
* An admin user with the 'administer views' permission.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* {@inheritdoc}
*/
public static $modules = ['node', 'views_ui'];
/**
* Sets up a Drupal site for running functional and integration tests.
*/
protected function setUp() {
parent::setUp(FALSE);
$this->adminUser = $this->drupalCreateUser(['administer views']);
$this->drupalLogin($this->adminUser);
}
/**
* Tests previews of unsaved new page displays.
*/
public function testUnsavedPageDisplayPreview() {
$this->drupalCreateContentType(['type' => 'page']);
for ($i = 0; $i < 5; $i++) {
$this->drupalCreateNode();
}
$this->drupalGet('admin/structure/views/view/content');
$this->assertResponse(200);
$this->drupalPostForm(NULL, [], t('Add Page'));
$this->assertResponse(200);
$this->drupalGet('admin/structure/views/nojs/display/content/page_2/path');
$this->assertResponse(200);
$this->drupalPostForm(NULL, ['path' => 'foobarbaz'], t('Apply'));
$this->assertResponse(200);
$this->drupalPostForm(NULL, [], t('Update preview'));
$this->assertResponse(200);
$this->assertText(t('This display has no path'));
$this->drupalGet('admin/structure/views/view/content/edit/page_2');
$this->assertResponse(200);
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertResponse(200);
$this->drupalPostForm(NULL, [], t('Update preview'));
$this->assertResponse(200);
$this->assertLinkByHref('foobarbaz');
}
}

View file

@ -1,236 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\views\Entity\View;
/**
* Tests some general functionality of editing views, like deleting a view.
*
* @group views_ui
*/
class ViewEditTest extends UITestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_view', 'test_display', 'test_groupwise_term_ui'];
/**
* Tests the delete link on a views UI.
*/
public function testDeleteLink() {
$this->drupalGet('admin/structure/views/view/test_view');
$this->assertLink(t('Delete view'), 0, 'Ensure that the view delete link appears');
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_view');
$this->assertTrue($view instanceof View);
$this->clickLink(t('Delete view'));
$this->assertUrl('admin/structure/views/view/test_view/delete');
$this->drupalPostForm(NULL, [], t('Delete'));
$this->assertRaw(t('The view %name has been deleted.', ['%name' => $view->label()]));
$this->assertUrl('admin/structure/views');
$view = $this->container->get('entity.manager')->getStorage('view')->load('test_view');
$this->assertFalse($view instanceof View);
}
/**
* Tests the machine name and administrative comment forms.
*/
public function testOtherOptions() {
$this->drupalGet('admin/structure/views/view/test_view');
// Add a new attachment display.
$this->drupalPostForm(NULL, [], 'Add Attachment');
// Test that a long administrative comment is truncated.
$edit = ['display_comment' => 'one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen'];
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/attachment_1/display_comment', $edit, 'Apply');
$this->assertText('one two three four five six seven eight nine ten eleven twelve thirteen fourteen...');
// Change the machine name for the display from page_1 to test_1.
$edit = ['display_id' => 'test_1'];
$this->drupalPostForm('admin/structure/views/nojs/display/test_view/attachment_1/display_id', $edit, 'Apply');
$this->assertLink(t('test_1'));
// Save the view, and test the new ID has been saved.
$this->drupalPostForm(NULL, [], 'Save');
$view = \Drupal::entityManager()->getStorage('view')->load('test_view');
$displays = $view->get('display');
$this->assertTrue(!empty($displays['test_1']), 'Display data found for new display ID key.');
$this->assertIdentical($displays['test_1']['id'], 'test_1', 'New display ID matches the display ID key.');
$this->assertFalse(array_key_exists('attachment_1', $displays), 'Old display ID not found.');
// Test the form validation with invalid IDs.
$machine_name_edit_url = 'admin/structure/views/nojs/display/test_view/test_1/display_id';
$error_text = t('Display name must be letters, numbers, or underscores only.');
// Test that potential invalid display ID requests are detected
$this->drupalGet('admin/structure/views/ajax/handler/test_view/fake_display_name/filter/title');
$this->assertText('Invalid display id fake_display_name');
$edit = ['display_id' => 'test 1'];
$this->drupalPostForm($machine_name_edit_url, $edit, 'Apply');
$this->assertText($error_text);
$edit = ['display_id' => 'test_1#'];
$this->drupalPostForm($machine_name_edit_url, $edit, 'Apply');
$this->assertText($error_text);
// Test using an existing display ID.
$edit = ['display_id' => 'default'];
$this->drupalPostForm($machine_name_edit_url, $edit, 'Apply');
$this->assertText(t('Display id should be unique.'));
// Test that the display ID has not been changed.
$this->drupalGet('admin/structure/views/view/test_view/edit/test_1');
$this->assertLink(t('test_1'));
// Test that validation does not run on cancel.
$this->drupalGet('admin/structure/views/view/test_view');
// Delete the field to cause an error on save.
$fields = [];
$fields['fields[age][removed]'] = 1;
$fields['fields[id][removed]'] = 1;
$fields['fields[name][removed]'] = 1;
$this->drupalPostForm('admin/structure/views/nojs/rearrange/test_view/default/field', $fields, t('Apply'));
$this->drupalPostForm(NULL, [], 'Save');
$this->drupalPostForm(NULL, [], t('Cancel'));
$this->assertNoFieldByXpath('//div[contains(@class, "error")]', FALSE, 'No error message is displayed.');
$this->assertUrl('admin/structure/views', [], 'Redirected back to the view listing page..');
}
/**
* Tests the language options on the views edit form.
*/
public function testEditFormLanguageOptions() {
// Language options should not exist without language module.
$test_views = [
'test_view' => 'default',
'test_display' => 'page_1',
];
foreach ($test_views as $view_name => $display) {
$this->drupalGet('admin/structure/views/view/' . $view_name);
$this->assertResponse(200);
$langcode_url = 'admin/structure/views/nojs/display/' . $view_name . '/' . $display . '/rendering_language';
$this->assertNoLinkByHref($langcode_url);
$this->assertNoLink(t('@type language selected for page', ['@type' => t('Content')]));
$this->assertNoLink(t('Content language of view row'));
}
// Make the site multilingual and test the options again.
$this->container->get('module_installer')->install(['language', 'content_translation']);
ConfigurableLanguage::createFromLangcode('hu')->save();
$this->resetAll();
$this->rebuildContainer();
// Language options should now exist with entity language the default.
foreach ($test_views as $view_name => $display) {
$this->drupalGet('admin/structure/views/view/' . $view_name);
$this->assertResponse(200);
$langcode_url = 'admin/structure/views/nojs/display/' . $view_name . '/' . $display . '/rendering_language';
if ($view_name == 'test_view') {
$this->assertNoLinkByHref($langcode_url);
$this->assertNoLink(t('@type language selected for page', ['@type' => t('Content')]));
$this->assertNoLink(t('Content language of view row'));
}
else {
$this->assertLinkByHref($langcode_url);
$this->assertNoLink(t('@type language selected for page', ['@type' => t('Content')]));
$this->assertLink(t('Content language of view row'));
}
$this->drupalGet($langcode_url);
$this->assertResponse(200);
if ($view_name == 'test_view') {
$this->assertText(t('The view is not based on a translatable entity type or the site is not multilingual.'));
}
else {
$this->assertFieldByName('rendering_language', '***LANGUAGE_entity_translation***');
// Test that the order of the language list is similar to other language
// lists, such as in the content translation settings.
$expected_elements = [
'***LANGUAGE_entity_translation***',
'***LANGUAGE_entity_default***',
'***LANGUAGE_site_default***',
'***LANGUAGE_language_interface***',
'en',
'hu',
];
$elements = $this->xpath('//select[@id="edit-rendering-language"]/option');
// Compare values inside the option elements with expected values.
for ($i = 0; $i < count($elements); $i++) {
$this->assertEqual($elements[$i]->attributes()->{'value'}, $expected_elements[$i]);
}
// Check that the selected values are respected even we they are not
// supposed to be listed.
// Give permission to edit languages to authenticated users.
$edit = [
'authenticated[administer languages]' => TRUE,
];
$this->drupalPostForm('/admin/people/permissions', $edit, t('Save permissions'));
// Enable Content language negotiation so we have one more item
// to select.
$edit = [
'language_content[configurable]' => TRUE,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Choose the new negotiation as the rendering language.
$edit = [
'rendering_language' => '***LANGUAGE_language_content***',
];
$this->drupalPostForm('/admin/structure/views/nojs/display/' . $view_name . '/' . $display . '/rendering_language', $edit, t('Apply'));
// Disable language content negotiation.
$edit = [
'language_content[configurable]' => FALSE,
];
$this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
// Check that the previous selection is listed and selected.
$this->drupalGet($langcode_url);
$element = $this->xpath('//select[@id="edit-rendering-language"]/option[@value="***LANGUAGE_language_content***" and @selected="selected"]');
$this->assertFalse(empty($element), 'Current selection is not lost');
// Check the order for the langcode filter.
$langcode_url = 'admin/structure/views/nojs/handler/' . $view_name . '/' . $display . '/filter/langcode';
$this->drupalGet($langcode_url);
$this->assertResponse(200);
$expected_elements = [
'all',
'***LANGUAGE_site_default***',
'***LANGUAGE_language_interface***',
'***LANGUAGE_language_content***',
'en',
'hu',
'und',
'zxx',
];
$elements = $this->xpath('//div[@id="edit-options-value"]//input');
// Compare values inside the option elements with expected values.
for ($i = 0; $i < count($elements); $i++) {
$this->assertEqual($elements[$i]->attributes()->{'value'}, $expected_elements[$i]);
}
}
}
}
/**
* Tests Representative Node for a Taxonomy Term.
*/
public function testRelationRepresentativeNode() {
// Populate and submit the form.
$edit["name[taxonomy_term_field_data.tid_representative]"] = TRUE;
$this->drupalPostForm('admin/structure/views/nojs/add-handler/test_groupwise_term_ui/default/relationship', $edit, 'Add and configure relationships');
// Apply changes.
$edit = [];
$this->drupalPostForm('admin/structure/views/nojs/handler/test_groupwise_term_ui/default/relationship/tid_representative', $edit, 'Apply');
}
}

View file

@ -1,69 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\simpletest\WebTestBase;
use Drupal\views\Entity\View;
use Drupal\views\Views;
/**
* Tests the views list.
*
* @group views_ui
*/
class ViewsListTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['block', 'views_ui'];
/**
* A user with permission to administer views.
*
* @var \Drupal\user\Entity\User
*/
protected $adminUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('local_tasks_block');
$this->drupalPlaceBlock('local_actions_block');
$this->adminUser = $this->drupalCreateUser(['administer views']);
$this->drupalLogin($this->adminUser);
}
/**
* Tests that the views list does not use a pager.
*/
public function testViewsListLimit() {
// Check if we can access the main views admin page.
$this->drupalGet('admin/structure/views');
$this->assertResponse(200);
$this->assertLink(t('Add view'));
// Count default views to be subtracted from the limit.
$views = count(Views::getEnabledViews());
// Create multiples views.
$limit = 51;
$values = $this->config('views.view.test_view_storage')->get();
for ($i = 1; $i <= $limit - $views; $i++) {
$values['id'] = 'test_view_storage_new' . $i;
unset($values['uuid']);
$created = View::create($values);
$created->save();
}
$this->drupalGet('admin/structure/views');
// Check that all the rows are listed.
$this->assertEqual(count($this->xpath('//tbody/tr[contains(@class,"views-ui-list-enabled")]')), $limit);
}
}

View file

@ -1,111 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\tour\Tests\TourTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
/**
* Tests the Views UI tour.
*
* @group views_ui
*/
class ViewsUITourTest extends TourTestBase {
/**
* An admin user with administrative permissions for views.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* String translation storage object.
*
* @var \Drupal\locale\StringStorageInterface
*/
protected $localeStorage;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['views_ui', 'tour', 'language', 'locale'];
protected function setUp() {
parent::setUp();
$this->adminUser = $this->drupalCreateUser(['administer views', 'access tour']);
$this->drupalLogin($this->adminUser);
}
/**
* Tests views_ui tour tip availability.
*/
public function testViewsUiTourTips() {
// Create a basic view that shows all content, with a page and a block
// display.
$view['label'] = $this->randomMachineName(16);
$view['id'] = strtolower($this->randomMachineName(16));
$view['page[create]'] = 1;
$view['page[path]'] = $this->randomMachineName(16);
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$this->assertTourTips();
}
/**
* Tests views_ui tour tip availability in a different language.
*/
public function testViewsUiTourTipsTranslated() {
$langcode = 'nl';
// Add a default locale storage for this test.
$this->localeStorage = $this->container->get('locale.storage');
// Add Dutch language programmatically.
ConfigurableLanguage::createFromLangcode($langcode)->save();
// Handler titles that need translations.
$handler_titles = [
'Format',
'Fields',
'Sort criteria',
'Filter criteria',
];
foreach ($handler_titles as $handler_title) {
// Create source string.
$source = $this->localeStorage->createString([
'source' => $handler_title
]);
$source->save();
$this->createTranslation($source, $langcode);
}
// Create a basic view that shows all content, with a page and a block
// display.
$view['label'] = $this->randomMachineName(16);
$view['id'] = strtolower($this->randomMachineName(16));
$view['page[create]'] = 1;
$view['page[path]'] = $this->randomMachineName(16);
// Load the page in dutch.
$this->drupalPostForm(
$langcode . '/admin/structure/views/add',
$view,
t('Save and edit')
);
$this->assertTourTips();
}
/**
* Creates single translation for source string.
*/
public function createTranslation($source, $langcode) {
return $this->localeStorage->createTranslation([
'lid' => $source->lid,
'language' => $langcode,
'translation' => $this->randomMachineName(100),
])->save();
}
}

View file

@ -1,62 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
use Drupal\views\Tests\Wizard\WizardTestBase;
/**
* Tests the wizard.
*
* @group views_ui
* @see \Drupal\views\Plugin\views\display\DisplayPluginBase
* @see \Drupal\views\Plugin\views\display\PathPluginBase
* @see \Drupal\views\Plugin\views\wizard\WizardPluginBase
*/
class WizardTest extends WizardTestBase {
/**
* Tests filling in the wizard with really long strings.
*/
public function testWizardFieldLength() {
$view = [];
$view['label'] = $this->randomMachineName(256);
$view['id'] = strtolower($this->randomMachineName(129));
$view['page[create]'] = TRUE;
$view['page[path]'] = $this->randomMachineName(255);
$view['page[title]'] = $this->randomMachineName(256);
$view['page[feed]'] = TRUE;
$view['page[feed_properties][path]'] = $this->randomMachineName(255);
$view['block[create]'] = TRUE;
$view['block[title]'] = $this->randomMachineName(256);
$view['rest_export[create]'] = TRUE;
$view['rest_export[path]'] = $this->randomMachineName(255);
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$this->assertText('Machine-readable name cannot be longer than 128 characters but is currently 129 characters long.');
$this->assertText('Path cannot be longer than 254 characters but is currently 255 characters long.');
$this->assertText('Page title cannot be longer than 255 characters but is currently 256 characters long.');
$this->assertText('View name cannot be longer than 255 characters but is currently 256 characters long.');
$this->assertText('Feed path cannot be longer than 254 characters but is currently 255 characters long.');
$this->assertText('Block title cannot be longer than 255 characters but is currently 256 characters long.');
$this->assertText('REST export path cannot be longer than 254 characters but is currently 255 characters long.');
$view['label'] = $this->randomMachineName(255);
$view['id'] = strtolower($this->randomMachineName(128));
$view['page[create]'] = TRUE;
$view['page[path]'] = $this->randomMachineName(254);
$view['page[title]'] = $this->randomMachineName(255);
$view['page[feed]'] = TRUE;
$view['page[feed_properties][path]'] = $this->randomMachineName(254);
$view['block[create]'] = TRUE;
$view['block[title]'] = $this->randomMachineName(255);
$view['rest_export[create]'] = TRUE;
$view['rest_export[path]'] = $this->randomMachineName(254);
$this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit'));
$this->assertUrl('admin/structure/views/view/' . $view['id'], [], 'Make sure the view saving was successful and the browser got redirected to the edit page.');
// Assert that the page title is correctly truncated.
$this->assertText(views_ui_truncate($view['page[title]'], 32));
}
}

View file

@ -1,42 +0,0 @@
<?php
namespace Drupal\views_ui\Tests;
/**
* Tests the Xss vulnerability.
*
* @group views_ui
*/
class XssTest extends UITestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'user', 'views_ui', 'views_ui_test'];
public function testViewsUi() {
$this->drupalGet('admin/structure/views/view/sa_contrib_2013_035');
$this->assertEscaped('<marquee>test</marquee>', 'Field admin label is properly escaped.');
$this->drupalGet('admin/structure/views/nojs/handler/sa_contrib_2013_035/page_1/header/area');
$this->assertEscaped('{{ title }} == <marquee>test</marquee>', 'Token label is properly escaped.');
$this->assertEscaped('{{ title_1 }} == <script>alert("XSS")</script>', 'Token label is properly escaped.');
}
/**
* Checks the admin UI for double escaping.
*/
public function testNoDoubleEscaping() {
$this->drupalGet('admin/structure/views');
$this->assertNoEscaped('&lt;');
$this->drupalGet('admin/structure/views/view/sa_contrib_2013_035');
$this->assertNoEscaped('&lt;');
$this->drupalGet('admin/structure/views/nojs/handler/sa_contrib_2013_035/page_1/header/area');
$this->assertNoEscaped('&lt;');
}
}

View file

@ -10,6 +10,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Form controller for the Views edit form.
*
* @internal
*/
class ViewAddForm extends ViewFormBase {
@ -182,12 +184,12 @@ class ViewAddForm extends ViewFormBase {
}
// @todo Figure out whether it really makes sense to throw and catch exceptions on the wizard.
catch (WizardException $e) {
drupal_set_message($e->getMessage(), 'error');
$this->messenger()->addError($e->getMessage());
$form_state->setRedirect('entity.view.collection');
return;
}
$this->entity->save();
drupal_set_message($this->t('The view %name has been saved.', ['%name' => $form_state->getValue('label')]));
$this->messenger()->addStatus($this->t('The view %name has been saved.', ['%name' => $form_state->getValue('label')]));
$form_state->setRedirectUrl($this->entity->urlInfo('edit-form'));
}

View file

@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface;
/**
* Form controller for the Views duplicate form.
*
* @internal
*/
class ViewDuplicateForm extends ViewFormBase {

View file

@ -3,7 +3,7 @@
namespace Drupal\views_ui;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\ReplaceCommand;
@ -11,20 +11,23 @@ use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\ElementInfoManagerInterface;
use Drupal\Core\Url;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\views\Views;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
/**
* Form controller for the Views edit form.
*
* @internal
*/
class ViewEditForm extends ViewFormBase {
/**
* The views temp store.
*
* @var \Drupal\user\SharedTempStore
* @var \Drupal\Core\TempStore\SharedTempStore
*/
protected $tempStore;
@ -52,7 +55,7 @@ class ViewEditForm extends ViewFormBase {
/**
* Constructs a new ViewEditForm object.
*
* @param \Drupal\user\SharedTempStoreFactory $temp_store_factory
* @param \Drupal\Core\TempStore\SharedTempStoreFactory $temp_store_factory
* The factory for the temp store object.
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
* The request stack object.
@ -73,7 +76,7 @@ class ViewEditForm extends ViewFormBase {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('user.shared_tempstore'),
$container->get('tempstore.shared'),
$container->get('request_stack'),
$container->get('date.formatter'),
$container->get('element_info')
@ -129,7 +132,7 @@ class ViewEditForm extends ViewFormBase {
'#account' => $this->entityManager->getStorage('user')->load($view->lock->owner),
];
$lock_message_substitutions = [
'@user' => drupal_render($username),
'@user' => \Drupal::service('renderer')->render($username),
'@age' => $this->dateFormatter->formatTimeDiffSince($view->lock->updated),
':url' => $view->url('break-lock-form'),
];
@ -162,7 +165,6 @@ class ViewEditForm extends ViewFormBase {
],
];
$form['displays']['top'] = $this->renderDisplayTop($view);
// The rest requires a display to be selected.
@ -262,7 +264,7 @@ class ViewEditForm extends ViewFormBase {
// options.
$display_handler = $executable->displayHandlers->get($id);
if ($attachments = $display_handler->getAttachedDisplays()) {
foreach ($attachments as $attachment ) {
foreach ($attachments as $attachment) {
$attached_options = $executable->displayHandlers->get($attachment)->getOption('displays');
unset($attached_options[$id]);
$executable->displayHandlers->get($attachment)->setOption('displays', $attached_options);
@ -275,7 +277,7 @@ class ViewEditForm extends ViewFormBase {
// Rename display ids if needed.
foreach ($executable->displayHandlers as $id => $display) {
if (!empty($display->display['new_id']) && empty($display->display['deleted'])) {
if (!empty($display->display['new_id']) && $display->display['new_id'] !== $display->display['id'] && empty($display->display['deleted'])) {
$new_id = $display->display['new_id'];
$display->display['id'] = $new_id;
unset($display->display['new_id']);
@ -290,6 +292,9 @@ class ViewEditForm extends ViewFormBase {
'display_id' => $new_id,
]);
}
elseif (isset($display->display['new_id'])) {
unset($display->display['new_id']);
}
}
$view->set('display', $displays);
@ -320,7 +325,7 @@ class ViewEditForm extends ViewFormBase {
$view->save();
drupal_set_message($this->t('The view %name has been saved.', ['%name' => $view->label()]));
$this->messenger()->addStatus($this->t('The view %name has been saved.', ['%name' => $view->label()]));
// Remove this view from cache so we can edit it properly.
$this->tempStore->delete($view->id());
@ -414,15 +419,25 @@ class ViewEditForm extends ViewFormBase {
// path.
elseif ($view->status() && $view->getExecutable()->displayHandlers->get($display['id'])->hasPath()) {
$path = $view->getExecutable()->displayHandlers->get($display['id'])->getPath();
if ($path && (strpos($path, '%') === FALSE)) {
if (!parse_url($path, PHP_URL_SCHEME)) {
// @todo Views should expect and store a leading /. See:
// https://www.drupal.org/node/2423913
$url = Url::fromUserInput('/' . ltrim($path, '/'));
// Wrap this in a try/catch as trying to generate links to some
// routes may throw a NotAcceptableHttpException if they do not
// respond to HTML, such as RESTExports.
try {
if (!parse_url($path, PHP_URL_SCHEME)) {
// @todo Views should expect and store a leading /. See:
// https://www.drupal.org/node/2423913
$url = Url::fromUserInput('/' . ltrim($path, '/'));
}
else {
$url = Url::fromUri("base:$path");
}
}
else {
$url = Url::fromUri("base:$path");
catch (NotAcceptableHttpException $e) {
$url = '/' . $path;
}
$build['top']['actions']['path'] = [
'#type' => 'link',
'#title' => $this->t('View @display_title', ['@display_title' => $display_title]),
@ -1083,7 +1098,7 @@ class ViewEditForm extends ViewFormBase {
$build['fields'][$id]['#class'][] = Html::cleanCssIdentifier($display['id'] . '-' . $type . '-' . $id);
if ($executable->display_handler->useGroupBy() && $handler->usesGroupBy()) {
$build['fields'][$id]['#settings_links'][] = $this->l(SafeMarkup::format('<span class="label">@text</span>', ['@text' => $this->t('Aggregation settings')]), new Url('views_ui.form_handler_group', [
$build['fields'][$id]['#settings_links'][] = $this->l(new FormattableMarkup('<span class="label">@text</span>', ['@text' => $this->t('Aggregation settings')]), new Url('views_ui.form_handler_group', [
'js' => 'nojs',
'view' => $view->id(),
'display_id' => $display['id'],
@ -1093,7 +1108,7 @@ class ViewEditForm extends ViewFormBase {
}
if ($handler->hasExtraOptions()) {
$build['fields'][$id]['#settings_links'][] = $this->l(SafeMarkup::format('<span class="label">@text</span>', ['@text' => $this->t('Settings')]), new Url('views_ui.form_handler_extra', [
$build['fields'][$id]['#settings_links'][] = $this->l(new FormattableMarkup('<span class="label">@text</span>', ['@text' => $this->t('Settings')]), new Url('views_ui.form_handler_extra', [
'js' => 'nojs',
'view' => $view->id(),
'display_id' => $display['id'],
@ -1132,7 +1147,7 @@ class ViewEditForm extends ViewFormBase {
foreach ($contents as $key => $pid) {
if ($key != $last) {
$operator = $group_info['groups'][$gid] == 'OR' ? $this->t('OR') : $this->t('AND');
$store[$pid]['#link'] = SafeMarkup::format('@link <span>@operator</span>', ['@link' => $store[$pid]['#link'], '@operator' => $operator]);
$store[$pid]['#link'] = new FormattableMarkup('@link <span>@operator</span>', ['@link' => $store[$pid]['#link'], '@operator' => $operator]);
}
$build['fields'][$pid] = $store[$pid];
}

View file

@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
/**
* Defines a class to build a listing of view entities.
@ -177,6 +178,14 @@ class ViewListBuilder extends ConfigEntityListBuilder {
}
}
// ajax.js focuses automatically on the data-drupal-selector element. When
// enabling the view again, focusing on the disable link doesn't work, as it
// is hidden. We assign data-drupal-selector to every link, so it focuses
// on the edit link.
foreach ($operations as &$operation) {
$operation['attributes']['data-drupal-selector'] = 'views-listing-' . $entity->id();
}
return $operations;
}
@ -255,9 +264,17 @@ class ViewListBuilder extends ConfigEntityListBuilder {
if ($display->hasPath()) {
$path = $display->getPath();
if ($view->status() && strpos($path, '%') === FALSE) {
// @todo Views should expect and store a leading /. See:
// https://www.drupal.org/node/2423913
$rendered_path = \Drupal::l('/' . $path, Url::fromUserInput('/' . $path));
// Wrap this in a try/catch as trying to generate links to some
// routes may throw a NotAcceptableHttpException if they do not
// respond to HTML, such as RESTExports.
try {
// @todo Views should expect and store a leading /. See:
// https://www.drupal.org/node/2423913
$rendered_path = \Drupal::l('/' . $path, Url::fromUserInput('/' . $path));
}
catch (NotAcceptableHttpException $e) {
$rendered_path = '/' . $path;
}
}
else {
$rendered_path = '/' . $path;

View file

@ -7,6 +7,8 @@ use Drupal\Core\Url;
/**
* Form controller for the Views preview form.
*
* @internal
*/
class ViewPreviewForm extends ViewFormBase {
@ -75,7 +77,7 @@ class ViewPreviewForm extends ViewFormBase {
return [
'#attributes' => [
'id' => 'preview-submit-wrapper',
'class' => ['preview-submit-wrapper']
'class' => ['preview-submit-wrapper'],
],
'button' => [
'#type' => 'submit',

View file

@ -4,7 +4,6 @@ namespace Drupal\views_ui;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Timer;
use Drupal\Component\Utility\Xss;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Views;
@ -49,10 +48,10 @@ class ViewUI implements ViewEntityInterface {
* If this view is locked for editing.
*
* If this view is locked it will contain the result of
* \Drupal\user\SharedTempStore::getMetadata(). Which can be a stdClass or
* \Drupal\Core\TempStore\SharedTempStore::getMetadata(). Which can be a stdClass or
* NULL.
*
* @var stdClass
* @var object
*/
public $lock;
@ -688,7 +687,11 @@ class ViewUI implements ViewEntityInterface {
'#template' => "<strong>{% trans 'Title' %}</strong>",
],
],
Xss::filterAdmin($executable->getTitle()),
[
'data' => [
'#markup' => $executable->getTitle(),
],
],
];
if (isset($path)) {
// @todo Views should expect and store a leading /. See:
@ -710,7 +713,7 @@ class ViewUI implements ViewEntityInterface {
'data' => [
'#markup' => $path,
],
]
],
];
}
if ($show_stats) {
@ -787,7 +790,7 @@ class ViewUI implements ViewEntityInterface {
else {
foreach ($errors as $display_errors) {
foreach ($display_errors as $error) {
drupal_set_message($error, 'error');
\Drupal::messenger()->addError($error);
}
}
$preview = ['#markup' => t('Unable to preview due to validation errors.')];
@ -852,11 +855,11 @@ class ViewUI implements ViewEntityInterface {
}
/**
* Sets a cached view object in the user tempstore.
* Sets a cached view object in the shared tempstore.
*/
public function cacheSet() {
if ($this->isLocked()) {
drupal_set_message(t('Changes cannot be made to a locked view.'), 'error');
\Drupal::messenger()->addError(t('Changes cannot be made to a locked view.'));
return;
}
@ -875,7 +878,7 @@ class ViewUI implements ViewEntityInterface {
$executable->default_display = NULL;
$executable->query = NULL;
$executable->displayHandlers = NULL;
\Drupal::service('user.shared_tempstore')->get('views')->set($this->id(), $this);
\Drupal::service('tempstore.shared')->get('views')->set($this->id(), $this);
}
/**