Highlight selected navigation item

In research I’ve sometimes seen people click the wrong nav item. I
reckon that people’s concept of which pages live behind which navigation
items isn’t very strong.

We can reinforce this relationship by showing, for every page, which is
the corresponding nav item. The conventional way of doing this is either
with some kind of emphasis, typically colour or bold. I’ve gone for bold
because colour would be weird.

---

The implementation of this is quite loosely coupled to our application
code because:
- our application code is not well structured (eg we don’t make any use
  of blueprints)
- spreading this change across lots of files in our application would
  make it harder to test without actually hitting each endpoints; such
  tests would be slow and verbose

So I’ve gone for more of a meta approach. Rather than testing that each
endpoint has a specific navigation item selected, I’ve gone for
validating that:
- all endpoints being mapped to are real
- all endpoints have _a_ selected navigation item (or are specifically
  excluded)

This means that it’s impossible to add, change or remove an endpoint
without also updating which navigation item should be selected. And the
actual mapping is so declarative that it testing it would be redundant.
This commit is contained in:
Chris Hill-Scott
2018-04-24 12:48:05 +01:00
parent 63061b1bab
commit 1fba5d186d
5 changed files with 312 additions and 8 deletions

View File

@@ -0,0 +1,53 @@
import pytest
from tests.conftest import SERVICE_ONE_ID, app_
from app import navigation
all_endpoints = [
rule.endpoint for rule in next(app_(None)).url_map.iter_rules()
]
def test_navigation_items_are_properly_defined():
for endpoint in navigation.endpoints_with_navigation:
assert endpoint in all_endpoints
assert endpoint not in navigation.endpoints_without_navigation
assert navigation.endpoints_with_navigation.count(endpoint) == 1
def test_excluded_navigation_items_are_properly_defined():
for endpoint in navigation.endpoints_without_navigation:
assert endpoint in all_endpoints
assert endpoint not in navigation.endpoints_with_navigation
assert navigation.endpoints_without_navigation.count(endpoint) == 1
def test_all_endpoints_are_covered():
for endpoint in all_endpoints:
assert endpoint in (
navigation.endpoints_with_navigation +
navigation.endpoints_without_navigation
)
@pytest.mark.xfail(raises=KeyError)
def test_raises_on_invalid_navigation_item(client_request):
navigation.nav_selected('foo')
@pytest.mark.parametrize('endpoint, selected_nav_item', [
('main.choose_template', 'Templates'),
('main.manage_users', 'Team members'),
])
def test_a_page_should_nave_selected_navigation_item(
client_request,
mock_get_service_templates,
mock_get_users_by_service,
mock_get_invites_for_service,
endpoint,
selected_nav_item,
):
page = client_request.get(endpoint, service_id=SERVICE_ONE_ID)
selected_nav_items = page.select('.navigation a.selected')
assert len(selected_nav_items) == 1
assert selected_nav_items[0].text.strip() == selected_nav_item