From 4a287d665d6c663a7db5c1ea091783eda1f307fb Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Wed, 3 Mar 2021 17:35:42 +0000 Subject: [PATCH] Move agenda TZ selector out of sidebar so it is always available. Fixes #3172. Commit ready for merge. - Legacy-Id: 18884 --- ietf/meeting/tests_js.py | 103 ++++++++++++++++++++++++- ietf/meeting/tests_views.py | 4 + ietf/static/ietf/js/agenda/timezone.js | 5 +- ietf/templates/meeting/agenda.html | 54 ++++++++++--- 4 files changed, 153 insertions(+), 13 deletions(-) diff --git a/ietf/meeting/tests_js.py b/ietf/meeting/tests_js.py index a407d5db1..5bec75fbb 100644 --- a/ietf/meeting/tests_js.py +++ b/ietf/meeting/tests_js.py @@ -41,7 +41,7 @@ try: from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By - from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support.ui import Select, WebDriverWait from selenium.webdriver.support import expected_conditions from selenium.common.exceptions import NoSuchElementException except ImportError as e: @@ -904,6 +904,107 @@ class AgendaTests(MeetingTestCase): with self.assertRaises(NoSuchElementException): self.driver.find_element_by_xpath('//a[text()="%s"]' % slide.title) + def _wait_for_tz_change_from(self, old_tz): + """Helper to wait for tz displays to change from their old value""" + match = 'text()!="%s"' % old_tz + WebDriverWait(self.driver, 2).until( + expected_conditions.presence_of_element_located((By.XPATH, '//*[@class="current-tz"][%s]' % match)) + ) + + def test_agenda_time_zone_selection(self): + self.assertNotEqual(self.meeting.time_zone, 'UTC', 'Meeting time zone must not be UTC') + + self.driver.get(self.absreverse('ietf.meeting.views.agenda')) + + # wait for the select box to be updated - look for an arbitrary time zone to be in + # its options list to detect this + WebDriverWait(self.driver, 2).until( + expected_conditions.presence_of_element_located((By.XPATH, '//option[@value="America/Halifax"]')) + ) + + tz_select_input = Select(self.driver.find_element_by_id('timezone_select')) + meeting_tz_link = self.driver.find_element_by_id('meeting-timezone') + local_tz_link = self.driver.find_element_by_id('local-timezone') + utc_tz_link = self.driver.find_element_by_id('utc-timezone') + tz_displays = self.driver.find_elements_by_css_selector('.current-tz') + self.assertGreaterEqual(len(tz_displays), 1) + # we'll check that all current-tz elements are updated, but first check that at least one is in the nav sidebar + self.assertIsNotNone(self.driver.find_element_by_css_selector('.nav .current-tz')) + + # Moment.js guesses local time zone based on the behavior of Selenium's web client. This seems + # to inherit Django's settings.TIME_ZONE but I don't know whether that's guaranteed to be consistent. + # To avoid test fragility, ask Moment what it considers local and expect that. + local_tz = self.driver.execute_script('return moment.tz.guess();') + self.assertNotEqual(self.meeting.time_zone, local_tz, 'Meeting time zone must not be local time zone') + self.assertNotEqual(local_tz, 'UTC', 'Local time zone must not be UTC') + + # Should start off in meeting time zone + self.assertEqual(tz_select_input.first_selected_option.get_attribute('value'), self.meeting.time_zone) + for disp in tz_displays: + self.assertEqual(disp.text.strip(), self.meeting.time_zone) + + # Click 'local' button + local_tz_link.click() + self._wait_for_tz_change_from(self.meeting.time_zone) + self.assertEqual(tz_select_input.first_selected_option.get_attribute('value'), local_tz) + for disp in tz_displays: + self.assertEqual(disp.text.strip(), local_tz) + + # click 'utc' button + utc_tz_link.click() + self._wait_for_tz_change_from(local_tz) + self.assertEqual(tz_select_input.first_selected_option.get_attribute('value'), 'UTC') + for disp in tz_displays: + self.assertEqual(disp.text.strip(), 'UTC') + + # click back to meeting + meeting_tz_link.click() + self._wait_for_tz_change_from('UTC') + self.assertEqual(tz_select_input.first_selected_option.get_attribute('value'), self.meeting.time_zone) + for disp in tz_displays: + self.assertEqual(disp.text.strip(), self.meeting.time_zone) + + # and then back to UTC... + utc_tz_link.click() + self._wait_for_tz_change_from(self.meeting.time_zone) + self.assertEqual(tz_select_input.first_selected_option.get_attribute('value'), 'UTC') + for disp in tz_displays: + self.assertEqual(disp.text.strip(), 'UTC') + + # ... and test the switch from UTC to local + local_tz_link.click() + self._wait_for_tz_change_from('UTC') + self.assertEqual(tz_select_input.first_selected_option.get_attribute('value'), local_tz) + for disp in tz_displays: + self.assertEqual(disp.text.strip(), local_tz) + + # Now select a different item from the select input + tz_select_input.select_by_value('America/Halifax') + self._wait_for_tz_change_from(self.meeting.time_zone) + self.assertEqual(tz_select_input.first_selected_option.get_attribute('value'), 'America/Halifax') + for disp in tz_displays: + self.assertEqual(disp.text.strip(), 'America/Halifax') + + def test_agenda_time_zone_selection_updates_weekview(self): + """Changing the time zone should update the weekview to match""" + # enable a filter so the weekview iframe is visible + self.driver.get(self.absreverse('ietf.meeting.views.agenda') + '?show=mars') + # wait for the select box to be updated - look for an arbitrary time zone to be in + # its options list to detect this + WebDriverWait(self.driver, 2).until( + expected_conditions.presence_of_element_located((By.XPATH, '//option[@value="America/Halifax"]')) + ) + + tz_select_input = Select(self.driver.find_element_by_id('timezone_select')) + + # Now select a different item from the select input + tz_select_input.select_by_value('America/Halifax') + self._wait_for_tz_change_from(self.meeting.time_zone) + self.assertEqual(tz_select_input.first_selected_option.get_attribute('value'), 'America/Halifax') + self.driver.switch_to.frame('weekview') + wv_url = self.driver.execute_script('return document.location.href') + self.assertIn('tz=america/halifax', wv_url) + @skipIf(skip_selenium, skip_message) class WeekviewTests(MeetingTestCase): diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 43d71c5f9..1c0db1299 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -143,6 +143,10 @@ class MeetingTests(TestCase): self.assertIn(session.group.parent.acronym.upper(), agenda_content) self.assertIn(slot.location.name, agenda_content) self.assertIn(time_interval, agenda_content) + self.assertIsNotNone(q(':input[value="%s"]' % meeting.time_zone), + 'Time zone selector should show meeting timezone') + self.assertIsNotNone(q('.nav *:contains("%s")' % meeting.time_zone), + 'Time zone indicator should be in nav sidebar') # plain time_interval = "%s-%s" % (slot.time.strftime("%H:%M").lstrip("0"), (slot.time + slot.duration).strftime("%H:%M").lstrip("0")) diff --git a/ietf/static/ietf/js/agenda/timezone.js b/ietf/static/ietf/js/agenda/timezone.js index 22f04175a..61e271e53 100644 --- a/ietf/static/ietf/js/agenda/timezone.js +++ b/ietf/static/ietf/js/agenda/timezone.js @@ -28,8 +28,9 @@ function timezone_init(current) { var tz_names = moment.tz.names(); var select = $('#timezone_select'); + select.empty(); $.each(tz_names, function(i, item) { - if (current == item) { + if (current === item) { select.append($('