From 276c2da873a1ef331cab1f29bdf617c131cc736d Mon Sep 17 00:00:00 2001 From: Ada Werefox Date: Fri, 27 Jan 2023 01:36:12 +0000 Subject: [PATCH] Added validation for root domain tests, refactored some code to be more modular. --- run_tests.sh | 7 ++- src/info/data/homepage/subdomains.yml | 2 +- tests/docker-compose.yml | 1 + tests/requirements.txt | 3 +- tests/test_suite/footer_test.py | 22 +++++--- tests/test_suite/root_domain_test.py | 63 +++++---------------- tests/test_suite/shared_methods.py | 77 ++++++++++++++++++++++++++ tests/test_suite/shared_vars.py | 20 +++++++ tests/test_suite/webdriver_methods.py | 11 ++++ tests/test_suite/werefox_cafe.resource | 11 +--- tests/test_suite/werefox_cafe.robot | 5 +- 11 files changed, 152 insertions(+), 70 deletions(-) create mode 100755 tests/test_suite/shared_methods.py create mode 100755 tests/test_suite/shared_vars.py create mode 100755 tests/test_suite/webdriver_methods.py diff --git a/run_tests.sh b/run_tests.sh index eebb565..c36160d 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -7,7 +7,12 @@ MODE=$1 if [ "$MODE" == "--debug-server" ] || [ "$MODE" == "-s" ]; then docker run --rm --name selenium-debug-server -p "4444:4444" -p "7900:7900" -e SE_OPTS="--allow-cors true" --shm-size="2g" selenium/standalone-chrome:108.0 elif [ "$MODE" == "--debug-node" ] || [ "$MODE" == "-n" ]; then - docker run --rm --name selenium-debug-node -e "PYTHONPYCACHEPREFIX=/dev/null/" -v $(pwd)/tests/test_suite:/tests -v $(pwd)/tests/output:/output selenium-node:latest robot -d /output /tests/ + docker run --rm --name selenium-debug-node \ + -e "PYTHONPYCACHEPREFIX=/dev/null/" \ + -v $(pwd)/tests/test_suite:/tests \ + -v $(pwd)/tests/output:/output \ + -v $(pwd)/src/info/data:/data \ + selenium-node:latest robot -d /output /tests/ else cd tests/ diff --git a/src/info/data/homepage/subdomains.yml b/src/info/data/homepage/subdomains.yml index eb8ed80..e6e8a3a 100755 --- a/src/info/data/homepage/subdomains.yml +++ b/src/info/data/homepage/subdomains.yml @@ -7,7 +7,7 @@ new_tab: true Mastodon: - url: "https://masto.werefox.cafe" + url: "https://masto.werefox.cafe/about" images: - { src: "/emoji/mastodon-logo.png", alt: "Mastodon logo" } new_tab: true diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index e86f95f..93f0957 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -28,5 +28,6 @@ services: volumes: - ./test_suite:/tests:ro - ./output:/output:rw + - ../data:/data:ro user: "1000:1000" command: 'python3 -m robot -d /output /tests' diff --git a/tests/requirements.txt b/tests/requirements.txt index 5831d39..09733db 100755 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,2 +1,3 @@ selenium>=4.7.2 -robotframework>=6.0.0 \ No newline at end of file +robotframework>=6.0.0 +pyyaml>-5.3.0 \ No newline at end of file diff --git a/tests/test_suite/footer_test.py b/tests/test_suite/footer_test.py index 16cf05e..693a7f6 100755 --- a/tests/test_suite/footer_test.py +++ b/tests/test_suite/footer_test.py @@ -7,13 +7,8 @@ from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions from robot.api.logger import info, debug, trace, console, error - -def check_footer_links(driver): - # setup wait and grab original tab/window - wait = WebDriverWait(driver, 10) - main_tab = driver.current_window_handle - - # Try to grab button elements of maintained subdomains +def grab_button_elements(driver): + # Try to grab button elements of the footer try: footer_element = driver.find_element(By.TAG_NAME, "footer") sites = footer_element.find_elements( @@ -22,7 +17,16 @@ def check_footer_links(driver): error("Couldn't find the element.") driver.close() driver.quit() - return False + return {} + + return sites + +def check_footer_links(driver): + # setup wait and grab original tab/window + wait = WebDriverWait(driver, 10) + main_tab = driver.current_window_handle + + sites = grab_button_elements(driver) # Iterate through subdomains for e in sites: @@ -41,4 +45,4 @@ def check_footer_links(driver): driver.quit() return False - return True \ No newline at end of file + return True diff --git a/tests/test_suite/root_domain_test.py b/tests/test_suite/root_domain_test.py index 920955e..68ca46c 100644 --- a/tests/test_suite/root_domain_test.py +++ b/tests/test_suite/root_domain_test.py @@ -1,79 +1,44 @@ #!/usr/bin/python # Necessary imports -from selenium import webdriver from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions -from robot.api.logger import info, debug, trace, console, error +from robot.api.logger import info, error from footer_test import check_footer_links +from shared_methods import load_data, check_buttons -def check_subdomains(driver): - # setup wait and grab original tab/window - wait = WebDriverWait(driver, 10) - main_tab = driver.current_window_handle +def grab_button_elements(driver): # Try to grab button elements of maintained subdomains try: site_lists = driver.find_elements( By.TAG_NAME, "nav") + info(site_lists) sites = [] for l in site_lists: sites += l.find_elements(By.XPATH, ".//a") except: error("Couldn't find the element.") - driver.close() - driver.quit() - return False + return [] - # Iterate through subdomains - for e in sites: - try: - # link_element = e.find_element(By.XPATH, "./a") - e.click() - info(e.text) - wait.until(expected_conditions.number_of_windows_to_be(2)) - for window_handle in driver.window_handles: - if window_handle != main_tab: - driver.switch_to.window(window_handle) - driver.close() - driver.switch_to.window(main_tab) - except: - error("Couldn't find the element somewhere...") - driver.close() - driver.quit() - return False - - return True - - -def setup_webdriver(remote_url): - # Set up webdriver and necessary variables for later - chrome_options = webdriver.ChromeOptions() - info('Attempting to establish connection to remote webdriver...') - driver = webdriver.Remote( - command_executor=remote_url, options=chrome_options) - info('Connection established.') - return driver - - -def teardown_webdriver(driver): - # Close browser and lean up - driver.close() - driver.quit() + return sites def execute_tests(driver, site_url): + filepaths = ['/data/homepage/subdomains.yml', '/data/homepage/other.yml'] + data = load_data(filepaths) + # Load requested site info('Attempting to get page...') driver.get(site_url) info('Page loaded.') - # Check all the buttons work + # A little bit of setup, grabbing the button elements + button_elements = grab_button_elements(driver) + info('Attempting to click through subdomain buttons...') - # Check the subdomain buttons - if (not check_subdomains(driver)): + # Check all the buttons work + if (not check_buttons(driver, data, button_elements)): info('Test failed.') return False # Check the footer buttons diff --git a/tests/test_suite/shared_methods.py b/tests/test_suite/shared_methods.py new file mode 100755 index 0000000..8c2c675 --- /dev/null +++ b/tests/test_suite/shared_methods.py @@ -0,0 +1,77 @@ +#!/usr/bin/python + +# Necessary imports +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions +from robot.api.logger import info, error +from yaml import load, Loader + + +def standardize_url(url): + # Make sure there are no leading or trailing characters so we can check urls are identical + if (len(url) > 1): + if (url[-1:] == '/'): + url = url[:-1] + if (len(url) > 8): + if (url[:8] == 'https://'): + url = url[8:] + if (url[:7] == 'http://'): + url = url[7:] + return url + + +def load_data(filepaths): + # Load the data that *should* be on a templated page + data = {} + for filepath in filepaths: + try: + with open(filepath) as yaml_doc: + data.update(load(yaml_doc, Loader=Loader)) + + with open('/data/homepage/other.yml') as yaml_doc: + data.update(load(yaml_doc, Loader=Loader)) + except: + error("Couldn't open or parse the yaml document.") + return {} + return data + + +def check_buttons(driver, data, button_elements): + # Iterate through buttons based on imported data + wait = WebDriverWait(driver, 10) + main_tab = driver.current_window_handle + for d in data: + try: + try: + url = standardize_url(data[d]['url']) + except: + error(f'Some error in grabbing the url from: {d}') + return False + + try: + element = [e for e in button_elements if e.text == d][0] + info(element.text) + except: + error( + f'Button text does not match data file - data: {d} | elements: {[e.text for e in button_elements]}') + return False + element.click() + wait.until(expected_conditions.number_of_windows_to_be(2)) + for window_handle in driver.window_handles: + if window_handle != main_tab: + driver.switch_to.window(window_handle) + wait.until( + expected_conditions.presence_of_all_elements_located) + if (url != standardize_url(driver.current_url)): + info( + f'Opened URL does not match data file - button_url: #{url}# | current_url: #{standardize_url(driver.current_url)}#') + return False + driver.close() + driver.switch_to.window(main_tab) + except: + error("Couldn't find the element somewhere...") + driver.close() + driver.quit() + return False + + return True diff --git a/tests/test_suite/shared_vars.py b/tests/test_suite/shared_vars.py new file mode 100755 index 0000000..c5dcb7e --- /dev/null +++ b/tests/test_suite/shared_vars.py @@ -0,0 +1,20 @@ +#!/usr/bin/python + +# Necessary imports +from selenium import webdriver +from robot.api.logger import info + + +def setup_webdriver(remote_url): + # Set up webdriver and necessary variables for later + chrome_options = webdriver.ChromeOptions() + info('Attempting to establish connection to remote webdriver...') + # driver = webdriver.Remote( + # command_executor=remote_url, options=chrome_options) + # info('Connection established.') + return webdriver.Remote(command_executor=remote_url, options=chrome_options) + + +def get_variables(url): + var = {"DRIVER": setup_webdriver(url)} + return var diff --git a/tests/test_suite/webdriver_methods.py b/tests/test_suite/webdriver_methods.py new file mode 100755 index 0000000..c9ec2c6 --- /dev/null +++ b/tests/test_suite/webdriver_methods.py @@ -0,0 +1,11 @@ +#!/usr/bin/python + +# Necessary imports +from selenium import webdriver +from robot.api.logger import info + + +def teardown_webdriver(driver): + # Close browser and lean up + driver.close() + driver.quit() diff --git a/tests/test_suite/werefox_cafe.resource b/tests/test_suite/werefox_cafe.resource index b7faaac..0ad7194 100755 --- a/tests/test_suite/werefox_cafe.resource +++ b/tests/test_suite/werefox_cafe.resource @@ -1,19 +1,14 @@ *** Settings *** Documentation Import Python functions -Library ./root_domain_test.py +Library root_domain_test.py +Library shared_methods.py *** Keywords *** -# My Keyword [Arguments] ${path} -# Directory Should Exist ${path} Werefox Cafe Test Cases - [Arguments] ${remote_url} ${site_url} - - ${driver}= Setup Webdriver ${remote_url} + [Arguments] ${site_url} ${result}= Execute Tests ${driver} ${site_url} Should Be True ${result} - - [Teardown] Teardown Webdriver ${driver} diff --git a/tests/test_suite/werefox_cafe.robot b/tests/test_suite/werefox_cafe.robot index 71e97d8..6ce5792 100755 --- a/tests/test_suite/werefox_cafe.robot +++ b/tests/test_suite/werefox_cafe.robot @@ -2,6 +2,8 @@ Documentation Validate functionality of root domain site. Resource werefox_cafe.resource +Library webdriver_methods.py +Variables shared_vars.py ${remote_url} Default Tags positive @@ -13,4 +15,5 @@ ${site_url} https://werefox.cafe *** Test Cases *** Test Werefox Cafe [Documentation] Run Werefox Cafe Test Cases. - Werefox Cafe Test Cases ${remote_url} ${site_url} + Werefox Cafe Test Cases ${site_url} + [Teardown] Teardown Webdriver ${driver}