While testing the patch for #2156661: Search admin menu entry uses "settings" -- UI-text standards violation I came across an unrelated problem:
If you go to the Search pages management screen (currently admin/config/search/settings, but after that patch is in, it will be admin/config/search/pages), and try to either Add a new page or Enable a disabled page, you get an exception like this:
Symfony\Component\Routing\Exception\RouteNotFoundException: Route "search.view_user_search" does not exist. in Drupal\Core\Routing\RouteProvider->getRouteByName() (line 150 of core/lib/Drupal/Core/Routing/RouteProvider.php).
The page is added/enabled correctly, but you get this exception on your screen.
The reason is this code in core/modules/search/lib/Drupal/search/Routing/SearchPageRoutes.php:
$active_pages = $this->searchPageRepository->getActiveSearchPages();
foreach ($active_pages as $entity_id => $entity) {
$routes["search.view_$entity_id"] = new Route(
'/search/' . $entity->getPath() . '/{keys}',
...
In other words, the routes for managing pages are dynamic, and they are only set up for active pages. But just after you have either added or enabled a previously nonexistent or disabled page, the routes do not exist. Hence you get this exception, probably when you are trying to return to the Search settings page.
So ... there's some kind of a race condition going on -- the routes are trying to be set up before they're available.
And I'm sure this used to work a few weeks ago. Something changed, and the tests we have did not catch it.
| Comment | File | Size | Author |
|---|---|---|---|
| #8 | search-2229303-7.patch | 3.86 KB | tim.plunkett |
| #5 | 2229303-additional-tests.patch | 3.55 KB | jhodgdon |
Comments
Comment #1
jhodgdonMore on this...
The error is happening when the site tries to return you to admin/config/search/settings.
This page is an entity list for the SearchPage entity:
Looking at SearchPageListBuilder::buildRow()
So that is where the route is being requested.
As noted in the original issue filing, the route is being created in SearchPageRoutes (a RouteListener):
And here is SearchPageRepository::getActiveSearchPages()
So my guess is that after adding or enabling a route, the RouteListener isn't being invoked at all to define the new routes. If you refresh the page after getting the exception, all is well -- the route is defined by then.
Is there something we need to do to make this happen? And why don't the tests catch this???
Comment #2
tim.plunkettSo, SearchPage::postSave() has code to handle this:
$this->routeBuilder()->setRebuildNeeded();However, RouterRebuildSubscriber::onKernelTerminate() is apparently not firing during the AJAX request (which makes some sense, I guess).
This worked at one point, but apparently our test coverage is not sufficient.
I'll at least get that taken care of.
Comment #3
tim.plunkettHmm, seems RouterRebuildSubscriber::onKernelTerminate is never called during the test.
Since the routes are *never* rebuilt, after disabling it, the route is not missing when trying to enable.
Comment #4
jhodgdonI don't think there is any AJAX request happening here (re #2)?
Regarding test coverage, maybe you're talking about some unit tests?
We also have some tests for search page CRUD via the UI in SearchConfigSettingsFormTest::testMultipleSearchPages().
There's a spot where it uses the "add", but it only does:
And this passes (the message is shown, along with the exception). I guess drupalPostForm() doesn't care if the page it lands on has an exception on it, and WebTestBase doesn't care if there is an exception either, apparently.
And later on it does an enable with:
and also doesn't check that the text on the search settings page comes back up.
So we should add a couple of lines to these tests to make sure the search settings page is generated, and probably an assertNoText('Exception') or something like that. Probably to all of the CRUD operations.
Comment #5
jhodgdonHuh. I attempted to add some tests to SearchConfigSettingsFormTest::testMultipleSearchPages() but I cannot reproduce the problem there. The add and enable operations get you successfully back to the search settings page without an exception. Perhaps this is due to how drupalPostForm() works, as opposed to the Real World?
Anyway, here's a test patch, but it doesn't fail, and when you look at the debug output the add/enable operations worked just fine and didn't take you to an exception page.
Comment #6
jhodgdonSetting to "needs work" since these tests don't really help the problem and definitely don't solve the problem.
Comment #7
jhodgdonOK, I think I see what you're saying about AJAX - you are saying that Disable and Enable are AJAX operations -- I guess they might be. They are coming from the Drupal\Core\Config\Entity\DraggableListBuilder class... no, from its parent, ConfigEntityListBuilder... no its parent, EntityListBuilder.
Are these AJAX? It's not obvious to me.
But anyway, this does not apply to Add. Add goes to a whole separate add form page, and then when the page submits you get back to admin/config/search/settings, which gives you the exception when you are in the real UI (the test UI apparently does not generate the exception).
Comment #8
tim.plunkettThis exposes the current brokenness.
Because the router is never rebuilt during the test run, neither of the search pages are actually working.
But that is a Simpletest problem separate from the bug at hand, which I still believe is AJAX-based. Looking into that more.
Comment #9
jhodgdonIn the real UI, if you go back to admin/config/search/settings after getting the exception, you are OK, so I don't think we should do a get on admin/config/search/settings in that patch in verifySearchPageOperations.
The other change, to check the path, seems like a good idea, but we should probably move it to a different method so that we won't move to a different page within verifySearchPageOperations (which is often done twice in a row).
Comment #10
jhodgdonActually, I am pretty sure this is not specifically AJAX-related.
If you go to admin/config/search/settings and disable a search page, and then copy the URL it gives you for the Enable, something like:
http://wren/~d8git/admin/config/search/settings/manage/users/enable
(here "users" is the machine name of this particular page that I added manually), and paste that into a new tab of your browser, you can see the exception.
Comment #12
tim.plunkettCorrect, not AJAX related. Views is also broken due to what I think is a related reason, bisecting now.
At least those tests failed!
Comment #13
tim.plunkettThere are two problems here.
One is #2230091: Route rebuilding is not guaranteed to finish in time for the next request, which is causing the breakage during manual testing.
The second is that simpletest does not fire the terminate subscriber at all, and so routes are never rebuilt.
I don't have any bright ideas for fixing that, and I also don't know if that needs a dedicated issue.
Comment #14
jhodgdon#2230091: Route rebuilding is not guaranteed to finish in time for the next request has now been fixed.
I just retested this:
- Install with standard profile.
- Go to Configuration > Search and Meta Data > Search pages (admin/config/search/pages)
- Disable then Enable the User search page. All is well.
- Add a new Content search page. All is well.
So, I'm going to now mark this as a duplicate of that other issue.