diff --git a/core/modules/views/js/base.js b/core/modules/views/js/base.js index 7c7622db4e572b76293d0baffff9ecaab3de349a..cca3be4ddecd0fec3cdb4b47881a7e4a55e3e9c5 100644 --- a/core/modules/views/js/base.js +++ b/core/modules/views/js/base.js @@ -53,9 +53,11 @@ Drupal.Views.parseViewArgs = function (href, viewPath) { var returnObj = {}; var path = Drupal.Views.getPath(href); + // Get viewPath url without baseUrl portion. + var viewHref = Drupal.url(viewPath).substring(drupalSettings.path.baseUrl.length); // Ensure we have a correct path. - if (viewPath && path.substring(0, viewPath.length + 1) === viewPath + '/') { - returnObj.view_args = decodeURIComponent(path.substring(viewPath.length + 1, path.length)); + if (viewHref && path.substring(0, viewHref.length + 1) === viewHref + '/') { + returnObj.view_args = decodeURIComponent(path.substring(viewHref.length + 1, path.length)); returnObj.view_path = path; } return returnObj; diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml index bf44f36e6b53a5e7501f59096123436e0ba8726f..e2e143eafc2bdf288b705d3f974a0c8e4d2e8183 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml @@ -5,56 +5,450 @@ dependencies: - node - user id: test_glossary -label: test_glossary -module: views -description: '' +label: Test glossary +module: node +description: 'All content, by letter.' tag: default base_table: node_field_data base_field: nid core: '8' display: default: + id: default + display_title: Master + display_plugin: default + position: 0 display_options: + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + use_ajax: true access: type: perm - arguments: + options: + perm: 'access content' + cache: + type: tag + options: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: mini + options: + items_per_page: 36 + offset: 0 + id: 0 + total_pages: 0 + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + tags: + previous: ‹‹ + next: ›› + fields: title: - default_argument_type: fixed + id: title + table: node_field_data field: title - glossary: true + plugin_id: field + relationship: none + group_type: group + admin_label: '' + label: Title + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + entity_type: node + entity_field: title + name: + id: name + table: users_field_data + field: name + label: Author + relationship: uid + plugin_id: field + type: user_name + group_type: group + admin_label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + entity_type: user + entity_field: name + changed: + id: changed + table: node_field_data + field: changed + label: 'Last update' + type: timestamp + settings: + date_format: long + custom_date_format: '' + timezone: '' + plugin_id: field + relationship: none + group_type: group + admin_label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + entity_type: node + entity_field: changed + arguments: + title: id: title - limit: 1 + table: node_field_data + field: title + default_action: default + exception: + title_enable: true + default_argument_type: fixed + default_argument_options: + argument: a summary: format: default_summary - number_of_records: 0 - summary_options: - items_per_page: 25 - table: node_field_data + specify_validation: true + glossary: true + limit: 1 + case: upper + path_case: lower + transform_dash: false plugin_id: string + relationship: none + group_type: group + admin_label: '' + title_enable: false + title: '' + default_argument_skip_url: false + summary_options: { } + validate: + type: none + fail: 'not found' + validate_options: { } + break_phrase: false entity_type: node entity_field: title - cache: - type: tag - exposed_form: - type: basic - fields: + relationships: + uid: + id: uid + table: node_field_data + field: uid + plugin_id: standard + relationship: none + group_type: group + admin_label: author + required: false + style: + type: table + options: + columns: + title: title + name: name + changed: changed + default: title + info: + title: + sortable: true + separator: '' + name: + sortable: true + separator: '' + changed: + sortable: true + separator: '' + override: true + sticky: false + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + order: asc + summary: '' + empty_table: false + row: + type: fields + options: + inline: { } + separator: '' + hide_empty: false + default_field_elements: true + header: { } + footer: { } + empty: { } + sorts: { } + filters: + langcode: + id: langcode + table: node_field_data + field: langcode + relationship: none + group_type: group + admin_label: '' + operator: in + value: + '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + reduce: false + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: language + entity_type: node + entity_field: langcode + display_extenders: { } + cache_metadata: + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + max-age: 0 + tags: { } + attachment_1: + id: attachment_1 + display_title: Attachment + display_plugin: attachment + position: 2 + display_options: + query: + type: views_query + options: { } + pager: + type: none + options: + offset: 0 + items_per_page: 0 + defaults: + arguments: false + arguments: title: - field: title id: title - label: '' table: node_field_data - plugin_id: field + field: title + default_action: summary + exception: + title_enable: true + default_argument_type: fixed + default_argument_options: + argument: a + summary: + format: unformatted_summary + summary_options: + items_per_page: 25 + inline: true + separator: ' | ' + specify_validation: true + glossary: true + limit: 1 + case: upper + path_case: lower + transform_dash: false + plugin_id: string + relationship: none + group_type: group + admin_label: '' + title_enable: false + title: '' + default_argument_skip_url: false + validate: + type: none + fail: 'not found' + validate_options: { } + break_phrase: false entity_type: node entity_field: title - pager: - type: full + displays: + default: default + page_1: page_1 + inherit_arguments: false + display_extenders: { } + cache_metadata: + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + max-age: 0 + tags: { } + page_1: + id: page_1 + display_title: Page + display_plugin: page + position: 1 + display_options: query: type: views_query - style: - type: default - row: - type: fields - display_plugin: default - display_title: Master - id: default - position: 0 + options: { } + path: test-glossary + menu: + type: normal + title: Glossary + weight: 0 + menu_name: main + parent: '' + display_extenders: { } + cache_metadata: + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + max-age: 0 + tags: { } diff --git a/core/modules/views/tests/src/FunctionalJavascript/GlossaryViewTest.php b/core/modules/views/tests/src/FunctionalJavascript/GlossaryViewTest.php new file mode 100644 index 0000000000000000000000000000000000000000..42da7b6593b7c34dcc012f54a7fce6bc634fd099 --- /dev/null +++ b/core/modules/views/tests/src/FunctionalJavascript/GlossaryViewTest.php @@ -0,0 +1,129 @@ +<?php + +namespace Drupal\Tests\views\FunctionalJavascript; + +use Drupal\Core\Url; +use Drupal\FunctionalJavascriptTests\JavascriptTestBase; +use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\simpletest\ContentTypeCreationTrait; +use Drupal\simpletest\NodeCreationTrait; +use Drupal\views\Tests\ViewTestData; + +/** + * Tests the basic AJAX functionality of the Glossary View. + * + * @group node + */ +class GlossaryViewTest extends JavascriptTestBase { + + use ContentTypeCreationTrait; + use NodeCreationTrait; + + /** + * {@inheritdoc} + */ + public static $modules = ['language', 'node', 'views', 'views_test_config']; + + /** + * @var array + * The test Views to enable. + */ + public static $testViews = ['test_glossary']; + + /** + * @var + * The additional language to use. + */ + protected $language; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + ViewTestData::createTestViews(get_class($this), array('views_test_config')); + + // Create a Content type and some test nodes with titles that start with + // different letters. + $this->createContentType(['type' => 'page']); + + $titles = [ + 'Page One', + 'Page Two', + 'Another page', + ]; + foreach ($titles as $title) { + $this->createNode([ + 'title' => $title, + 'language' => 'en', + ]); + $this->createNode([ + 'title' => $title, + 'language' => 'nl', + ]); + } + + // Create a user privileged enough to use exposed filters and view content. + $user = $this->drupalCreateUser([ + 'administer site configuration', + 'access content', + 'access content overview', + ]); + $this->drupalLogin($user); + } + + /** + * Tests the AJAX callbacks for the glossary view. + */ + public function testGlossaryDefault() { + // Visit the default Glossary page. + $url = Url::fromRoute('view.test_glossary.page_1'); + $this->drupalGet($url); + + $session = $this->getSession(); + $web_assert = $this->assertSession(); + + $page = $session->getPage(); + $rows = $page->findAll('css', '.view-test-glossary tr'); + // We expect 2 rows plus the header row. + $this->assertCount(3, $rows); + // Click on the P link, this should show 4 rows plus the header row. + $page->clickLink('P'); + $web_assert->assertWaitOnAjaxRequest(); + $rows = $page->findAll('css', '.view-test-glossary tr'); + $this->assertCount(5, $rows); + } + + /** + * Test that the glossary also works on a language prefixed URL. + */ + public function testGlossaryLanguagePrefix() { + $this->language = ConfigurableLanguage::createFromLangcode('nl')->save(); + + $config = $this->config('language.negotiation'); + $config->set('url.prefixes', ['en' => 'en', 'nl' => 'nl']) + ->save(); + + \Drupal::service('kernel')->rebuildContainer(); + + $url = Url::fromRoute('view.test_glossary.page_1'); + $this->drupalGet($url); + + $session = $this->getSession(); + $web_assert = $this->assertSession(); + + $page = $session->getPage(); + + $rows = $page->findAll('css', '.view-test-glossary tr'); + // We expect 2 rows plus the header row. + $this->assertCount(3, $rows); + // Click on the P link, this should show 4 rows plus the header row. + $page->clickLink('P'); + $web_assert->assertWaitOnAjaxRequest(); + + $rows = $page->findAll('css', '.view-test-glossary tr'); + $this->assertCount(5, $rows); + } + +}