The views add dialog filter search does not work as expected, it searches the label element instead of the title element.

When adding fields, filters, etc., in Views I am unable to use the string 'date' in the Search field to narrow down the available options. This is because the string of searchable text is derived from the input label, which as far as I can tell always contains the word "update".

To reproduce:

1. Edit a view,
2. in the Fields area, click "Add",
3. type "date" into the Search field.

The list should be filtered to only "date"-related options, but instead nothing happens. (I initially thought the keyword search wasn't working at all.)

This problem doesn't exist in 7.x.

Proposed solution: Formulate the searchText from the <td class="title"> element, which does not have "Update " prepended, instead of <label>.

I'll upload a patch in a moment.

CommentFileSizeAuthor
#43 drupal-views_ui-filtering_options-2846428-43.patch6.52 KBAnonymous (not verified)
#38 interdiff-37-38.txt7.57 KBAnonymous (not verified)
#38 drupal-views_ui-filtering_options-2846428-38.patch6.54 KBAnonymous (not verified)
#37 drupal-views_ui-filtering_options-2846428-36.patch8.92 KBmichielnugter
#37 interdiff.txt4.33 KBmichielnugter
#33 drupal-views_ui-filtering_options-2846428-33.patch7.54 KBmichielnugter
#33 interdiff.txt5.01 KBmichielnugter
#23 drupal-views_ui-filtering_options-2846428-23.patch4.37 KBmichielnugter
#23 interdiff.txt2.98 KBmichielnugter
#18 drupal-views_ui-filtering_options-2846428-18.patch3.85 KBothermachines
#18 drupal-views_ui-filtering_options-2846428-18-test-only.patch2.62 KBothermachines
#17 drupal-views_ui-filtering_options-2846428-17.patch3.66 KBothermachines
#17 drupal-views_ui-filtering_options-2846428-17-test-only.patch2.43 KBothermachines
#13 drupal-views_ui-filtering_options-2846428-13.patch3.67 KBothermachines
#13 drupal-views_ui-filtering_options-2846428-13-test-only.patch2.44 KBothermachines
#10 Screen Shot 2017-01-29 at 17.10.58.png91.07 KBJohn Cook
#10 Screen Shot 2017-01-29 at 17.05.45.png119.05 KBJohn Cook
#10 Screen Shot 2017-01-29 at 17.14.37.png97.88 KBJohn Cook
#10 Screen Shot 2017-01-29 at 17.06.05.png117.35 KBJohn Cook
#8 2846428-8.patch2.49 KBdagmar
#3 core-searchText_from_title-2846428-3.patch1.23 KBothermachines
#2 core-searchText_from_title-2846428-2.patch597 bytesothermachines
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

othermachines created an issue. See original summary.

othermachines’s picture

Status: Active » Needs review
FileSize
597 bytes
othermachines’s picture

Here's a better one.

Status: Needs review » Needs work

The last submitted patch, 3: core-searchText_from_title-2846428-3.patch, failed testing.

Lendude’s picture

@othermachines nice find! Manually tested this and you are spot on.

Fix makes sense, we need some Javascript tests for this though. There is some basic search setup in #2754985: [backport] Add JavaScript test coverage for adding an exposed filter in Views UI but that tries to do more and it's postponed on the extra things it's trying to do. So maybe some dedicated tests for the handler filtering would be great here.

othermachines’s picture

Hi, @Lendude. Sort of funny, huh? I'm actually surprised it wasn't noticed before, since... well, date fields.

I just had a quick look at the patch in #2754985-11: [backport] Add JavaScript test coverage for adding an exposed filter in Views UI and it looks like the basics are covered there. Are you suggesting pulling out the filter-related stuff into a simpler test?

This particular issue is a bit quirky and having eliminated the cause I don't think it warrants adding a special test case, do you? A string is a string - at least 99% of the time, anyway. :-/ Only thing I might suggest adding is to assert that description text is being searched so we know both elements are being correctly targeted and contain expected text.

Lendude’s picture

Are you suggesting pulling out the filter-related stuff into a simpler test?

Well yeah, looking at it now, combining the handler search testing with the exposed filter test makes little sense. The search needs its own dedicated test, and in that test I think its fine to add a search for the 'date' string and see that it currently fails to give the expected result.

dagmar’s picture

Status: Needs work » Needs review
Issue tags: +SprintWeekend2017, +BuenosAiresSprint
FileSize
2.49 KB

Marked #2847555: Searching for fields in views_ui doesn't work as expected as duplicated from this issue.

So I have a different problem, that is not fixed by this issue. If you search for ID, the results are not really representative.

Search for ID in views add fields

This new patch sort the handlers table by string length so if you type a few letters of a word, you will see first the shorter strings and will have more chance to find what you are looking for first.

droplet’s picture

I think it isn't duplicated. This one is bug fixing. Another one is search result improvement. #8 improvement may take a longer time to discuss in details.

I also created an issue to seek a common workaround for all these search fields.
#2846950: Narrow down Instant Search Field result in CORE

Patch #3 looks good. It's ready to go.

John Cook’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
117.35 KB
97.88 KB
119.05 KB
91.07 KB

I've tested patch #3 and #8 against 8.4.x.

Patch 3

The results for #3 are as follows:
Before patch:

After patch:

This works as described.

Patch 8

Patch #8 also performs a fix for this problem but it also has some other side effects.

Before patch:

After patch:

As you can see the order of the fields has change.

Therefore I would suggest moving patch #8 into Narrow down Instant Search Field result in CORE and commit #3 to fix the immediate problem.

Setting to RTBC for patch #3 and hiding #8 from display.

Lendude’s picture

Status: Reviewed & tested by the community » Needs work

As discussed in #5-#7, this still needs tests before we can RTBC it.

On reading up on this I agree with @droplet that this is a bug fix and #8 is an improvement, sorry @dagmar for implying that they might be the same thing. An improvement very much worth doing though!

othermachines’s picture

Assigned: Unassigned » othermachines

I'll work on a test this week.

othermachines’s picture

At the moment I'm having trouble running tests locally so not sure what will happen here (fingers crossed).

The last submitted patch, 13: drupal-views_ui-filtering_options-2846428-13-test-only.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 13: drupal-views_ui-filtering_options-2846428-13.patch, failed testing.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

othermachines’s picture

With all variables defined this time.

The last submitted patch, 18: drupal-views_ui-filtering_options-2846428-18-test-only.patch, failed testing.

Lendude’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests

@othermachines nice!

+++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
@@ -0,0 +1,80 @@
+    $web_assert->assertWaitOnAjaxRequest();
...
+    $session->wait(1000);

This should be updated to use the new preferred assertions that were added in #2837676: Provide a better way to validate all javascript activity is completed

Anonymous’s picture

#18: looks nice for me too! +1 for #20 and few remarks

  1. -    $all_rows = $page->findAll('css', 'tr.filterable-option');
    +    $all_rows = $page->findAll('css', '.filterable-option');
    

    A good practice is to manage only classes

  2. -    $this->assertTrue(count($visible_rows), format_string('Options filter found @num rows containing "date".', array('@num' => count($visible_rows))));
    +    use Drupal\Component\Render\FormattableMarkup;
    ...
    +    $this->assertTrue(count($visible_rows), new FormattableMarkup('Options filter found @num rows containing "date".', array('@num' => count($visible_rows))));
    

    format_string deprecated, and we haven't reason use it here.

  3. -    $this->assertFieldByName('name[users_field_data.changed]', NULL, 'Updated date field is displayed.');
    +    $this->assertSession()->fieldExists('name[users_field_data.changed]');
    

    similarly

droplet’s picture

+++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
@@ -0,0 +1,80 @@
+    // Test that the number of rows returned is less than total rows.
+    $this->assertTrue(count($visible_rows) < count($all_rows), 'Number of rows returned is less than total rows.');

An assertion to ensure it has the same number of "Updated" & rows at the beginning is required.

michielnugter’s picture

Status: Needs work » Needs review
FileSize
2.98 KB
4.37 KB

Small cleanup

- Used the new wait... methods.
- Added doxygen
- Added coverage for filterVisibleElements() by first checking the count before filtering. That covers @droplet's input right?
- Removed assertion messages as they're discouraged and fixed the deprecation.
- Changed deprecated assertFieldByName() implementation.

othermachines’s picture

Assigned: othermachines » Unassigned

Thanks for comments. Came by to roll another patch but I see it's been done.

droplet’s picture

Status: Needs review » Needs work
+++ b/core/modules/views_ui/js/views-admin.js
@@ -483,18 +483,18 @@
-        $label = $option.find('label');
+        $title = $option.find('.title');

+++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
@@ -0,0 +1,96 @@
+    // Assert the count is equal before filtering.
+    $all_rows = $page->findAll('css', '.filterable-option');
+    $visible_rows = $this->filterVisibleElements($all_rows);
+    $this->assertTrue(count($visible_rows) == count($all_rows));

Thanks @michielnugter! It's very close but it isn't what I wanted.

The reason we ran into the current problem is the word "Update" was added to label at some point. I bet that was an improvement of Accessibility. And that can be "Update" and "Add" in the future code changes. Or a checked box changed to "Checked Label" rather than "Update Label"..etc. At that point, it has potential to bring the bug back.

To prevent this happen again, we must check the word "Update" that match the rows at the beginning instead.

jQuery('.filterable-option').length === jQuery('.filterable-option:contains("Update")').length
othermachines’s picture

In response to #25 just wanted to note that fix proposed in #3 means the search string is no longer derived from label element so future changes there for reasons of accessibility (or whatever) wouldn't cause the issue to reemerge.

Small nitpick Re #23:

+    // Find matching rows based on visibility.
+    $all_rows = $page->findAll('css', '.filterable-option');

I don't think it's necessary to run this again after filtering.

Anonymous’s picture

I will try to explain #25 with an example again (be loyal to my English):

  1. We commited this patch as is.
  2. From X time we create issue "Update" prefix pointless, let's use "Check"
  3. Someone made patch with replace "Update" to "Check" and by some reason change search form .title to label again.
  4. Our patch does not prevent it, because search by 'date' still works. (But search by 'check' not works now!)

@droplet offers great idea to prevent this problem, because it very easy to implement. Although, of course, it does not give an absolute guarantee. It would be great to find for test a way to set unique words in .title and .description tags and testing search by them. But it is much more difficult, and perhaps not worth wasting time.

It would be great add check "Update" count near with search by 'date'. And documentation this.

Lendude’s picture

It would be great to find for test a way to set unique words in .title and .description tags and testing search by them.

Ok, so that sounds like we should make a custom global field handler in a test module, give that a distinct title and description and test for that.

droplet’s picture

Thanks @vaplas.

Instead of rebuilding a search system in the test case, another little tweak we could do:

1. Additional to above test.
2. Use JS (or any simple way) to change a label in Row A to "UniqueSearchWordWithoutSpaces"
3. Use JS to change a .title in Row B to "UniqueSearchWordWithoutSpaces"
4. Perform a search of "UniqueSearchWordWithoutSpaces"
5. Check if the result is Row B and only 1 result

othermachines’s picture

@vaplas - Very clear, thanks! I did suggest a broader approach in #6 (testing that elements are being targeted correctly). I'm honestly not sure about that now, though.

Is testing implementation (not just expected behaviour) a good idea? #29 would work to flag a very specific code change, but it assumes that change will always be bad. As soon as someone finds a *good* reason to omit the .title element from search functionality the test will not only fail, it will become obsolete - even though the behaviour itself might work perfectly.

I'm not suggesting that's the wrong way to do it - just trying to get a better understanding of the end goal so I can be more useful.

michielnugter’s picture

I looked at the JavaScript and it is hardcoded to look at the .title and .description tags. Because it is hardcoded a test should cover it, we want to cover each line of code in a test.
If the HTML is changed without updating the JavaScript this test will catch that and indicate the JavaScript (and this test) will also need an update.

So actually to make it complete, we need to inspect the HTML as part of the test and search on both title and description seperately. To make it complete we should use a custom global field to have better control over the text we want to search for.

michielnugter’s picture

Working on something, will finish it tomorrow and post it then.

michielnugter’s picture

Ok, new version.

I added a test module that adds two fields with a unique and searchable title and description.

The title and description are tested seperately now. I think the test now covers everything in JavaScript and I don't think any deeper inspection makes the test better. If the HTML is changed without the JavaScript this test will fail thus catching the broken functionality.

Lendude’s picture

Status: Needs review » Needs work
+++ b/core/modules/views_ui/tests/modules/views_ui_test_field/views_ui_test_field.views.inc
@@ -0,0 +1,29 @@
+      'id' => 'views_test_field_1',
...
+      'id' => 'views_test_field_2',

Ha! Sneaky, providing a title and description without an actual working plugin. I like!

  1. +++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
    @@ -0,0 +1,134 @@
    +      'administer views',
    

    Only this permission is needed. The other three can go.

  2. +++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
    @@ -0,0 +1,134 @@
    +    // Assert the count is equal before filtering.
    

    'Assert all rows are visible before filtering'. Otherwise we need to specify what 'the count' is equal to.

This gives excellent base coverage. We are now missing the 'date' search though. I would expect an additional test where we search for 'date' and find neither test fields (so something that would fail without the fix).

Anonymous’s picture

@michielnugter good works! But unfortunately, we still have the problem. If we change the .title to label, this test pass too :( Because

# /core/modules/views_ui/src/Form/Ajax/AddHandler.php::buildForm()
              'data' => array(
                '#title' => $option['title'],
                '#plain_text' => $option['title'],

What about hook_form_alter()? And what about set special word for label and testing that we not search by this too?

Also bit remarks:

+++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
@@ -0,0 +1,134 @@
+    $page->waitFor(10, function() use ($page) {
+      return !$page->findField('name[views.views_test_field_2]')->isVisible();
+    });
...
+    $this->assertFalse($field->isVisible());

Double check. Maybe we can use:

$unvisible = $page->waitFor(10, function() use ($page) { ...
$this->assertTrue($unvisible);
+++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
@@ -0,0 +1,134 @@
+    // Test that greater than zero options have been returned.
+    $this->assertTrue(count($visible_rows) > 0);
...
+    // Test that the number of rows returned is less than total rows.
+    $this->assertTrue(count($visible_rows) < count($all_rows));

Maybe use only:
$this->assertCount(1, $visible_rows);

michielnugter’s picture

Status: Needs work » Needs review

Updated test:

- Permissions fixed
- Reintroduced the label filter test using the form alter @vaplas suggested, thanks for that!
- Cleaned up double assertions and comments. @vaplas: The waitFor() doesn't fail if the assertion never passes, a recheck after the waitFor is required because of that.

Important warning though, I'm experiencing random failures on this test, the same as in #2832672. We need to fix this before we can commit this patch.. I'll postpone this one once it fails/passes.

michielnugter’s picture

Anonymous’s picture

#37 looks great for me! Now we have two controllable fields, hence we can not depend from other items. This simplifies the test, no?

The waitFor() doesn't fail if the assertion never passes,

I meant, that waitFor() return TRUE if success (or FALSE if not). We can use this fact. But +1 to use isVisible() by readability reason.

Review #38 patch:

-  //$form['options']['name']['#options']['views.views_test_field_1']['title']['data']['#title'] = 'TEST_FIELD_1_LABEL';
+  $form['options']['name']['#options']['views.views_test_field_1']['title']['data']['#title'] .= ' FIELD_1_LABEL';

Looks like forgotten comment. And maybe the addition would be better than a replacement, because we save words from title in this field.

-    'title' => t('Secondary field for testing purposes - FIELD_2_TITLE'),
-    'help' => t('Provide a secondary field for testing purposes. - FIELD_2_DESCRIPTION'),
+    'title' => t('Views test field 2 - FIELD_2_TITLE'),
+    'help' => t('Field 2 for testing purposes - FIELD_2_DESCRIPTION'),

Just reduction to a one view.

michielnugter’s picture

Nice cleanup! You're completely right about the overcomplicated way of testing now that we have 2 fields to check on..

Commented line, whoops.. Sorry about that.

Still we have to wait with RTBC untill the related issue is fixed I think..

droplet’s picture

Status: Needs review » Reviewed & tested by the community

It's the right time to go I think.

michielnugter’s picture

Ignore my note on the related bug and no-commit: The random fail only occurs if you update the PhantomJS Driver. It's safe to commit this, without the driver upgrade I had no random fails..

michielnugter’s picture

Title: Can't filter by string 'date' when adding options in Views » Views add dialog filter searches on label instead of title
Issue summary: View changes

Updated issue title and added small generic comment on the description to indicate the fix/test is not aimed at fixing the date search specifically but at searching the correct element.

Anonymous’s picture

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed f974370 to 8.4.x and c78d01c to 8.3.x. Thanks!

diff --git a/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
index a2ddbda..32b1a40 100644
--- a/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
+++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterOptionsTest.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\Tests\views_ui\FunctionalJavascript;
 
-use Behat\Mink\Element\NodeElement;
 use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
 
 /**

Fixed unused on commit.

  • alexpott committed f974370 on 8.4.x
    Issue #2846428 by othermachines, michielnugter, vaplas, dagmar, John...

  • alexpott committed c78d01c on 8.3.x
    Issue #2846428 by othermachines, michielnugter, vaplas, dagmar, John...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.