availcheck.checker
1# -*- coding: utf-8 -*- 2# Copyright (C) 2024 TU Dresden 3# ralf.klammer@tu-dresden.de 4 5import logging 6 7from json import dumps 8from time import time 9 10from . import ( 11 BROWSER_DIR, 12 O4A_ENTITIES_COUNT, 13) 14from .selenium import SeleniumAgent 15from .configs import CheckerConfigs 16 17log = logging.getLogger(__name__) 18 19 20def resolve_url(func): 21 """ 22 Decorator to resolve the URL before running any check. 23 """ 24 25 def wrap( 26 self, 27 subdomain=None, 28 path=None, 29 ignore_shadow_root=False, 30 *args, 31 **kwargs, 32 ): 33 current_url = self.selenium.get_url() 34 self.url = self.create_var_url(subdomain=subdomain, path=path) 35 if current_url != self.url: 36 try: 37 self.selenium.get(self.url) 38 if ( 39 getattr(self, "shadow_root", None) 40 and ignore_shadow_root is not True 41 ): 42 self.shadow_host = self.selenium.get_shadow_root( 43 self.shadow_root 44 ) 45 except Exception as e: 46 log.error(f"Unable to open URL: {self.url}") 47 log.error(e) 48 return False 49 50 return func(self, *args, **kwargs) 51 else: 52 return func(self, *args, **kwargs) 53 54 return wrap 55 56 57class CheckerBase(object): 58 """ 59 Base class for all the availability checker 60 """ 61 62 def __init__(self, url=None, instance="prod", path_of_screenshots=None): 63 self.instance = instance 64 self.selenium = SeleniumAgent( 65 path_of_screenshots=path_of_screenshots, 66 implicit_wait=10, 67 browser_dir=( 68 f"{BROWSER_DIR}_{self.__class__.__name__}_{self.instance}" 69 if BROWSER_DIR 70 else None 71 ), 72 ) 73 74 self.url = url 75 self._checker_config = None 76 77 @property 78 def checker_config(self): 79 """ 80 Get the checker configs for the given instance. 81 """ 82 return self._checker_config 83 84 @checker_config.setter 85 def checker_config(self, value): 86 """ 87 Set the checker configs for the given instance. 88 """ 89 self._checker_config = value 90 91 @property 92 def checks(self): 93 """ 94 Get the relevant checks for the given instance from the checker configs. 95 """ 96 if self.checker_config is not None: 97 return self.checker_config.get_checks() 98 99 def get_base_url(self): 100 """ 101 Get the base URL for the given instance from the checker configs. 102 """ 103 if self.checker_config is not None: 104 return self.checker_config.get_url(self.instance) 105 106 def run_check(self, check, checkmk_format=True): 107 """ 108 Run a single check for the given instance. 109 """ 110 # check if the check is supported 111 if check not in self.checks: 112 raise ValueError(f"Requested check '{check}' does not exist.") 113 elif self.instance not in self.checks[check]["instances"]: 114 raise ValueError( 115 f"Requested check '{check}' is not supported for instance " 116 f"'{self.instance}'." 117 ) 118 elif checkmk_format: 119 result = getattr(self, check)() 120 start_time = time() 121 result = getattr(self, check)() 122 execution_time = round(time() - start_time, 4) 123 status_code = ( 124 0 if result else self.checks[check]["status_on_error"] 125 ) 126 return "%i 'AvailabilityCheck | %s-%s | %s' duration=%s %s" % ( 127 status_code, 128 self.checker_config.id, 129 self.instance, 130 check, 131 execution_time, 132 f'{self.checks[check]["description"]} (URL: {self.url})', 133 ) 134 else: 135 return getattr(self, check)() 136 137 def run_checks(self): 138 """ 139 Run all checks defined in `self.checks` for the given instance. 140 """ 141 for check in self.checks: 142 if self.instance not in self.checks[check]["instances"]: 143 continue 144 yield self.run_check(check) 145 146 def save_checks(self, path): 147 """ 148 Save the results of the checks to a file. 149 """ 150 results = self.run_checks() 151 filename = f"{self.__class__.__name__}_{self.instance}.json" 152 with open(f"{path.rstrip('/')}/{filename}", "w") as f: 153 f.write(dumps(results)) 154 return filename 155 156 def create_var_url( 157 self, 158 subdomain=None, 159 path=None, 160 ): 161 """ 162 Cutting the url and setting subdomains based 163 if production or testing instance set. 164 """ 165 166 base_url = self.get_base_url() 167 168 if base_url is None: 169 raise ValueError( 170 f"self.Instance '{self.instance}' is not supported. " 171 "Please provide a valid URL." 172 ) 173 174 url = base_url 175 if subdomain is not None: 176 url = f"https://{subdomain}.{base_url.split('://')[1]}" 177 if path is not None: 178 url = f"{url}/{path.lstrip('/')}" 179 180 return url 181 182 def quit(self): 183 self.selenium.quit() 184 185 186class CheckerWebApps(CheckerBase): 187 """ 188 Checker for the Webapps Service 189 """ 190 191 checker_config = CheckerConfigs("webapps") 192 193 @resolve_url 194 def landing_page_webapps(self): 195 """ 196 Checks if the landing Page for Webapps is available 197 """ 198 199 result = self.selenium.find_by_css( 200 css="img[alt='Logo des NFDI Konsortiums NFDI4Earth']" 201 ) 202 203 return bool(result) 204 205 @resolve_url 206 def _visual_search_engine(self): 207 """ 208 Checks if the Graph Based Visual Search Engine is available 209 """ 210 result = self.selenium.wait_until( 211 css=".MuiDataGrid-cell--withRenderer", want_bool=True 212 ) 213 214 result = self.selenium.amount_of_elements( 215 css=".MuiDataGrid-cell--withRenderer", minimum=2 216 ) 217 218 return bool(result) 219 220 def visual_search_engine(self): 221 return self._visual_search_engine(subdomain="vesa") 222 223 224class CheckerKnowledgeHub(CheckerBase): 225 """ 226 Checker for the Knowledgehub Service 227 """ 228 229 checker_config = CheckerConfigs("knowledgehub") 230 231 @resolve_url 232 def _sparql(self): 233 """ 234 Checks if the Knowledgehub-SPARQL Endpoint is availiable 235 This is done by checking if an anchor of class 'navbar-brand' exists 236 and its text is 'SPARQL Query Editor' 237 """ 238 result = self.selenium.find_by_css(css="a[class='navbar-brand']") 239 return getattr(result, "text").strip() == "SPARQL Query Editor" 240 241 def sparql(self): 242 return self._sparql(subdomain="sparql") 243 244 @resolve_url 245 def _cordra(self): 246 """ 247 Checks if cordra is available, 248 This is done by checking for the searchbar. 249 """ 250 result = self.selenium.find_by_css(css="input[placeholder='Search']") 251 252 return bool(result) 253 254 def cordra(self): 255 return self._cordra(subdomain="cordra") 256 257 @resolve_url 258 def landing_page_knowledgehub(self): 259 """ 260 Checks if the Landingpage of Knowlegehub is available. 261 """ 262 current_url = self.selenium.get_url() 263 result = current_url.startswith("https://knowledgehub") 264 265 return bool(result) 266 267 @resolve_url 268 def more_examples_loaded(self): 269 """ 270 Check if more cards appear after button click. 271 """ 272 toggle_button = self.selenium.find_by_css( 273 css=("#hidden-card-deck-toggle") 274 ) 275 if toggle_button is None: 276 log.warning(f"{toggle_button} not found") 277 return False 278 else: 279 self.selenium.zoom() 280 toggle_button.click() 281 result = self.selenium.wait_until( 282 css="div[class='row mb-3'][id='card-deck']", want_bool=True 283 ) 284 return result 285 286 @resolve_url 287 def table_is_displayed(self): 288 """ 289 Checks if the "Harvested Ressources table appears 290 with atleast 10 Entries fetched. 291 """ 292 self.selenium.zoom() 293 self.selenium.wait_until(css=".col-3.border") 294 result = self.selenium.amount_of_elements(css=".col-3.border") 295 return bool(result) 296 297 @resolve_url 298 def check_button_endpoints(self): 299 """ 300 Checks for anker links working 301 """ 302 self.selenium.save_screenshot("/tmp/table.png") 303 result = self.selenium.check_button_redirection("a") 304 return bool(result) 305 306 307class CheckerSupportApps(CheckerBase): 308 """ 309 Checker for the SupportApps Service 310 """ 311 312 checker_config = CheckerConfigs("supportapps") 313 314 @resolve_url 315 def _jupyterhub(self): 316 """ 317 Checks if entry level of JupyterHub is restricted / service is running 318 This is done by checking if Logo and corresponding error code is shown. 319 """ 320 321 results = [] 322 323 # Check error 324 result = self.selenium.find_by_text( 325 css=".error", 326 text="405 : Method Not Allowed", 327 case_sensitive=False, 328 ) 329 results.append(result) 330 331 # Check logo 332 result = self.selenium.find_by_css(css="img[src='/hub/logo']") 333 results.append(result) 334 335 return all(results) 336 337 def jupyterhub(self): 338 return self._jupyterhub(subdomain="jupyterhub") 339 340 341class CheckerEduTrain(CheckerBase): 342 """ 343 Checker for the EduTrain Service 344 """ 345 346 checker_config = CheckerConfigs("edutrain") 347 348 @resolve_url 349 def openedx_lms(self): 350 """ 351 Check if the main page is loaded correctly. 352 This is done by checking if the DFG logo is present. 353 """ 354 result = self.selenium.find_by_css( 355 # Path may change on a regular, check again once more 356 css="a.explore-btn[href='/courses']" 357 ) 358 359 return bool(result) 360 361 @resolve_url 362 def _openedx_cms(self): 363 """ 364 Check if Educational Portal is Working 365 This is achieved by checking for the appearance of the logo 366 """ 367 result = self.selenium.find_by_css(css="a.brand-link img.brand-image") 368 return bool(result) 369 370 def openedx_cms(self): 371 return self._openedx_cms(subdomain="teacher") 372 373 @resolve_url 374 def _authentication(self): 375 """ 376 Check if URL is available, if "AcademicID" button 377 is available and leads to login page 378 """ 379 results = [] 380 academy_button = self.selenium.find_by_css( 381 css='button[id="oa2-academicid-oauth2"]' 382 ) 383 384 academy_button.click() 385 386 current_url = self.selenium.get_url() 387 self.selenium.save_screenshot("/tmp/auth.png") 388 target_page_reached = current_url.startswith( 389 "https://sso.academiccloud.de/simplesaml/module.php/" 390 ) 391 392 results.append(target_page_reached) 393 return all(results) 394 395 def authentication(self): 396 return self._authentication( 397 subdomain="apps", path="/authn/login?next=%2F" 398 ) 399 400 401class CheckerOneStop4All(CheckerBase): 402 """ 403 Checker for the OneStop4All Service 404 """ 405 406 checker_config = CheckerConfigs("onestop4all") 407 408 def __init__(self, url=None, instance=None, *args, **kwargs): 409 super().__init__(url=url, instance=instance, *args, **kwargs) 410 self.shadow_root = "onestop4all-app" 411 412 @resolve_url 413 def main_page(self): 414 """ 415 Check if the main page is loaded correctly. 416 This is done by checking if the DFG logo is present. 417 """ 418 result = self.selenium.find_by_css( 419 css='img[src="/dfg-logo.svg"]', elem=self.shadow_host 420 ) 421 return bool(result) 422 423 @resolve_url 424 def number_of_entities(self): 425 """ 426 Check if the number of entities is correct. 427 By checking if there is the correct amount of buttons on the webpage. 428 """ 429 results = self.selenium.find_by_css( 430 css="div.resourceEntries", 431 elem=self.shadow_host, 432 as_list=True, 433 ) 434 return len(results) == O4A_ENTITIES_COUNT 435 436 @resolve_url 437 def involvement(self): 438 """ 439 Check if the buttons withing involvement section is loaded correctly. 440 This is simply done, by checking if there are any buttons. 441 """ 442 results = self.selenium.find_by_css( 443 css="div.get-involved div.overlap > img", 444 elem=self.shadow_host, 445 as_list=True, 446 ) 447 return len(results) > 0 448 449 @resolve_url 450 def support_form(self, close_modal=True): 451 """ 452 Check if the support form is loaded correctly. 453 This is done by checking if the subject input field is present. 454 """ 455 # try to find the support form button 456 support_form_button = self.selenium.find_by_text( 457 css=".chakra-link", 458 text="user Support", 459 elem=self.shadow_host, 460 case_sensitive=False, 461 ) 462 463 # stop check if no support form button was found 464 if not support_form_button: 465 return False 466 467 # click on the support form button to open modal window 468 support_form_button.click() 469 470 subject = self.selenium.find_by_css( 471 css="input[name='subject']", elem=self.shadow_host 472 ) 473 if subject and close_modal: 474 # close the modal window finally 475 self.selenium.find_by_css( 476 css="button[aria-label='Close']", elem=self.shadow_host 477 ).click() 478 return bool(subject) 479 480 @resolve_url 481 def captcha_in_support_form(self): 482 """ 483 Check if the CAPTCHA is loaded correctly in the support form. 484 This is done by: 485 1. checking if the CAPTCHA checkbox is present 486 2. clicking on the CAPTCHA checkbox 487 3. checking if the CAPTCHA input field is present AND 488 its value is not empty 489 """ 490 if self.support_form(close_modal=False): 491 altcha_checkbox = self.selenium.wait_until( 492 css="input#altcha_checkbox", 493 elem=self.shadow_host, 494 ) 495 if altcha_checkbox: 496 altcha_checkbox.click() 497 altcha_input = self.selenium.wait_until( 498 css="input[type='hidden'][name='altcha']", 499 elem=self.shadow_host, 500 ) 501 if altcha_input and altcha_input.get_attribute("value") != "": 502 return True 503 return False 504 505 @resolve_url 506 def _solr(self): 507 """ 508 Check if the Solr login page is loaded correctly. 509 This is done by checking if the Solr logo is present. 510 """ 511 dashboard = self.selenium.find_by_css(css="a[href='#/']") 512 if dashboard is None: 513 return False 514 dashboard.click() 515 login = self.selenium.find_by_css(css="button.btn-danger") 516 return login is not None and login.text == "Login" 517 518 def solr(self): 519 return self._solr(path="/solr/#/login/", ignore_shadow_root=True)
21def resolve_url(func): 22 """ 23 Decorator to resolve the URL before running any check. 24 """ 25 26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs) 54 55 return wrap
Decorator to resolve the URL before running any check.
58class CheckerBase(object): 59 """ 60 Base class for all the availability checker 61 """ 62 63 def __init__(self, url=None, instance="prod", path_of_screenshots=None): 64 self.instance = instance 65 self.selenium = SeleniumAgent( 66 path_of_screenshots=path_of_screenshots, 67 implicit_wait=10, 68 browser_dir=( 69 f"{BROWSER_DIR}_{self.__class__.__name__}_{self.instance}" 70 if BROWSER_DIR 71 else None 72 ), 73 ) 74 75 self.url = url 76 self._checker_config = None 77 78 @property 79 def checker_config(self): 80 """ 81 Get the checker configs for the given instance. 82 """ 83 return self._checker_config 84 85 @checker_config.setter 86 def checker_config(self, value): 87 """ 88 Set the checker configs for the given instance. 89 """ 90 self._checker_config = value 91 92 @property 93 def checks(self): 94 """ 95 Get the relevant checks for the given instance from the checker configs. 96 """ 97 if self.checker_config is not None: 98 return self.checker_config.get_checks() 99 100 def get_base_url(self): 101 """ 102 Get the base URL for the given instance from the checker configs. 103 """ 104 if self.checker_config is not None: 105 return self.checker_config.get_url(self.instance) 106 107 def run_check(self, check, checkmk_format=True): 108 """ 109 Run a single check for the given instance. 110 """ 111 # check if the check is supported 112 if check not in self.checks: 113 raise ValueError(f"Requested check '{check}' does not exist.") 114 elif self.instance not in self.checks[check]["instances"]: 115 raise ValueError( 116 f"Requested check '{check}' is not supported for instance " 117 f"'{self.instance}'." 118 ) 119 elif checkmk_format: 120 result = getattr(self, check)() 121 start_time = time() 122 result = getattr(self, check)() 123 execution_time = round(time() - start_time, 4) 124 status_code = ( 125 0 if result else self.checks[check]["status_on_error"] 126 ) 127 return "%i 'AvailabilityCheck | %s-%s | %s' duration=%s %s" % ( 128 status_code, 129 self.checker_config.id, 130 self.instance, 131 check, 132 execution_time, 133 f'{self.checks[check]["description"]} (URL: {self.url})', 134 ) 135 else: 136 return getattr(self, check)() 137 138 def run_checks(self): 139 """ 140 Run all checks defined in `self.checks` for the given instance. 141 """ 142 for check in self.checks: 143 if self.instance not in self.checks[check]["instances"]: 144 continue 145 yield self.run_check(check) 146 147 def save_checks(self, path): 148 """ 149 Save the results of the checks to a file. 150 """ 151 results = self.run_checks() 152 filename = f"{self.__class__.__name__}_{self.instance}.json" 153 with open(f"{path.rstrip('/')}/{filename}", "w") as f: 154 f.write(dumps(results)) 155 return filename 156 157 def create_var_url( 158 self, 159 subdomain=None, 160 path=None, 161 ): 162 """ 163 Cutting the url and setting subdomains based 164 if production or testing instance set. 165 """ 166 167 base_url = self.get_base_url() 168 169 if base_url is None: 170 raise ValueError( 171 f"self.Instance '{self.instance}' is not supported. " 172 "Please provide a valid URL." 173 ) 174 175 url = base_url 176 if subdomain is not None: 177 url = f"https://{subdomain}.{base_url.split('://')[1]}" 178 if path is not None: 179 url = f"{url}/{path.lstrip('/')}" 180 181 return url 182 183 def quit(self): 184 self.selenium.quit()
Base class for all the availability checker
63 def __init__(self, url=None, instance="prod", path_of_screenshots=None): 64 self.instance = instance 65 self.selenium = SeleniumAgent( 66 path_of_screenshots=path_of_screenshots, 67 implicit_wait=10, 68 browser_dir=( 69 f"{BROWSER_DIR}_{self.__class__.__name__}_{self.instance}" 70 if BROWSER_DIR 71 else None 72 ), 73 ) 74 75 self.url = url 76 self._checker_config = None
78 @property 79 def checker_config(self): 80 """ 81 Get the checker configs for the given instance. 82 """ 83 return self._checker_config
Get the checker configs for the given instance.
92 @property 93 def checks(self): 94 """ 95 Get the relevant checks for the given instance from the checker configs. 96 """ 97 if self.checker_config is not None: 98 return self.checker_config.get_checks()
Get the relevant checks for the given instance from the checker configs.
100 def get_base_url(self): 101 """ 102 Get the base URL for the given instance from the checker configs. 103 """ 104 if self.checker_config is not None: 105 return self.checker_config.get_url(self.instance)
Get the base URL for the given instance from the checker configs.
107 def run_check(self, check, checkmk_format=True): 108 """ 109 Run a single check for the given instance. 110 """ 111 # check if the check is supported 112 if check not in self.checks: 113 raise ValueError(f"Requested check '{check}' does not exist.") 114 elif self.instance not in self.checks[check]["instances"]: 115 raise ValueError( 116 f"Requested check '{check}' is not supported for instance " 117 f"'{self.instance}'." 118 ) 119 elif checkmk_format: 120 result = getattr(self, check)() 121 start_time = time() 122 result = getattr(self, check)() 123 execution_time = round(time() - start_time, 4) 124 status_code = ( 125 0 if result else self.checks[check]["status_on_error"] 126 ) 127 return "%i 'AvailabilityCheck | %s-%s | %s' duration=%s %s" % ( 128 status_code, 129 self.checker_config.id, 130 self.instance, 131 check, 132 execution_time, 133 f'{self.checks[check]["description"]} (URL: {self.url})', 134 ) 135 else: 136 return getattr(self, check)()
Run a single check for the given instance.
138 def run_checks(self): 139 """ 140 Run all checks defined in `self.checks` for the given instance. 141 """ 142 for check in self.checks: 143 if self.instance not in self.checks[check]["instances"]: 144 continue 145 yield self.run_check(check)
Run all checks defined in self.checks
for the given instance.
147 def save_checks(self, path): 148 """ 149 Save the results of the checks to a file. 150 """ 151 results = self.run_checks() 152 filename = f"{self.__class__.__name__}_{self.instance}.json" 153 with open(f"{path.rstrip('/')}/{filename}", "w") as f: 154 f.write(dumps(results)) 155 return filename
Save the results of the checks to a file.
157 def create_var_url( 158 self, 159 subdomain=None, 160 path=None, 161 ): 162 """ 163 Cutting the url and setting subdomains based 164 if production or testing instance set. 165 """ 166 167 base_url = self.get_base_url() 168 169 if base_url is None: 170 raise ValueError( 171 f"self.Instance '{self.instance}' is not supported. " 172 "Please provide a valid URL." 173 ) 174 175 url = base_url 176 if subdomain is not None: 177 url = f"https://{subdomain}.{base_url.split('://')[1]}" 178 if path is not None: 179 url = f"{url}/{path.lstrip('/')}" 180 181 return url
Cutting the url and setting subdomains based if production or testing instance set.
187class CheckerWebApps(CheckerBase): 188 """ 189 Checker for the Webapps Service 190 """ 191 192 checker_config = CheckerConfigs("webapps") 193 194 @resolve_url 195 def landing_page_webapps(self): 196 """ 197 Checks if the landing Page for Webapps is available 198 """ 199 200 result = self.selenium.find_by_css( 201 css="img[alt='Logo des NFDI Konsortiums NFDI4Earth']" 202 ) 203 204 return bool(result) 205 206 @resolve_url 207 def _visual_search_engine(self): 208 """ 209 Checks if the Graph Based Visual Search Engine is available 210 """ 211 result = self.selenium.wait_until( 212 css=".MuiDataGrid-cell--withRenderer", want_bool=True 213 ) 214 215 result = self.selenium.amount_of_elements( 216 css=".MuiDataGrid-cell--withRenderer", minimum=2 217 ) 218 219 return bool(result) 220 221 def visual_search_engine(self): 222 return self._visual_search_engine(subdomain="vesa")
Checker for the Webapps Service
Set the checker configs for the given instance.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Checks if the landing Page for Webapps is available
Inherited Members
225class CheckerKnowledgeHub(CheckerBase): 226 """ 227 Checker for the Knowledgehub Service 228 """ 229 230 checker_config = CheckerConfigs("knowledgehub") 231 232 @resolve_url 233 def _sparql(self): 234 """ 235 Checks if the Knowledgehub-SPARQL Endpoint is availiable 236 This is done by checking if an anchor of class 'navbar-brand' exists 237 and its text is 'SPARQL Query Editor' 238 """ 239 result = self.selenium.find_by_css(css="a[class='navbar-brand']") 240 return getattr(result, "text").strip() == "SPARQL Query Editor" 241 242 def sparql(self): 243 return self._sparql(subdomain="sparql") 244 245 @resolve_url 246 def _cordra(self): 247 """ 248 Checks if cordra is available, 249 This is done by checking for the searchbar. 250 """ 251 result = self.selenium.find_by_css(css="input[placeholder='Search']") 252 253 return bool(result) 254 255 def cordra(self): 256 return self._cordra(subdomain="cordra") 257 258 @resolve_url 259 def landing_page_knowledgehub(self): 260 """ 261 Checks if the Landingpage of Knowlegehub is available. 262 """ 263 current_url = self.selenium.get_url() 264 result = current_url.startswith("https://knowledgehub") 265 266 return bool(result) 267 268 @resolve_url 269 def more_examples_loaded(self): 270 """ 271 Check if more cards appear after button click. 272 """ 273 toggle_button = self.selenium.find_by_css( 274 css=("#hidden-card-deck-toggle") 275 ) 276 if toggle_button is None: 277 log.warning(f"{toggle_button} not found") 278 return False 279 else: 280 self.selenium.zoom() 281 toggle_button.click() 282 result = self.selenium.wait_until( 283 css="div[class='row mb-3'][id='card-deck']", want_bool=True 284 ) 285 return result 286 287 @resolve_url 288 def table_is_displayed(self): 289 """ 290 Checks if the "Harvested Ressources table appears 291 with atleast 10 Entries fetched. 292 """ 293 self.selenium.zoom() 294 self.selenium.wait_until(css=".col-3.border") 295 result = self.selenium.amount_of_elements(css=".col-3.border") 296 return bool(result) 297 298 @resolve_url 299 def check_button_endpoints(self): 300 """ 301 Checks for anker links working 302 """ 303 self.selenium.save_screenshot("/tmp/table.png") 304 result = self.selenium.check_button_redirection("a") 305 return bool(result)
Checker for the Knowledgehub Service
Set the checker configs for the given instance.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Checks if the Landingpage of Knowlegehub is available.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Check if more cards appear after button click.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Checks if the "Harvested Ressources table appears with atleast 10 Entries fetched.
Inherited Members
308class CheckerSupportApps(CheckerBase): 309 """ 310 Checker for the SupportApps Service 311 """ 312 313 checker_config = CheckerConfigs("supportapps") 314 315 @resolve_url 316 def _jupyterhub(self): 317 """ 318 Checks if entry level of JupyterHub is restricted / service is running 319 This is done by checking if Logo and corresponding error code is shown. 320 """ 321 322 results = [] 323 324 # Check error 325 result = self.selenium.find_by_text( 326 css=".error", 327 text="405 : Method Not Allowed", 328 case_sensitive=False, 329 ) 330 results.append(result) 331 332 # Check logo 333 result = self.selenium.find_by_css(css="img[src='/hub/logo']") 334 results.append(result) 335 336 return all(results) 337 338 def jupyterhub(self): 339 return self._jupyterhub(subdomain="jupyterhub")
Checker for the SupportApps Service
Set the checker configs for the given instance.
Inherited Members
342class CheckerEduTrain(CheckerBase): 343 """ 344 Checker for the EduTrain Service 345 """ 346 347 checker_config = CheckerConfigs("edutrain") 348 349 @resolve_url 350 def openedx_lms(self): 351 """ 352 Check if the main page is loaded correctly. 353 This is done by checking if the DFG logo is present. 354 """ 355 result = self.selenium.find_by_css( 356 # Path may change on a regular, check again once more 357 css="a.explore-btn[href='/courses']" 358 ) 359 360 return bool(result) 361 362 @resolve_url 363 def _openedx_cms(self): 364 """ 365 Check if Educational Portal is Working 366 This is achieved by checking for the appearance of the logo 367 """ 368 result = self.selenium.find_by_css(css="a.brand-link img.brand-image") 369 return bool(result) 370 371 def openedx_cms(self): 372 return self._openedx_cms(subdomain="teacher") 373 374 @resolve_url 375 def _authentication(self): 376 """ 377 Check if URL is available, if "AcademicID" button 378 is available and leads to login page 379 """ 380 results = [] 381 academy_button = self.selenium.find_by_css( 382 css='button[id="oa2-academicid-oauth2"]' 383 ) 384 385 academy_button.click() 386 387 current_url = self.selenium.get_url() 388 self.selenium.save_screenshot("/tmp/auth.png") 389 target_page_reached = current_url.startswith( 390 "https://sso.academiccloud.de/simplesaml/module.php/" 391 ) 392 393 results.append(target_page_reached) 394 return all(results) 395 396 def authentication(self): 397 return self._authentication( 398 subdomain="apps", path="/authn/login?next=%2F" 399 )
Checker for the EduTrain Service
Set the checker configs for the given instance.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Check if the main page is loaded correctly. This is done by checking if the DFG logo is present.
Inherited Members
402class CheckerOneStop4All(CheckerBase): 403 """ 404 Checker for the OneStop4All Service 405 """ 406 407 checker_config = CheckerConfigs("onestop4all") 408 409 def __init__(self, url=None, instance=None, *args, **kwargs): 410 super().__init__(url=url, instance=instance, *args, **kwargs) 411 self.shadow_root = "onestop4all-app" 412 413 @resolve_url 414 def main_page(self): 415 """ 416 Check if the main page is loaded correctly. 417 This is done by checking if the DFG logo is present. 418 """ 419 result = self.selenium.find_by_css( 420 css='img[src="/dfg-logo.svg"]', elem=self.shadow_host 421 ) 422 return bool(result) 423 424 @resolve_url 425 def number_of_entities(self): 426 """ 427 Check if the number of entities is correct. 428 By checking if there is the correct amount of buttons on the webpage. 429 """ 430 results = self.selenium.find_by_css( 431 css="div.resourceEntries", 432 elem=self.shadow_host, 433 as_list=True, 434 ) 435 return len(results) == O4A_ENTITIES_COUNT 436 437 @resolve_url 438 def involvement(self): 439 """ 440 Check if the buttons withing involvement section is loaded correctly. 441 This is simply done, by checking if there are any buttons. 442 """ 443 results = self.selenium.find_by_css( 444 css="div.get-involved div.overlap > img", 445 elem=self.shadow_host, 446 as_list=True, 447 ) 448 return len(results) > 0 449 450 @resolve_url 451 def support_form(self, close_modal=True): 452 """ 453 Check if the support form is loaded correctly. 454 This is done by checking if the subject input field is present. 455 """ 456 # try to find the support form button 457 support_form_button = self.selenium.find_by_text( 458 css=".chakra-link", 459 text="user Support", 460 elem=self.shadow_host, 461 case_sensitive=False, 462 ) 463 464 # stop check if no support form button was found 465 if not support_form_button: 466 return False 467 468 # click on the support form button to open modal window 469 support_form_button.click() 470 471 subject = self.selenium.find_by_css( 472 css="input[name='subject']", elem=self.shadow_host 473 ) 474 if subject and close_modal: 475 # close the modal window finally 476 self.selenium.find_by_css( 477 css="button[aria-label='Close']", elem=self.shadow_host 478 ).click() 479 return bool(subject) 480 481 @resolve_url 482 def captcha_in_support_form(self): 483 """ 484 Check if the CAPTCHA is loaded correctly in the support form. 485 This is done by: 486 1. checking if the CAPTCHA checkbox is present 487 2. clicking on the CAPTCHA checkbox 488 3. checking if the CAPTCHA input field is present AND 489 its value is not empty 490 """ 491 if self.support_form(close_modal=False): 492 altcha_checkbox = self.selenium.wait_until( 493 css="input#altcha_checkbox", 494 elem=self.shadow_host, 495 ) 496 if altcha_checkbox: 497 altcha_checkbox.click() 498 altcha_input = self.selenium.wait_until( 499 css="input[type='hidden'][name='altcha']", 500 elem=self.shadow_host, 501 ) 502 if altcha_input and altcha_input.get_attribute("value") != "": 503 return True 504 return False 505 506 @resolve_url 507 def _solr(self): 508 """ 509 Check if the Solr login page is loaded correctly. 510 This is done by checking if the Solr logo is present. 511 """ 512 dashboard = self.selenium.find_by_css(css="a[href='#/']") 513 if dashboard is None: 514 return False 515 dashboard.click() 516 login = self.selenium.find_by_css(css="button.btn-danger") 517 return login is not None and login.text == "Login" 518 519 def solr(self): 520 return self._solr(path="/solr/#/login/", ignore_shadow_root=True)
Checker for the OneStop4All Service
Set the checker configs for the given instance.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Check if the main page is loaded correctly. This is done by checking if the DFG logo is present.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Check if the number of entities is correct. By checking if there is the correct amount of buttons on the webpage.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Check if the buttons withing involvement section is loaded correctly. This is simply done, by checking if there are any buttons.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Check if the support form is loaded correctly. This is done by checking if the subject input field is present.
26 def wrap( 27 self, 28 subdomain=None, 29 path=None, 30 ignore_shadow_root=False, 31 *args, 32 **kwargs, 33 ): 34 current_url = self.selenium.get_url() 35 self.url = self.create_var_url(subdomain=subdomain, path=path) 36 if current_url != self.url: 37 try: 38 self.selenium.get(self.url) 39 if ( 40 getattr(self, "shadow_root", None) 41 and ignore_shadow_root is not True 42 ): 43 self.shadow_host = self.selenium.get_shadow_root( 44 self.shadow_root 45 ) 46 except Exception as e: 47 log.error(f"Unable to open URL: {self.url}") 48 log.error(e) 49 return False 50 51 return func(self, *args, **kwargs) 52 else: 53 return func(self, *args, **kwargs)
Check if the CAPTCHA is loaded correctly in the support form. This is done by: 1. checking if the CAPTCHA checkbox is present 2. clicking on the CAPTCHA checkbox 3. checking if the CAPTCHA input field is present AND its value is not empty