DisplayPathTest.php 9.71 KB
Newer Older
1 2
<?php

3 4
namespace Drupal\Tests\views_ui\Functional;

5 6
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\menu_link_content\Entity\MenuLinkContent;
7
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
8 9 10 11

/**
 * Tests the UI of generic display path plugin.
 *
12
 * @group views_ui
13 14
 * @see \Drupal\views\Plugin\views\display\PathPluginBase
 */
15
class DisplayPathTest extends UITestBase {
16

17
  use AssertPageCacheContextsAndTagsTrait;
18

19 20
  protected function setUp($import_test_views = TRUE) {
    parent::setUp($import_test_views);
21

22
    $this->placeBlock('page_title_block');
23 24
  }

25 26 27
  /**
   * {@inheritdoc}
   */
28
  public static $modules = ['menu_ui'];
29

30 31 32 33 34
  /**
   * Views used by this test.
   *
   * @var array
   */
35
  public static $testViews = ['test_view', 'test_page_display_menu'];
36

37 38 39
  /**
   * Runs the tests.
   */
40
  public function testPathUI() {
41 42
    $this->doBasicPathUITest();
    $this->doAdvancedPathsValidationTest();
43
    $this->doPathXssFilterTest();
44 45 46 47 48 49
  }

  /**
   * Tests basic functionality in configuring a view.
   */
  protected function doBasicPathUITest() {
50 51 52
    $this->drupalGet('admin/structure/views/view/test_view');

    // Add a new page display and check the appearing text.
53
    $this->drupalPostForm(NULL, [], 'Add Page');
54
    $this->assertText(t('No path is set'), 'The right text appears if no path was set.');
55
    $this->assertNoLink(t('View @display', ['@display' => 'page']), 'No view page link found on the page.');
56 57

    // Save a path and make sure the summary appears as expected.
58
    $random_path = $this->randomMachineName();
59 60 61 62
    // @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);

63
    $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => $random_path], t('Apply'));
64
    $this->assertText('/' . $random_path, 'The custom path appears in the summary.');
65 66 67 68
    $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);
69 70
  }

71 72 73 74 75
  /**
   * Tests that View paths are properly filtered for XSS.
   */
  public function doPathXssFilterTest() {
    $this->drupalGet('admin/structure/views/view/test_view');
76 77 78 79 80 81 82
    $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'));
83 84 85 86 87 88 89 90 91 92
    $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');
  }

93 94 95 96 97 98
  /**
   * Tests a couple of invalid path patterns.
   */
  protected function doAdvancedPathsValidationTest() {
    $url = 'admin/structure/views/nojs/display/test_view/page_1/path';

99
    $this->drupalPostForm($url, ['path' => '%/magrathea'], t('Apply'));
100 101 102
    $this->assertUrl($url);
    $this->assertText('"%" may not be used for the first segment of a path.');

103
    $this->drupalPostForm($url, ['path' => 'user/%1/example'], t('Apply'));
104 105 106 107
    $this->assertUrl($url);
    $this->assertText("Numeric placeholders may not be used. Please use plain placeholders (%).");
  }

108 109 110 111 112
  /**
   * Tests deleting a page display that has no path.
   */
  public function testDeleteWithNoPath() {
    $this->drupalGet('admin/structure/views/view/test_view');
113 114 115 116
    $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']));
117
  }
118

119 120 121 122
  /**
   * Tests the menu and tab option form.
   */
  public function testMenuOptions() {
123
    $this->container->get('module_installer')->install(['menu_ui']);
124 125 126
    $this->drupalGet('admin/structure/views/view/test_view');

    // Add a new page display.
127
    $this->drupalPostForm(NULL, [], 'Add Page');
128 129

    // Add an invalid path (only fragment).
130
    $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => '#foo'], t('Apply'));
131 132 133
    $this->assertText('Path is empty');

    // Add an invalid path with a query.
134
    $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => 'foo?bar'], t('Apply'));
135 136 137
    $this->assertText('No query allowed.');

    // Add an invalid path with just a query.
138
    $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => '?bar'], t('Apply'));
139 140 141
    $this->assertText('Path is empty');

    // Provide a random, valid path string.
142
    $random_string = $this->randomMachineName();
143

144
    // Save a path.
145
    $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/path', ['path' => $random_string], t('Apply'));
146 147
    $this->drupalGet('admin/structure/views/view/test_view');

148
    $this->drupalPostForm('admin/structure/views/nojs/display/test_view/page_1/menu', ['menu[type]' => 'default tab', 'menu[title]' => 'Test tab title'], t('Apply'));
149 150 151
    $this->assertResponse(200);
    $this->assertUrl('admin/structure/views/nojs/display/test_view/page_1/tab_options');

152
    $this->drupalPostForm(NULL, ['tab_options[type]' => 'tab', 'tab_options[title]' => $this->randomString()], t('Apply'));
153 154 155 156
    $this->assertResponse(200);
    $this->assertUrl('admin/structure/views/view/test_view/edit/page_1');

    $this->drupalGet('admin/structure/views/view/test_view');
157
    $this->assertLink(t('Tab: @title', ['@title' => 'Test tab title']));
158 159
    // 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');
160 161 162 163 164

    // 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"]');
165
    $menu_options = (array) $menu_parent[0]->findAll('css', 'option');
166 167
    unset($menu_options['@attributes']);

168 169 170 171 172
    // Convert array to make the next assertion possible.
    $menu_options = array_map(function($element) {
      return $element->getText();
    }, $menu_options);

173 174 175 176 177 178 179 180 181 182 183
    $this->assertEqual([
      '<User account menu>',
      '-- My account',
      '-- Log out',
      '<Administration>',
      '<Footer>',
      '<Main navigation>',
      '<Tools>',
      '-- Compose tips (disabled)',
      '-- Test menu link',
    ], $menu_options);
184 185 186 187

    // The cache contexts associated with the (in)accessible menu links are
    // bubbled.
    $this->assertCacheContext('user.permissions');
188 189
  }

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
  /**
   * 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);
  }

257
}