diff --git a/server/routes/dev_place/utils.py b/server/routes/dev_place/utils.py index 239e78ccd7..beb4e6640f 100644 --- a/server/routes/dev_place/utils.py +++ b/server/routes/dev_place/utils.py @@ -48,11 +48,12 @@ ] # Place page categories -OVERVIEW_CATEGORY = "Overview" -ORDERED_CATEGORIES = [ - OVERVIEW_CATEGORY, "Economics", "Health", "Equity", "Crime", "Education", - "Demographics", "Housing", "Environment", "Energy" +ORDERED_TOPICS = [ + "Economics", "Health", "Equity", "Crime", "Education", "Demographics", + "Housing", "Environment", "Energy" ] +OVERVIEW_CATEGORY = "Overview" +ORDERED_CATEGORIES = [OVERVIEW_CATEGORY] + ORDERED_TOPICS CATEGORIES = set(ORDERED_CATEGORIES) diff --git a/server/webdriver/base_utils.py b/server/webdriver/base_utils.py index df8ed96137..24a2517dba 100644 --- a/server/webdriver/base_utils.py +++ b/server/webdriver/base_utils.py @@ -13,11 +13,16 @@ # limitations under the License. """Utilities used by the base webddriver test.""" +from typing import List + from selenium import webdriver from selenium.webdriver.chrome.options import Options +from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait +from server.webdriver import shared + DEFAULT_HEIGHT = 1200 DEFAULT_WIDTH = 1200 @@ -37,29 +42,81 @@ def create_driver(preferences=None): return driver -def find_elem(parent, by: str, value: str): +def find_parents(parents, + by: str = By.CLASS_NAME, + parent_path: List[str] = None + ) -> list[webdriver.remote.webelement.WebElement]: """ - Finds an element within the parent element with the specified by string and value. - Returns None if not found. + Returns the final list of elements matching the 'by' in parent_path, waits for elements if needed. + Note that we only return the elements matching all the way to the last parent_path value. + For example: +
+
+
+
+
+
+
+
+ For find_parents(driver, By.ID, ['block', 'chart']) --> returns all 4 chart elements within the blocks. + """ + if not parent_path: + return parents + + elements_to_return = [] + for value in parent_path: + this_level_elements = [] + for par in parents: + this_level_elements.extend(find_elems(par, by, value)) + elements_to_return = this_level_elements + + return elements_to_return + + +def find_elems( + parent: webdriver.remote.webelement.WebElement, + by: str = By.CLASS_NAME, + value: str = "", + path_to_elem: List[str] = None +) -> list[webdriver.remote.webelement.WebElement]: """ - try: - return parent.find_element(by, value) - except: - return None + Finds elements within the parent elements with the specified by string and value. + If not found, it will wait up to the timeout set, and then return None. + """ + parents = find_parents([parent], by, + path_to_elem) if path_to_elem else [parent] + elements = [] + for par in parents: + wait_elem(par, by, value, shared.TIMEOUT) + found_elements = par.find_elements(by, value) + if found_elements: + elements.extend(found_elements) + else: + elems_or_none = wait_elem(par, by, value, shared.TIMEOUT) + if elems_or_none: + elements.append(elems_or_none) + return elements if elements else [] -def find_elems(parent, by: str, value: str): + +def find_elem( + parent: webdriver.remote.webelement.WebElement, + by: str = By.CLASS_NAME, + value: str = "", + path_to_elem: List[str] = None +) -> webdriver.remote.webelement.WebElement | None: """ - Finds elements within the parent element with the specified by string and value. - Returns None if not found. + Finds an element within the parent element with the specified by string and value. + If not found, it will wait up to the timeout set, and then return None. """ - try: - return parent.find_elements(by, value) - except: - return None + elems = find_elems(parent, by, value, path_to_elem) + return elems[0] if elems else None -def wait_elem(driver, by: str, value: str, timeout_seconds: float = 5): +def wait_elem(driver, + by: str = By.CLASS_NAME, + value: str = "", + timeout_seconds: float = 5): """ Waits for an element within the parent element with the specified by string and value. Uses a default timeout of 5 seconds. diff --git a/server/webdriver/shared_tests/browser_test.py b/server/webdriver/shared_tests/browser_test.py index 6035d4ba5b..5550a860a6 100644 --- a/server/webdriver/shared_tests/browser_test.py +++ b/server/webdriver/shared_tests/browser_test.py @@ -17,6 +17,8 @@ from selenium.webdriver.support.ui import WebDriverWait from server.webdriver import shared +from server.webdriver.base_utils import find_elem +from server.webdriver.base_utils import find_elems MTV_URL = '/browser/geoId/0649670' CA_POPULATION_URL = '/browser/geoId/06?statVar=Count_Person' @@ -44,23 +46,16 @@ def test_page_landing(self): self.assertIn(title_text, self.driver.title) # Wait for title to be present - title_locator = (By.TAG_NAME, 'h1') - WebDriverWait(self.driver, self.TIMEOUT_SEC).until( - EC.text_to_be_present_in_element(title_locator, 'Knowledge Graph')) - title_element = self.driver.find_element(*title_locator) self.assertEqual( - "Knowledge Graph", title_element.text, - f"Expected title 'Knowledge Graph', but found: {title_element.text}") + find_elem(self.driver, by=By.TAG_NAME, value='h1').text, + "Knowledge Graph") # Assert intro is correct - description_locator = ( - By.XPATH, "//h1[text()='Knowledge Graph']/following-sibling::p") - description_element = self.driver.find_element(*description_locator) - expected_description_start = 'The Data Commons Knowledge Graph is constructed' self.assertTrue( - description_element.text.startswith(expected_description_start), - f"Intro text does not start with expected text. Found: {description_element.text}" - ) + find_elem(self.driver, + by=By.XPATH, + value="//h1[text()='Knowledge Graph']/following-sibling::p"). + text.startswith("The Data Commons Knowledge Graph is constructed")) def test_page_serve_ca_population(self): """Test the browser page for California population can be loaded successfully.""" @@ -81,36 +76,32 @@ def test_page_serve_ca_population(self): self.assertEqual(title_text, self.driver.title) # Assert header is correct. - element_present = EC.presence_of_element_located((By.TAG_NAME, 'h1')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - statvar_title = self.driver.find_element(By.XPATH, '//*[@id="node"]/h1[1]') - self.assertEqual(statvar_title.text, 'Statistical Variable: Count_Person') - about_title = self.driver.find_element(By.XPATH, '//*[@id="node"]/h1[2]') - self.assertEqual(about_title.text, 'About: California') + node = find_elem(self.driver, by=By.XPATH, value='//*[@id="node"]') + self.assertEqual( + find_elem(node, by=By.XPATH, value='.//h1[1]').text, + 'Statistical Variable: Count_Person') + self.assertEqual( + find_elem(node, by=By.XPATH, value='.//h1[2]').text, + 'About: California') # Assert properties section shows dcid and typeOf values for the statistical variable # Count_Person. - element_present = EC.presence_of_element_located( - (By.XPATH, '//*[@id="node-content"]/div[1]/div/table')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - table = self.driver.find_element( - By.XPATH, '//*[@id="node-content"]/div[1]/div/table') - dcid_row = table.find_elements(By.XPATH, './/tbody/tr[2]/td') + table = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="node-content"]/div[1]/div/table') + dcid_row = find_elems(table, by=By.XPATH, value='.//tbody/tr[2]/td') self.assertEqual(dcid_row[0].text, 'dcid') self.assertEqual(dcid_row[1].text, 'Count_Person') - type_of_row = table.find_elements(By.XPATH, './/tbody/tr[3]/td') + type_of_row = find_elems(table, by=By.XPATH, value='.//tbody/tr[3]/td') self.assertEqual(type_of_row[0].text, 'typeOf') self.assertEqual(type_of_row[1].text, 'StatisticalVariable') self.assertEqual(type_of_row[2].text, 'datacommons.org') # Assert observation charts loaded. - element_present = EC.presence_of_element_located( - (By.CLASS_NAME, 'observation-chart')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - observations_section = self.driver.find_element( - By.XPATH, '//*[@id="node-content"]/div[2]') - observations = observations_section.find_elements(By.CLASS_NAME, 'card') - self.assertTrue(len(observations) > 0) + observations_section = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="node-content"]/div[2]') + self.assertGreater(len(find_elems(observations_section, value='card')), 0) def test_page_serve_austrobaileya(self): """Test the browser page for Austrobaileya scandens can be loaded successfully.""" diff --git a/server/webdriver/tests/browser_test.py b/server/webdriver/tests/browser_test.py index 7339522496..fdab4401b2 100644 --- a/server/webdriver/tests/browser_test.py +++ b/server/webdriver/tests/browser_test.py @@ -21,6 +21,7 @@ from selenium.webdriver.support.ui import WebDriverWait from server.webdriver.base_dc_webdriver import BaseDcWebdriverTest +from server.webdriver.base_utils import find_elem import server.webdriver.shared as shared from server.webdriver.shared_tests.browser_test import BrowserTestMixin @@ -107,22 +108,23 @@ def test_observation_table_redirect(self): self.driver.get(self.url_ + CA_POPULATION_URL) # Wait for observation charts to be loaded. - element_present = EC.presence_of_element_located( - (By.CLASS_NAME, 'observation-chart')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - observations_section = self.driver.find_element( - By.XPATH, '//*[@id="node-content"]/div[2]') + self.assertIsNotNone(find_elem(self.driver, value='observation-chart')) + observations_section = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="node-content"]/div[2]') # Switch to table view for the first chart - observation_section_chart_1 = observations_section.find_elements( - By.CLASS_NAME, 'card')[0] - table_view_button = observation_section_chart_1.find_element( - By.TAG_NAME, 'button') + observation_section_chart_1 = find_elem(observations_section, value='card') + table_view_button = find_elem(observation_section_chart_1, + by=By.TAG_NAME, + value='button') table_view_button.click() # Click the first row in the table view to open the browser page for that observation - table = observation_section_chart_1.find_element(By.TAG_NAME, 'table') - first_row = table.find_element(By.XPATH, './/tbody/tr[2]/td') + table = find_elem(observation_section_chart_1, + by=By.TAG_NAME, + value='table') + first_row = find_elem(table, by=By.XPATH, value='.//tbody/tr[2]/td') first_row.click() # Wait for the new page to open in a new tab @@ -140,32 +142,33 @@ def test_observation_table_redirect(self): self.assertEqual(new_page_title, self.driver.title) # Assert header of the new page is correct. - element_present = EC.presence_of_element_located((By.TAG_NAME, 'h1')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - about_title = self.driver.find_element(By.XPATH, '//*[@id="node"]/h1') - self.assertEqual(about_title.text, 'About: dc/o/y54f4zvqrzf67') - dcid_subtitle = self.driver.find_element(By.XPATH, '//*[@id="node"]/h2[1]') - self.assertEqual(dcid_subtitle.text, 'dcid: dc/o/y54f4zvqrzf67') - typeOf_subtitle = self.driver.find_element(By.XPATH, - '//*[@id="node"]/h2[2]') - self.assertEqual(typeOf_subtitle.text, 'typeOf: StatVarObservation') + node = find_elem(self.driver, by=By.XPATH, value='//*[@id="node"]') + self.assertEqual( + find_elem(node, by=By.XPATH, value='.//h1').text, + 'About: dc/o/y54f4zvqrzf67') # about title. + self.assertEqual( + find_elem(node, by=By.XPATH, value='.//h2[1]').text, + 'dcid: dc/o/y54f4zvqrzf67') # dcid subtitle + self.assertEqual( + find_elem(node, by=By.XPATH, value='.//h2[2]').text, + 'typeOf: StatVarObservation') # typeOf_subtitle def test_observation_chart_redirect(self): """Test that the observation chart observation node links can redirect properly""" # Load California population browser page. self.driver.get(self.url_ + CA_POPULATION_URL) - element_present = EC.presence_of_element_located( - (By.XPATH, '//*[@id="node-content"]/div[1]/div/table')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) + self.assertIsNotNone( + find_elem(self.driver, + by=By.XPATH, + value='//*[@id="node-content"]/div[1]/div/table')) # Click the point on the chart for the year 1850 - element_present = EC.presence_of_element_located((By.XPATH, ( - '//*[@id="node-content"]/div[2]/div/div[1]/div[2]/div/div[2]/div/*[name()="svg"]/' - + '*[name()="g"][4]/*[name()="g"]/*[name()="circle"][1]'))) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - point = self.driver.find_element(By.XPATH, ( + point = find_elem( + self.driver, + by=By.XPATH, + value= '//*[@id="node-content"]/div[2]/div/div[1]/div[2]/div/div[2]/div/*[name()="svg"]/' - + '*[name()="g"][4]/*[name()="g"]/*[name()="circle"][1]')) + + '*[name()="g"][4]/*[name()="g"]/*[name()="circle"][1]') point.click() # Wait for the new page to open in a new tab @@ -183,12 +186,13 @@ def test_observation_chart_redirect(self): self.assertEqual(new_page_title, self.driver.title) # Assert header of the new page is correct. - element_present = EC.presence_of_element_located((By.TAG_NAME, 'h1')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - about_title = self.driver.find_element(By.XPATH, '//*[@id="node"]/h1') - self.assertEqual(about_title.text, 'About: dc/o/y54f4zvqrzf67') - dcid_subtitle = self.driver.find_element(By.XPATH, '//*[@id="node"]/h2[1]') - self.assertEqual(dcid_subtitle.text, 'dcid: dc/o/y54f4zvqrzf67') - typeOf_subtitle = self.driver.find_element(By.XPATH, - '//*[@id="node"]/h2[2]') - self.assertEqual(typeOf_subtitle.text, 'typeOf: StatVarObservation') + node = find_elem(self.driver, by=By.XPATH, value='//*[@id="node"]') + self.assertEqual( + find_elem(node, by=By.XPATH, value='.//h1').text, + 'About: dc/o/y54f4zvqrzf67') # about title. + self.assertEqual( + find_elem(node, by=By.XPATH, value='.//h2[1]').text, + 'dcid: dc/o/y54f4zvqrzf67') # dcid subtitle + self.assertEqual( + find_elem(node, by=By.XPATH, value='.//h2[2]').text, + 'typeOf: StatVarObservation') # typeOf_subtitle diff --git a/server/webdriver/tests/disaster_page_test.py b/server/webdriver/tests/disaster_page_test.py index 7216e7a9a0..c0309cf228 100644 --- a/server/webdriver/tests/disaster_page_test.py +++ b/server/webdriver/tests/disaster_page_test.py @@ -19,6 +19,9 @@ from selenium.webdriver.support.ui import WebDriverWait from server.webdriver.base import WebdriverBaseTest +from server.webdriver.base_utils import find_elem +from server.webdriver.base_utils import find_elems +from server.webdriver.base_utils import wait_elem class TestCharts(WebdriverBaseTest): @@ -45,26 +48,23 @@ def test_server_and_page(self): EC.title_contains('Disasters Dashboard')) # Wait until the group of charts has loaded. - element_present = EC.presence_of_element_located( - (By.ID, 'subject-page-main-pane')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) + self.assertIsNotNone( + wait_elem(self.driver, by=By.ID, value='subject-page-main-pane')) # Store a list of all the charts. - event_maps = self.driver.find_elements(By.CLASS_NAME, - 'disaster-event-map-tile') - # Assert there are 5+ maps. + event_maps = find_elems(self.driver, value='disaster-event-map-tile') self.assertGreater(len(event_maps), 5) # Wait until the svg loads in the first article. - WebDriverWait(self.driver, self.TIMEOUT_SEC).until( - lambda d: event_maps[0].find_element(By.TAG_NAME, 'svg')) + self.assertIsNotNone(find_elem(event_maps[0], by=By.TAG_NAME, value='svg')) # Assert first article has svg with map geo region. - map_geo_region = event_maps[0].find_element(By.ID, 'map-geo-regions') - path = map_geo_region.find_elements(By.TAG_NAME, 'path') + map_geo_region = find_elem(event_maps[0], by=By.ID, value='map-geo-regions') + self.assertIsNotNone(map_geo_region) + + path = find_elems(map_geo_region, by=By.TAG_NAME, value='path') self.assertEqual(len(path), 1) - # Assert first article has svg with points. - map_points_layers = event_maps[0].find_elements(By.CLASS_NAME, - 'map-points-layer') - self.assertGreater(len(map_points_layers), 2) + # Assert first article has svg with at least 2 points. + self.assertGreater(len(find_elems(event_maps[0], value='map-points-layer')), + 2) diff --git a/server/webdriver/tests/event_page_test.py b/server/webdriver/tests/event_page_test.py index 87b29210e9..3ae812cb5f 100644 --- a/server/webdriver/tests/event_page_test.py +++ b/server/webdriver/tests/event_page_test.py @@ -21,6 +21,8 @@ from selenium.webdriver.support.ui import WebDriverWait from server.webdriver.base_dc_webdriver import BaseDcWebdriverTest +from server.webdriver.base_utils import find_elem +from server.webdriver.base_utils import find_elems BASE_PAGE_URL = '/event/' CYCLONE_NICOLE_DCID = 'cyclone/ibtracs_2022309N16290' @@ -47,57 +49,46 @@ def test_page_cyclone(self): EC.title_contains('Nicole - Event Page - ' + self.dc_title_string)) # Check header section - element_present = EC.presence_of_element_located((By.TAG_NAME, 'h1')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - title = self.driver.find_element(By.XPATH, - '//*[@id="main-pane"]/div[1]/div[1]/h1') - self.assertEqual(title.text, 'Nicole') - dcid_subtitle = self.driver.find_element( - By.XPATH, '//*[@id="main-pane"]/div[1]/div[1]/h3') + div1 = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="main-pane"]/div[1]/div[1]') + self.assertEqual(find_elem(div1, by=By.TAG_NAME, value='h1').text, 'Nicole') self.assertEqual( - dcid_subtitle.text, + find_elem(div1, by=By.TAG_NAME, value='h3').text, 'Cyclone Event in Indian River County, Florida, United States, North America, Earth' ) - # Check google map section - element_present = EC.presence_of_element_located( - (By.CLASS_NAME, 'map-container')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - iframe_list = self.driver.find_elements(By.TAG_NAME, 'iframe') - # assert there is 1 iframe - self.assertEqual(len(iframe_list), 1) + # Check the Google Map section + map_container = find_elem(self.driver, value='map-container') + self.assertEqual( + len(find_elems(map_container, by=By.TAG_NAME, value='iframe')), 1) # Check property values table - element_present = EC.presence_of_element_located( - (By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - table = self.driver.find_element( - By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table') - table_rows = table.find_elements( - By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table/tbody/tr') + table = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="main-pane"]/div[1]/section/div/table') + table_rows = find_elems(table, by=By.XPATH, value='.//tbody/tr') + # assert there are 3+ rows in the property values table self.assertGreater(len(table_rows), 3) - date_row = table.find_elements( - By.XPATH, - '//*[@id="main-pane"]/div[1]/section/div/table/tbody/tr[2]/td') + date_rows = find_elems( + table, + by=By.XPATH, + value='//*[@id="main-pane"]/div[1]/section/div/table/tbody/tr[2]/td') # assert the date is correct - self.assertEqual(date_row[0].text, 'Date') - self.assertEqual(date_row[1].text, + self.assertEqual(date_rows[0].text, 'Date') + self.assertEqual(date_rows[1].text, '2022-11-05T06:00:00 — 2022-11-11T18:00:00') # Check additional charts section - element_present = EC.presence_of_element_located((By.TAG_NAME, 'svg')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - chart_section = self.driver.find_element(By.ID, 'subject-page-main-pane') - charts = chart_section.find_elements(By.CLASS_NAME, 'chart-container') - # assert there are 4+ charts - self.assertGreater(len(charts), 4) + chart_section = find_elem(self.driver, + by=By.ID, + value='subject-page-main-pane') + charts = find_elems(chart_section, value='chart-container') - # assert that the first chart has data - line_present = EC.presence_of_element_located((By.CLASS_NAME, 'line')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(line_present) - chart_lines = charts[0].find_elements(By.CLASS_NAME, 'line') - self.assertEqual(len(chart_lines), 1) + # assert there are 4+ charts, and the first line has data + self.assertGreater(len(charts), 4) + self.assertEqual(len(find_elems(charts[0], value='line')), 1) def test_page_fire(self): """Test a fire event page can be loaded successfully""" @@ -115,60 +106,44 @@ def test_page_fire(self): EC.title_contains('0003 Fire 2015 (2836427)')) # Check header section - element_present = EC.presence_of_element_located((By.TAG_NAME, 'h1')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - title = self.driver.find_element(By.XPATH, - '//*[@id="main-pane"]/div[1]/div[1]/h1') - self.assertEqual(title.text, '0003 Fire 2015 (2836427)') - dcid_subtitle = self.driver.find_element( - By.XPATH, '//*[@id="main-pane"]/div[1]/div[1]/h3') + div1 = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="main-pane"]/div[1]/div[1]') + self.assertEqual( + find_elem(div1, by=By.TAG_NAME, value='h1').text, + '0003 Fire 2015 (2836427)') self.assertEqual( - dcid_subtitle.text, + find_elem(div1, by=By.TAG_NAME, value='h3').text, 'Wildland Fire Event in Deschutes County, Oregon, United States, North America, Earth' ) # Check google map section - element_present = EC.presence_of_element_located( - (By.CLASS_NAME, 'map-container')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - element_present = EC.presence_of_element_located((By.TAG_NAME, 'iframe')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - iframe_list = self.driver.find_elements(By.TAG_NAME, 'iframe') - # assert there is 1 iframe - self.assertEqual(len(iframe_list), 1) + map_container = find_elem(self.driver, value='map-container') + self.assertEqual( + len(find_elems(map_container, by=By.TAG_NAME, value='iframe')), 1) # Check property values table - element_present = EC.presence_of_element_located( - (By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - table = self.driver.find_element( - By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table') - table_rows = table.find_elements( - By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table/tbody/tr') - # assert there are 2+ rows in the property values table - self.assertGreater(len(table_rows), 2) - date_row = table.find_elements( - By.XPATH, - '//*[@id="main-pane"]/div[1]/section/div/table/tbody/tr[2]/td') - # assert the date is correct - self.assertEqual(date_row[0].text, 'Date') - self.assertEqual(date_row[1].text, '2015-01-05') + table = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="main-pane"]/div[1]/section/div/table') + + # assert there are 2+ rows in the property values table and they have the right dates + self.assertGreater(len(find_elems(table, by=By.XPATH, value='.//tbody/tr')), + 2) + date_rows = find_elems(table, by=By.XPATH, value='.//tbody/tr[2]/td') + self.assertEqual(date_rows[0].text, 'Date') + self.assertEqual(date_rows[1].text, '2015-01-05') # Check additional charts section - element_present = EC.presence_of_element_located((By.TAG_NAME, 'svg')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - chart_section = self.driver.find_element(By.ID, 'subject-page-main-pane') - charts = chart_section.find_elements(By.CLASS_NAME, 'chart-container') - # assert there are 4+ charts + chart_section = find_elem(self.driver, + by=By.ID, + value='subject-page-main-pane') + charts = find_elems(chart_section, value='chart-container') + + # assert there are 4+ charts, and the first line has data self.assertGreater(len(charts), 4) - # assert that the first chart has data - line_present = EC.presence_of_element_located((By.CLASS_NAME, 'line')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(line_present) - chart_lines = charts[0].find_elements(By.CLASS_NAME, 'line') - self.assertEqual(len(chart_lines), 1) - - # TODO (boxu): fix the flaky test and reenable it. - @unittest.skip + self.assertEqual(len(find_elems(charts[0], value='line')), 1) + def test_page_drought(self): """Test a drought event page can be loaded successfully""" @@ -186,51 +161,41 @@ def test_page_drought(self): self.dc_title_string)) # Check header section - element_present = EC.presence_of_element_located((By.TAG_NAME, 'h1')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - title = self.driver.find_element(By.XPATH, - '//*[@id="main-pane"]/div[1]/div[1]/h1') - self.assertEqual(title.text, 'stormEvent/nws5512667') - dcid_subtitle = self.driver.find_element( - By.XPATH, '//*[@id="main-pane"]/div[1]/div[1]/h3') + div1 = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="main-pane"]/div[1]/div[1]') + self.assertEqual( + find_elem(div1, by=By.TAG_NAME, value='h1').text, + 'stormEvent/nws5512667') self.assertEqual( - dcid_subtitle.text, + find_elem(div1, by=By.TAG_NAME, value='h3').text, 'Drought Event in Hood County, Texas, United States, North America, Earth' ) # Check google map section - element_present = EC.presence_of_element_located( - (By.CLASS_NAME, 'map-container')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - iframe_list = self.driver.find_elements(By.TAG_NAME, 'iframe') - # assert there is 1 iframe - self.assertEqual(len(iframe_list), 1) + map_container = find_elem(self.driver, value='map-container') + self.assertEqual( + len(find_elems(map_container, by=By.TAG_NAME, value='iframe')), 1) # Check property values table - element_present = EC.presence_of_element_located( - (By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - table = self.driver.find_element( - By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table') - table_rows = table.find_elements( - By.XPATH, '//*[@id="main-pane"]/div[1]/section/div/table/tbody/tr') - # assert there are 3+ rows in the property values table - self.assertGreater(len(table_rows), 2) - date_row = table.find_elements( - By.XPATH, - '//*[@id="main-pane"]/div[1]/section/div/table/tbody/tr[2]/td') - # assert the date is correct - self.assertEqual(date_row[0].text, 'Date') - self.assertEqual(date_row[1].text, + table = find_elem(self.driver, + by=By.XPATH, + value='//*[@id="main-pane"]/div[1]/section/div/table') + + # assert there are 2+ rows in the property values table and they have the right dates + self.assertGreater(len(find_elems(table, by=By.XPATH, value='.//tbody/tr')), + 2) + date_rows = find_elems(table, by=By.XPATH, value='.//tbody/tr[2]/td') + self.assertEqual(date_rows[0].text, 'Date') + self.assertEqual(date_rows[1].text, '2006-05-01T00:00:00-05:00 — 2006-05-08T23:59:00-05:00') # Check additional charts section - element_present = EC.presence_of_element_located((By.TAG_NAME, 'svg')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(element_present) - chart_section = self.driver.find_element(By.ID, 'subject-page-main-pane') - charts = chart_section.find_elements(By.CLASS_NAME, 'chart-container') - # assert there are 5+ charts + chart_section = find_elem(self.driver, + by=By.ID, + value='subject-page-main-pane') + charts = find_elems(chart_section, value='chart-container') + + # assert there are 4+ charts, and the first line has data self.assertGreater(len(charts), 5) - # assert that the first chart has data - chart_lines = charts[0].find_elements(By.CLASS_NAME, 'line') - self.assertEqual(len(chart_lines), 1) + self.assertEqual(len(find_elems(charts[0], value='line')), 1) diff --git a/server/webdriver/tests/homepage_test.py b/server/webdriver/tests/homepage_test.py index fc5de509cf..d4073a866e 100644 --- a/server/webdriver/tests/homepage_test.py +++ b/server/webdriver/tests/homepage_test.py @@ -17,6 +17,8 @@ from selenium.webdriver.support.ui import WebDriverWait from server.webdriver.base_dc_webdriver import BaseDcWebdriverTest +from server.webdriver.base_utils import find_elem +from server.webdriver.base_utils import find_elems from server.webdriver.shared_tests.homepage_test import HomepageTestMixin @@ -28,13 +30,12 @@ def test_homepage_en_by_css(self): self.driver.get(self.url_ + '/') - title_present = EC.text_to_be_present_in_element( - (By.CSS_SELECTOR, '.navbar-brand'), self.dc_title_string) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(title_present) + # Assert page title is correct + WebDriverWait(self.driver, self.TIMEOUT_SEC).until( + EC.title_contains(self.dc_title_string)) - hero_msg = self.driver.find_elements(By.ID, 'hero')[0] self.assertTrue( - hero_msg.text.startswith( + find_elem(self.driver, by=By.ID, value='hero').text.startswith( "Data Commons brings together the world's public data, making it simple to explore" )) @@ -43,13 +44,12 @@ def test_homepage_it(self): self.driver.get(self.url_ + '/?hl=it') - title_present = EC.text_to_be_present_in_element( - (By.CSS_SELECTOR, '.navbar-brand'), self.dc_title_string) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(title_present) + # Assert page title is correct + WebDriverWait(self.driver, self.TIMEOUT_SEC).until( + EC.title_contains(self.dc_title_string)) - hero_msg = self.driver.find_elements(By.ID, 'hero')[0] self.assertTrue( - hero_msg.text.startswith( + find_elem(self.driver, by=By.ID, value='hero').text.startswith( "Data Commons brings together the world's public data, making it simple to explore" )) @@ -100,19 +100,15 @@ def test_homepage_autocomplete(self): self.driver.get(self.url_ + '/?ac_on=true') - title_present = EC.text_to_be_present_in_element( - (By.CSS_SELECTOR, '.navbar-brand'), self.dc_title_string) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(title_present) - - search_box_input = self.driver.find_element(By.ID, 'query-search-input') + # Assert page title is correct + WebDriverWait(self.driver, self.TIMEOUT_SEC).until( + EC.title_contains(self.dc_title_string)) # Type california into the search box. + search_box_input = find_elem(self.driver, + by=By.ID, + value='query-search-input') search_box_input.send_keys("California") - suggestions_present = EC.presence_of_element_located( - (By.CLASS_NAME, 'search-input-result-section')) - WebDriverWait(self.driver, 300).until(suggestions_present) - - autocomplete_results = self.driver.find_elements( - By.CLASS_NAME, 'search-input-result-section') - self.assertTrue(len(autocomplete_results) == 5) + self.assertEqual( + len(find_elems(self.driver, value='search-input-result-section')), 5) diff --git a/server/webdriver/tests/place_explorer_i18n_test.py b/server/webdriver/tests/place_explorer_i18n_test.py index e5aa9997d7..4800836e64 100644 --- a/server/webdriver/tests/place_explorer_i18n_test.py +++ b/server/webdriver/tests/place_explorer_i18n_test.py @@ -18,6 +18,7 @@ from server.webdriver import shared from server.webdriver.base_dc_webdriver import BaseDcWebdriverTest +from server.webdriver.base_utils import find_elem from server.webdriver.shared_tests.place_explorer_i18n_test import \ PlaceI18nExplorerTestMixin @@ -41,9 +42,7 @@ def test_explorer_redirect_place_explorer_populates_search_bar(self): shared.wait_for_loading(self.driver) # Ensure the query string is set in the NL Search Bar. - search_bar_present = EC.presence_of_element_located( - (By.ID, 'query-search-input')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(search_bar_present) - search_bar = self.driver.find_element(By.ID, 'query-search-input') - self.assertEqual(search_bar.get_attribute('value'), - 'United States Of America') + self.assertEqual( + find_elem(self.driver, by=By.ID, + value='query-search-input').get_attribute('value'), + 'United States Of America') diff --git a/server/webdriver/tests/place_explorer_test.py b/server/webdriver/tests/place_explorer_test.py index 9c04d82db7..0b11640caa 100644 --- a/server/webdriver/tests/place_explorer_test.py +++ b/server/webdriver/tests/place_explorer_test.py @@ -17,9 +17,11 @@ from selenium.webdriver.support.ui import WebDriverWait from server.routes.dev_place.utils import ORDERED_CATEGORIES -from server.webdriver import base_utils +from server.routes.dev_place.utils import ORDERED_TOPICS from server.webdriver import shared from server.webdriver.base_dc_webdriver import BaseDcWebdriverTest +from server.webdriver.base_utils import find_elem +from server.webdriver.base_utils import find_elems from server.webdriver.shared_tests.place_explorer_test import \ PlaceExplorerTestMixin @@ -31,39 +33,64 @@ def test_dev_place_overview_california(self): """Ensure experimental dev place page content loads""" self.driver.get(self.url_ + '/place/geoId/06?force_dev_places=true') - expected_topics = ORDERED_CATEGORIES + # Assert the subheader contains the parent places. + self.assertIsNotNone(find_elem(self.driver, value='place-info')) + self.assertEqual( + find_elem(self.driver, value='subheader').text, + 'State in United States of America, North America') + + # Asert the related places box exists + self.assertEqual( + find_elem(self.driver, value='related-places-callout').text, + 'Places in California') + + # Assert the overview exists, has a summary and a map. + self.assertNotEqual(len(find_elem(self.driver, value='place-summary').text), + "") + self.assertIsNotNone(find_elem(self.driver, value='map-container')) + + # Assert the key demographics table has data + self.assertEqual( + len( + find_elems(self.driver, + value='key-demographics-row', + path_to_elem=['key-demographics-table'])), 5) + shared.assert_topics(self, self.driver, path_to_topics=['explore-topics-box'], classname='item-list-item', - expected_topics=expected_topics) + expected_topics=ORDERED_CATEGORIES) - # Assert the subheader contains the parent places. - place_subheader_callout_el = base_utils.wait_elem(self.driver, - By.CLASS_NAME, - 'subheader', - self.TIMEOUT_SEC) - self.assertEqual(place_subheader_callout_el.text, - 'State in United States of America, North America') - - # For the dev place page, the related places callout is under the - # .related-places-callout div. - related_places_callout_el = base_utils.wait_elem(self.driver, By.CLASS_NAME, - 'related-places-callout', - self.TIMEOUT_SEC) - self.assertEqual(related_places_callout_el.text, 'Places in California') - - # Assert the "Download" link is present in charts - download_link_el = base_utils.wait_elem(self.driver, By.CLASS_NAME, - 'download-outlink', - self.TIMEOUT_SEC) - self.assertTrue('Download' in download_link_el.text) - - # Assert the "Explore in ... Tool" link is present in charts - explore_in_link_el = base_utils.wait_elem(self.driver, By.CLASS_NAME, - 'explore-in-outlink', - self.TIMEOUT_SEC) - self.assertTrue('Explore in' in explore_in_link_el.text) + # And that the categories have data in the overview + block_titles = find_elems(self.driver, value='block-title') + self.assertEqual(set([block.text for block in block_titles]), + set(ORDERED_TOPICS)) + + # Assert that every category is expected, and has at least one chart + category_containers = find_elems(self.driver, + value='category', + path_to_elem=['charts-container']) + self.assertEqual(len(category_containers), len(ORDERED_TOPICS)) + for category_container in category_containers: + chart_containers = find_elems(category_container, value='chart-container') + self.assertGreater(len(chart_containers), 0) + + def test_dev_place_chart_settings(self): + """Ensure the charts in the new place page contain the expected settings""" + self.driver.get(self.url_ + '/place/geoId/06?force_dev_places=true') + + self.assertTrue( + find_elem(self.driver, + value='download-outlink', + path_to_elem=['charts-container']).text, 'Download') + + self.assertTrue( + find_elem(self.driver, + value='explore-in-outlink', + path_to_elem=['charts-container']).text, + 'Explore in Timeline tool', + ) def test_explorer_redirect_place_explorer_populates_search_bar(self): """Test the redirection from explore to place explore for single place queries populates the search bar from the URL query""" @@ -81,9 +108,7 @@ def test_explorer_redirect_place_explorer_populates_search_bar(self): shared.wait_for_loading(self.driver) # Ensure the query string is set in the NL Search Bar. - search_bar_present = EC.presence_of_element_located( - (By.ID, 'query-search-input')) - WebDriverWait(self.driver, self.TIMEOUT_SEC).until(search_bar_present) - search_bar = self.driver.find_element(By.ID, 'query-search-input') - self.assertEqual(search_bar.get_attribute('value'), - 'United States Of America') + self.assertEqual( + find_elem(self.driver, by=By.ID, + value='query-search-input').get_attribute('value'), + 'United States Of America') diff --git a/static/js/place/dev_place_main.tsx b/static/js/place/dev_place_main.tsx index c006ed220b..5f75476021 100644 --- a/static/js/place/dev_place_main.tsx +++ b/static/js/place/dev_place_main.tsx @@ -224,7 +224,7 @@ const PlaceOverviewTable = (props: { }); return ( - +
+
@@ -241,7 +241,7 @@ const PlaceOverviewTable = (props: { const formattedObservationValue = dataRow.variable.observation.value.toLocaleString(); return ( -
{dataRow.variable.properties.name} {formattedObservationValue} {unit} (