Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development selenium add stats page tests 1 #3313

Open
wants to merge 14 commits into
base: development
Choose a base branch
from
2 changes: 1 addition & 1 deletion packages/playground/tests/frontend_selenium/Config.ini
Marinaa-Emad marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ net = dev
seed =
A-Harby marked this conversation as resolved.
Show resolved Hide resolved
node_seed =
address =
email =
email =
87 changes: 87 additions & 0 deletions packages/playground/tests/frontend_selenium/pages/statistics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException



class StatisticsPage:

logout_button = (By.XPATH, "//button[.//span[text()=' Logout ']]")
tfgrid_button = (By.XPATH, "//span[text()='TFGrid']")
grid_status_button = (By.XPATH, "//span[text()='Grid Status']")
node_monitoring_button = (By.XPATH, "//span[text()='Node Monitoring']")
statistics_button = (By.XPATH, "//span[text()='Node Statistics']")
statistics_label = (By.XPATH, "//*[contains(text(), 'Statistics')]")
map = (By.XPATH,"//button[contains(@class, 'btn-main-container')]")
nodes_online = (By.XPATH, "//span[text()='Nodes Online']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
dedicated_machines = (By.XPATH, "//span[text()='Dedicated Machines']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
farms = (By.XPATH, "//span[text()='Farms']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
countries = (By.XPATH, "//span[text()='Countries']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
cpus = (By.XPATH, "//span[text()='CPUs']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
ssd_storage = (By.XPATH, "//span[text()='SSD Storage']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
hdd_storage = (By.XPATH, "//span[text()='HDD Storage']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
ram = (By.XPATH, "//span[text()='RAM']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
gpus = (By.XPATH, "//span[text()='GPUs']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
access_nodes = (By.XPATH, "//span[text()='Access Nodes']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
gateways = (By.XPATH, "//span[text()='Gateways']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
twins = (By.XPATH, "//span[text()='Twins']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
public_ips = (By.XPATH, "//span[text()='Public IPs']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
conracts = (By.XPATH, "//span[text()='Contracts']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")
number_of_workloads = (By.XPATH, "//span[text()='Number of workloads']/ancestor::div/following-sibling::div[@class='v-card-text card-body']")


def __init__(self, browser):
self.browser = browser

def navigate(self):
webdriver.ActionChains(self.browser).send_keys(Keys.ESCAPE).perform()
self.browser.find_element(*self.tfgrid_button).click()
self.browser.find_element(*self.statistics_button).click()
WebDriverWait(self.browser, 60).until(EC.visibility_of_element_located(self.statistics_label))

def statistics_detials(self):
details = []
wait = WebDriverWait(self.browser, 60) # Increased wait time to 60 seconds
elements_to_fetch = [
("Nodes Online", self.nodes_online),
("Dedicated Machines", self.dedicated_machines),
("Farms", self.farms),
("Countries", self.countries),
("CPUs", self.cpus),
("SSD Storage", self.ssd_storage),
("HDD Storage", self.hdd_storage),
("RAM", self.ram),
("GPUs", self.gpus),
("Access Nodes", self.access_nodes),
("Gateways", self.gateways),
("Twins", self.twins),
("Public IPs", self.public_ips),
("Contracts", self.conracts),
("Number of workloads", self.number_of_workloads)
]
for _, locator in elements_to_fetch:
try:
element_text = wait.until(EC.visibility_of_element_located(locator)).text
details.append(element_text)
except TimeoutException:
details.append(None) # Add None or some default value to maintain list consistency
return details

def get_link(self):
WebDriverWait(self.browser, 30).until(EC.number_of_windows_to_be(2))
self.browser.switch_to.window(self.browser.window_handles[1])
url = self.browser.current_url
self.browser.close()
self.browser.switch_to.window(self.browser.window_handles[0])
return url

def grid_status_link(self):
self.browser.find_element(*self.grid_status_button).click()
return self.get_link()

def node_monitoring_link(self):
self.browser.find_element(*self.node_monitoring_button).click()
return self.get_link()
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import math
from utils.utils import byte_converter,convert_to_scaled_float
from pages.statistics import StatisticsPage
from utils.grid_proxy import GridProxy
from pages.dashboard import DashboardPage

def before_test_setup(browser):
statistics_page = StatisticsPage(browser)
dashboard_page = DashboardPage(browser)
dashboard_page.open_and_load()
statistics_page.navigate()
return statistics_page

def test_statistics_details(browser):
statistics_page = before_test_setup(browser)
grid_proxy = GridProxy(browser)
statistics_details = statistics_page.statistics_detials()
grid_statistics_details = grid_proxy.get_stats()
# Convert necessary values from string to integer before comparing
statistics_details_converted = [int(detail.replace(',', '')) if detail is not None and detail.isdigit() else detail for detail in statistics_details]
# Full set of assertions, comparing UI stats with proxy stats
assert grid_statistics_details['nodes'] == statistics_details_converted[0]
assert grid_statistics_details['dedicatedNodes'] == statistics_details_converted[1]
assert grid_statistics_details['farms'] == statistics_details_converted[2]
assert grid_statistics_details['countries'] == statistics_details_converted[3]
assert grid_statistics_details['totalCru'] == statistics_details_converted[4]
assert math.isclose(convert_to_scaled_float(grid_statistics_details['totalSru']), convert_to_scaled_float(byte_converter(statistics_details_converted[5])), abs_tol=0.002)
assert math.isclose(convert_to_scaled_float(grid_statistics_details['totalHru']), convert_to_scaled_float(byte_converter(statistics_details_converted[6])), abs_tol=0.002)
assert math.isclose(convert_to_scaled_float(grid_statistics_details['totalMru']), convert_to_scaled_float(byte_converter(statistics_details_converted[7])), abs_tol=0.002)
assert grid_statistics_details['gpus'] == statistics_details_converted[8]
assert grid_statistics_details['accessNodes'] == statistics_details_converted[9]
assert grid_statistics_details['gateways'] == statistics_details_converted[10]
assert grid_statistics_details['twins'] == statistics_details_converted[11]
assert grid_statistics_details['publicIps'] == statistics_details_converted[12]
assert grid_statistics_details['contracts'] == statistics_details_converted[13]
assert grid_statistics_details['workloads_number'] == statistics_details_converted[14]

def test_tfgrid_links(browser):
statistics_page = before_test_setup(browser)
assert statistics_page.grid_status_link() == 'https://status.grid.tf/status/threefold/'
assert statistics_page.node_monitoring_link() == 'https://metrics.grid.tf/d/rYdddlPWkfqwf/zos-host-metrics?orgId=2&refresh=30s/'
35 changes: 32 additions & 3 deletions packages/playground/tests/frontend_selenium/utils/grid_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,36 @@ def get_twin_node(self, twin_id):
details = r.json()
return details


def get_stats(self):
r = requests.post('https://stats.' + Base.net + '.grid.tf/api/stats-summary')
stats_json = r.json()
return list(stats_json.values())
up = requests.get(Base.gridproxy_url + 'stats?status=up', timeout=10).json()
standby = requests.get(Base.gridproxy_url + 'stats?status=standby', timeout=10).json()
# Initialize a dictionary to store the merged data
merged_data = {}
# Merge simple values, summing if they differ
keys_to_sum = ['nodes', 'accessNodes', 'totalCru', 'totalSru', 'totalMru', 'totalHru', 'gpus', 'dedicatedNodes', 'workloads_number']
for key in keys_to_sum:
merged_data[key] = up[key] + standby[key]
# Merge the "farms", "publicIps", "gateways", "twins", and "contracts" fields (they are the same)
keys_to_add_once = ['farms', 'publicIps', 'gateways', 'twins', 'contracts']
for key in keys_to_add_once:
merged_data[key] = up[key]
# Merge nodesDistribution and calculate unique and common countries
up_distribution = up['nodesDistribution']
standby_distribution = standby['nodesDistribution']
merged_distribution = {}
common_countries = 0
for country, up_count in up_distribution.items():
standby_count = standby_distribution.get(country, 0)
merged_distribution[country] = up_count + standby_count
if standby_count > 0:
common_countries += 1
for country, standby_count in standby_distribution.items():
if country not in merged_distribution:
merged_distribution[country] = standby_count
merged_data['nodesDistribution'] = merged_distribution
# Calculate the total countries: all unique countries minus common countries
total_countries = len(merged_distribution) # Total unique countries
merged_data['countries'] = total_countries
# Return the dictionary directly
return merged_data
23 changes: 18 additions & 5 deletions packages/playground/tests/frontend_selenium/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,29 @@ def randomize_public_ipv4():
ip_subnet = ip + '/' + random.choice(['26', '27', '28', '29'])
return ip_subnet, ip


def convert_to_scaled_float(number):
str_number = str(number)
if '.' in str_number:
decimal_index = str_number.index('.')
else:
decimal_index = len(str_number)
divisor = 10 ** decimal_index
scaled_number = number / divisor
return scaled_number



def byte_converter(value):
if value != '0':
if value[-2] == 'P':
return float(value[:-3])*(1024*2)
return float(value[:-3]) * (1024 ** 5)
elif value[-2] == 'T':
return float(value[:-3])*1024
else:
return float(value[:-3]) * (1024 ** 4)
elif value[-2] == 'G':
return float(value[:-3])
else:
return float(value)
return float(value)


def get_min(nodes, resource):
min = nodes[0][resource]
Expand Down
Loading