| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- import os
- import time
- import unittest
- import pytest
- import requests
- import logging
- from urllib.parse import urljoin
- from selenium import webdriver
- from selenium.webdriver.common.by import By
- from selenium.webdriver.common.keys import Keys
- from selenium.webdriver.chrome.options import Options
- from selenium.webdriver.support.wait import WebDriverWait
- from selenium.webdriver.common import utils
- from selenium.common.exceptions import NoSuchElementException
- logger = logging.getLogger()
- logger.setLevel(logging.INFO)
- @pytest.fixture
- def driver():
- options = Options()
- options.add_argument("--headless")
- options.add_argument("--no-sandbox")
- _driver = webdriver.Chrome(options=options)
- yield _driver
- _driver.quit()
- @pytest.fixture(autouse=True)
- def dashboard_url(dashboard_host, dashboard_port):
- count = 0
- while utils.is_connectable(port=dashboard_port, host=dashboard_host) is False:
- if count == 30:
- raise Exception("Dashboard is not ready")
- count += 1
- time.sleep(1)
- return f"http://{dashboard_host}:{dashboard_port}"
- def login(driver, dashboard_url):
- # admin is set in CI jobs, hence as default value
- password = os.getenv("EMQX_DASHBOARD__DEFAULT_PASSWORD", "admin")
- driver.get(dashboard_url)
- assert "EMQX Dashboard" == driver.title
- assert f"{dashboard_url}/#/login?to=/dashboard/overview" == driver.current_url
- driver.execute_script("window.localStorage.setItem('licenseTipVisible','false');")
- driver.find_element(By.XPATH, "//div[@class='login']//form//input[@type='text']").send_keys("admin")
- driver.find_element(By.XPATH, "//div[@class='login']//form//input[@type='password']").send_keys(password)
- driver.find_element(By.XPATH, "//div[@class='login']//form//button").click()
- dest_url = urljoin(dashboard_url, "/#/dashboard/overview")
- ensure_current_url(driver, dest_url)
- assert len(driver.find_elements(By.XPATH, "//div[@class='login']")) == 0
- logger.info(f"Logged in to {dashboard_url}")
- def ensure_current_url(d, url):
- count = 0
- while url != d.current_url:
- if count == 10:
- raise Exception(f"Failed to load {url}")
- count += 1
- time.sleep(1)
- def title(d):
- title = ''
- for _ in range(5):
- try:
- title = d.find_element("xpath", "//div[@id='app']//h1[@class='header-title']")
- break
- except NoSuchElementException:
- time.sleep(1)
- else:
- raise AssertionError("Cannot find the title element")
- return title
- def wait_title_text(d, text):
- return WebDriverWait(d, 10).until(lambda x: title(x).text == text)
- def test_basic(driver, dashboard_url):
- login(driver, dashboard_url)
- logger.info(f"Current URL: {driver.current_url}")
- wait_title_text(driver, "Cluster Overview")
- def test_log(driver, dashboard_url):
- login(driver, dashboard_url)
- logger.info(f"Current URL: {driver.current_url}")
- dest_url = urljoin(dashboard_url, "/#/log")
- driver.get(dest_url)
- ensure_current_url(driver, dest_url)
- wait_title_text(driver, "Logging")
- label = driver.find_element(By.XPATH, "//div[@id='app']//form//label[contains(., 'Enable Log Handler')]")
- assert driver.find_elements(By.ID, label.get_attribute("for"))
- label = driver.find_element(By.XPATH, "//div[@id='app']//form//label[contains(., 'Log Level')]")
- assert driver.find_elements(By.ID, label.get_attribute("for"))
- label = driver.find_element(By.XPATH, "//div[@id='app']//form//label[contains(., 'Log Formatter')]")
- assert driver.find_elements(By.ID, label.get_attribute("for"))
- label = driver.find_element(By.XPATH, "//div[@id='app']//form//label[contains(., 'Time Offset')]")
- assert driver.find_elements(By.ID, label.get_attribute("for"))
- def fetch_version_info(dashboard_url):
- status_url = urljoin(dashboard_url, "/status?format=json")
- response = requests.get(status_url)
- response.raise_for_status()
- return response.json()
- def parse_version(version_str):
- prefix_major, minor, _ = version_str.split('.', 2)
- prefix = prefix_major[:1]
- major = prefix_major[1:]
- return prefix, major + '.' + minor
- def fetch_version(url):
- info = fetch_version_info(url)
- version_str = info['rel_vsn']
- return parse_version(version_str)
- def test_docs_link(driver, dashboard_url):
- login(driver, dashboard_url)
- logger.info(f"Current URL: {driver.current_url}")
- xpath_link_help = "//div[@id='app']//div[@class='nav-header']//a[contains(@class, 'link-help')]"
- # retry up to 5 times
- for _ in range(5):
- try:
- link_help = driver.find_element(By.XPATH, xpath_link_help)
- break
- except NoSuchElementException:
- time.sleep(1)
- else:
- raise AssertionError("Cannot find the help link")
- driver.execute_script("arguments[0].click();", link_help)
- prefix, emqx_version = fetch_version(dashboard_url)
- # it's v5.x in the url
- emqx_version = 'v' + emqx_version
- docs_base_url = "https://docs.emqx.com/en/emqx"
- docs_url = f"{docs_base_url}/{emqx_version}"
- xpath = f"//div[@id='app']//div[@class='nav-header']//a[@href[starts-with(.,'{docs_url}')]]"
- try:
- driver.find_element(By.XPATH, xpath)
- except NoSuchElementException:
- raise AssertionError(f"Cannot find the doc URL for version {emqx_version}, please make sure the dashboard package is up to date.")
|