From 516abc5725a2b8e6b30884139be197ddd7abab69 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Wed, 31 Mar 2021 15:42:39 +0000 Subject: [PATCH] Drop parent group filter keyword from special group agenda items. Fixes #3115. - Legacy-Id: 18927 --- ietf/meeting/helpers.py | 11 +++++- ietf/meeting/tests_js.py | 85 ++++++++++++++++++++++++++++++++-------- ietf/meeting/views.py | 8 ++-- 3 files changed, 82 insertions(+), 22 deletions(-) diff --git a/ietf/meeting/helpers.py b/ietf/meeting/helpers.py index 42ec9d4ba..ae295842f 100644 --- a/ietf/meeting/helpers.py +++ b/ietf/meeting/helpers.py @@ -243,6 +243,10 @@ def preprocess_assignments_for_agenda(assignments_queryset, meeting, extra_prefe return assignments +def is_regular_agenda_filter_group(group): + """Should this group appear in the 'regular' agenda filter button lists?""" + return group.type_id in ('wg', 'rg', 'ag', 'rag', 'iab', 'program') + def tag_assignments_with_filter_keywords(assignments): """Add keywords for agenda filtering @@ -261,7 +265,12 @@ def filter_keywords_for_session(session): keywords.add('bof') keywords.add(group.acronym.lower()) area = getattr(group, 'historic_parent', group.parent) - if area is not None: + + # Only sessions belonging to "regular" groups should respond to the + # parent group filter keyword (often the 'area'). This must match + # the test used by the agenda() view to decide whether a group + # gets an area or non-area filter button. + if is_regular_agenda_filter_group(group) and area is not None: keywords.add(area.acronym.lower()) office_hours_match = re.match(r'^ *\w+(?: +\w+)* +office hours *$', session.name, re.IGNORECASE) if office_hours_match is not None: diff --git a/ietf/meeting/tests_js.py b/ietf/meeting/tests_js.py index 5bec75fbb..9342c6a3f 100644 --- a/ietf/meeting/tests_js.py +++ b/ietf/meeting/tests_js.py @@ -649,44 +649,95 @@ class AgendaTests(MeetingTestCase): else: self.assertIsNone(item_div, 'Unexpected weekview entry for "%s" (%s)' % (label, item.slug())) + @staticmethod + def open_agenda_filter_ui(wait): + """Click the 'customize' anchor to reveal the group buttons""" + customize_anchor = wait.until( + expected_conditions.element_to_be_clickable( + (By.CSS_SELECTOR, '#accordion a[data-toggle="collapse"]') + ) + ) + customize_anchor.click() + return customize_anchor + + @staticmethod + def get_agenda_filter_group_button(wait, group_acronym): + return wait.until( + expected_conditions.element_to_be_clickable( + (By.CSS_SELECTOR, 'button.pickview.%s' % group_acronym) + ) + ) + def test_agenda_view_group_filter_toggle(self): """Clicking a group toggle enables/disables agenda filtering""" + wait = WebDriverWait(self.driver, 2) group_acronym = 'mars' self.login() url = self.absreverse('ietf.meeting.views.agenda') self.driver.get(url) - # Click the 'customize' anchor to reveal the group buttons - customize_anchor = WebDriverWait(self.driver, 2).until( - expected_conditions.element_to_be_clickable( - (By.CSS_SELECTOR, '#accordion a[data-toggle="collapse"]') - ) - ) - customize_anchor.click() + self.open_agenda_filter_ui(wait) # Click the group button - group_button = WebDriverWait(self.driver, 2).until( - expected_conditions.element_to_be_clickable( - (By.CSS_SELECTOR, 'button.pickview.%s' % group_acronym) - ) - ) + group_button = self.get_agenda_filter_group_button(wait, group_acronym) group_button.click() # Check visibility self.assert_agenda_item_visibility([group_acronym]) # Click the group button again - group_button = WebDriverWait(self.driver, 2).until( - expected_conditions.element_to_be_clickable( - (By.CSS_SELECTOR, 'button.pickview.%s' % group_acronym) - ) - ) group_button.click() # Check visibility self.assert_agenda_item_visibility() + def test_agenda_view_team_group_filter_toggle(self): + """'Team' group sessions should not respond to area filter button + + Sessions belonging to 'team' groups should not respond to their parent buttons. This prevents, + e.g., 'hackathon', or 'tools' group sessions from being shown/hidden when their parent group + filter button is clicked. + """ + wait = WebDriverWait(self.driver, 10) + meeting = Meeting.objects.get(type_id='ietf') + parent_group = GroupFactory(type_id='area') + other_group = GroupFactory(parent=parent_group, type_id='wg') + hackathon_group = GroupFactory(acronym='hackathon', type_id='team', parent=parent_group) + + # hackathon session + SessionFactory( + meeting=meeting, + type_id='other', + group=hackathon_group, + name='Hackathon', + ) + + # session to cause the parent_group to appear in the filter UI tables + SessionFactory(meeting=meeting, type_id='regular', group=other_group) + + self.login() + url = self.absreverse('ietf.meeting.views.agenda') + self.driver.get(url) + + self.open_agenda_filter_ui(wait) + + self.get_agenda_filter_group_button(wait, 'mars').click() + self.assert_agenda_item_visibility(['mars']) + + # enable hackathon group + group_button = self.get_agenda_filter_group_button(wait, 'hackathon') + group_button.click() + self.assert_agenda_item_visibility(['mars', 'hackathon']) + + # disable hackathon group + group_button.click() + self.assert_agenda_item_visibility(['mars']) + + # clicking area should not show the hackathon + self.get_agenda_filter_group_button(wait, parent_group.acronym).click() + self.assert_agenda_item_visibility(['mars', other_group.acronym]) + def test_agenda_view_group_filter_toggle_without_replace_state(self): """Toggle should function for browsers without window.history.replaceState""" group_acronym = 'mars' diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 749ec8d00..d3d3edc09 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -64,7 +64,7 @@ from ietf.meeting.helpers import get_all_assignments_from_schedule from ietf.meeting.helpers import get_modified_from_assignments from ietf.meeting.helpers import get_wg_list, find_ads_for_meeting from ietf.meeting.helpers import get_meeting, get_ietf_meeting, get_current_ietf_meeting_num -from ietf.meeting.helpers import get_schedule, schedule_permissions +from ietf.meeting.helpers import get_schedule, schedule_permissions, is_regular_agenda_filter_group from ietf.meeting.helpers import preprocess_assignments_for_agenda, read_agenda_file from ietf.meeting.helpers import filter_keywords_for_session, tag_assignments_with_filter_keywords from ietf.meeting.helpers import convert_draft_to_pdf, get_earliest_session_date @@ -1375,7 +1375,7 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc="" groups = [a.session.historic_group for a in filtered_assignments if a.session and a.session.historic_group - and a.session.historic_group.type_id in ('wg', 'rg', 'ag', 'rag', 'iab', 'program') + and is_regular_agenda_filter_group(a.session.historic_group) and a.session.historic_group.historic_parent] group_parents = [] for g in groups: @@ -1467,7 +1467,7 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc="" if len(category) > 0] is_current_meeting = (num is None) or (num == get_current_ietf_meeting_num()) - + rendered_page = render(request, "meeting/"+base+ext, { "schedule": schedule, "filtered_assignments": filtered_assignments, @@ -3377,7 +3377,7 @@ def upcoming(request): # using group / parent instead of historic_group / historic_parent groups = [s.group for s in interim_sessions if s.group - and s.group.type_id in ('wg', 'rg', 'ag', 'rag', 'iab', 'program') + and is_regular_agenda_filter_group(s.group) and s.group.parent] group_parents = {g.parent for g in groups if g.parent} seen = set()