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.save_screenshot("/tmp/table.png") 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 299class CheckerSupportApps(CheckerBase): 300 """ 301 Checker for the SupportApps Service 302 """ 303 304 checker_config = CheckerConfigs("supportapps") 305 306 @resolve_url 307 def _jupyterhub(self): 308 """ 309 Checks if entry level of JupyterHub is restricted / service is running 310 This is done by checking if Logo and corresponding error code is shown. 311 """ 312 313 results = [] 314 315 # Check error 316 result = self.selenium.find_by_text( 317 css=".error", 318 text="405 : Method Not Allowed", 319 case_sensitive=False, 320 ) 321 results.append(result) 322 323 # Check logo 324 result = self.selenium.find_by_css(css="img[src='/hub/logo']") 325 results.append(result) 326 327 return all(results) 328 329 def jupyterhub(self): 330 return self._jupyterhub(subdomain="jupyterhub") 331 332 333class CheckerEduTrain(CheckerBase): 334 """ 335 Checker for the EduTrain Service 336 """ 337 338 checker_config = CheckerConfigs("edutrain") 339 340 @resolve_url 341 def openedx_lms(self): 342 """ 343 Check if the main page is loaded correctly. 344 This is done by checking if the DFG logo is present. 345 """ 346 result = self.selenium.find_by_css( 347 # Path may change on a regular, check again once more 348 css="a.explore-btn[href='/courses']" 349 ) 350 351 return bool(result) 352 353 @resolve_url 354 def _openedx_cms(self): 355 """ 356 Check if Educational Portal is Working 357 This is achieved by checking for the appearance of the logo 358 """ 359 result = self.selenium.find_by_css(css="a.brand-link img.brand-image") 360 return bool(result) 361 362 def openedx_cms(self): 363 return self._openedx_cms(subdomain="teacher") 364 365 @resolve_url 366 def _authentication(self): 367 """ 368 Check if URL is available, if "AcademicID" button 369 is available and leads to login page 370 """ 371 results = [] 372 academy_button = self.selenium.find_by_css( 373 css='button[id="oa2-academicid-oauth2"]' 374 ) 375 376 academy_button.click() 377 378 current_url = self.selenium.get_url() 379 self.selenium.save_screenshot("/tmp/auth.png") 380 target_page_reached = current_url.startswith( 381 "https://sso.academiccloud.de/simplesaml/module.php/" 382 ) 383 384 results.append(target_page_reached) 385 return all(results) 386 387 def authentication(self): 388 return self._authentication( 389 subdomain="apps", path="/authn/login?next=%2F" 390 ) 391 392 393class CheckerOneStop4All(CheckerBase): 394 """ 395 Checker for the OneStop4All Service 396 """ 397 398 checker_config = CheckerConfigs("onestop4all") 399 400 def __init__(self, url=None, instance=None, *args, **kwargs): 401 super().__init__(url=url, instance=instance, *args, **kwargs) 402 self.shadow_root = "onestop4all-app" 403 404 @resolve_url 405 def main_page(self): 406 """ 407 Check if the main page is loaded correctly. 408 This is done by checking if the DFG logo is present. 409 """ 410 result = self.selenium.find_by_css( 411 css='img[src="/dfg-logo.svg"]', elem=self.shadow_host 412 ) 413 return bool(result) 414 415 @resolve_url 416 def number_of_entities(self): 417 """ 418 Check if the number of entities is correct. 419 By checking if there is the correct amount of buttons on the webpage. 420 """ 421 results = self.selenium.find_by_css( 422 css="div.resourceEntries", 423 elem=self.shadow_host, 424 as_list=True, 425 ) 426 return len(results) == O4A_ENTITIES_COUNT 427 428 @resolve_url 429 def involvement(self): 430 """ 431 Check if the buttons withing involvement section is loaded correctly. 432 This is simply done, by checking if there are any buttons. 433 """ 434 results = self.selenium.find_by_css( 435 css="div.get-involved div.overlap > img", 436 elem=self.shadow_host, 437 as_list=True, 438 ) 439 return len(results) > 0 440 441 @resolve_url 442 def support_form(self, close_modal=True): 443 """ 444 Check if the support form is loaded correctly. 445 This is done by checking if the subject input field is present. 446 """ 447 # try to find the support form button 448 support_form_button = self.selenium.find_by_text( 449 css=".chakra-link", 450 text="user Support", 451 elem=self.shadow_host, 452 case_sensitive=False, 453 ) 454 455 # stop check if no support form button was found 456 if not support_form_button: 457 return False 458 459 # click on the support form button to open modal window 460 support_form_button.click() 461 462 subject = self.selenium.find_by_css( 463 css="input[name='subject']", elem=self.shadow_host 464 ) 465 if subject and close_modal: 466 # close the modal window finally 467 self.selenium.find_by_css( 468 css="button[aria-label='Close']", elem=self.shadow_host 469 ).click() 470 return bool(subject) 471 472 @resolve_url 473 def captcha_in_support_form(self): 474 """ 475 Check if the CAPTCHA is loaded correctly in the support form. 476 This is done by: 477 1. checking if the CAPTCHA checkbox is present 478 2. clicking on the CAPTCHA checkbox 479 3. checking if the CAPTCHA input field is present AND 480 its value is not empty 481 """ 482 if self.support_form(close_modal=False): 483 altcha_checkbox = self.selenium.wait_until( 484 css="input#altcha_checkbox", 485 elem=self.shadow_host, 486 ) 487 if altcha_checkbox: 488 altcha_checkbox.click() 489 altcha_input = self.selenium.wait_until( 490 css="input[type='hidden'][name='altcha']", 491 elem=self.shadow_host, 492 ) 493 if altcha_input and altcha_input.get_attribute("value") != "": 494 return True 495 return False 496 497 @resolve_url 498 def _solr(self): 499 """ 500 Check if the Solr login page is loaded correctly. 501 This is done by checking if the Solr logo is present. 502 """ 503 login = self.selenium.wait_until(css="button.btn-danger") 504 if login: 505 return login is not None and login.text == "Login" 506 507 def solr(self): 508 return self._solr(path="/solr/#/", 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.save_screenshot("/tmp/table.png") 295 self.selenium.wait_until(css=".col-3.border") 296 result = self.selenium.amount_of_elements(css=".col-3.border") 297 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
300class CheckerSupportApps(CheckerBase): 301 """ 302 Checker for the SupportApps Service 303 """ 304 305 checker_config = CheckerConfigs("supportapps") 306 307 @resolve_url 308 def _jupyterhub(self): 309 """ 310 Checks if entry level of JupyterHub is restricted / service is running 311 This is done by checking if Logo and corresponding error code is shown. 312 """ 313 314 results = [] 315 316 # Check error 317 result = self.selenium.find_by_text( 318 css=".error", 319 text="405 : Method Not Allowed", 320 case_sensitive=False, 321 ) 322 results.append(result) 323 324 # Check logo 325 result = self.selenium.find_by_css(css="img[src='/hub/logo']") 326 results.append(result) 327 328 return all(results) 329 330 def jupyterhub(self): 331 return self._jupyterhub(subdomain="jupyterhub")
Checker for the SupportApps Service
Set the checker configs for the given instance.
Inherited Members
334class CheckerEduTrain(CheckerBase): 335 """ 336 Checker for the EduTrain Service 337 """ 338 339 checker_config = CheckerConfigs("edutrain") 340 341 @resolve_url 342 def openedx_lms(self): 343 """ 344 Check if the main page is loaded correctly. 345 This is done by checking if the DFG logo is present. 346 """ 347 result = self.selenium.find_by_css( 348 # Path may change on a regular, check again once more 349 css="a.explore-btn[href='/courses']" 350 ) 351 352 return bool(result) 353 354 @resolve_url 355 def _openedx_cms(self): 356 """ 357 Check if Educational Portal is Working 358 This is achieved by checking for the appearance of the logo 359 """ 360 result = self.selenium.find_by_css(css="a.brand-link img.brand-image") 361 return bool(result) 362 363 def openedx_cms(self): 364 return self._openedx_cms(subdomain="teacher") 365 366 @resolve_url 367 def _authentication(self): 368 """ 369 Check if URL is available, if "AcademicID" button 370 is available and leads to login page 371 """ 372 results = [] 373 academy_button = self.selenium.find_by_css( 374 css='button[id="oa2-academicid-oauth2"]' 375 ) 376 377 academy_button.click() 378 379 current_url = self.selenium.get_url() 380 self.selenium.save_screenshot("/tmp/auth.png") 381 target_page_reached = current_url.startswith( 382 "https://sso.academiccloud.de/simplesaml/module.php/" 383 ) 384 385 results.append(target_page_reached) 386 return all(results) 387 388 def authentication(self): 389 return self._authentication( 390 subdomain="apps", path="/authn/login?next=%2F" 391 )
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
394class CheckerOneStop4All(CheckerBase): 395 """ 396 Checker for the OneStop4All Service 397 """ 398 399 checker_config = CheckerConfigs("onestop4all") 400 401 def __init__(self, url=None, instance=None, *args, **kwargs): 402 super().__init__(url=url, instance=instance, *args, **kwargs) 403 self.shadow_root = "onestop4all-app" 404 405 @resolve_url 406 def main_page(self): 407 """ 408 Check if the main page is loaded correctly. 409 This is done by checking if the DFG logo is present. 410 """ 411 result = self.selenium.find_by_css( 412 css='img[src="/dfg-logo.svg"]', elem=self.shadow_host 413 ) 414 return bool(result) 415 416 @resolve_url 417 def number_of_entities(self): 418 """ 419 Check if the number of entities is correct. 420 By checking if there is the correct amount of buttons on the webpage. 421 """ 422 results = self.selenium.find_by_css( 423 css="div.resourceEntries", 424 elem=self.shadow_host, 425 as_list=True, 426 ) 427 return len(results) == O4A_ENTITIES_COUNT 428 429 @resolve_url 430 def involvement(self): 431 """ 432 Check if the buttons withing involvement section is loaded correctly. 433 This is simply done, by checking if there are any buttons. 434 """ 435 results = self.selenium.find_by_css( 436 css="div.get-involved div.overlap > img", 437 elem=self.shadow_host, 438 as_list=True, 439 ) 440 return len(results) > 0 441 442 @resolve_url 443 def support_form(self, close_modal=True): 444 """ 445 Check if the support form is loaded correctly. 446 This is done by checking if the subject input field is present. 447 """ 448 # try to find the support form button 449 support_form_button = self.selenium.find_by_text( 450 css=".chakra-link", 451 text="user Support", 452 elem=self.shadow_host, 453 case_sensitive=False, 454 ) 455 456 # stop check if no support form button was found 457 if not support_form_button: 458 return False 459 460 # click on the support form button to open modal window 461 support_form_button.click() 462 463 subject = self.selenium.find_by_css( 464 css="input[name='subject']", elem=self.shadow_host 465 ) 466 if subject and close_modal: 467 # close the modal window finally 468 self.selenium.find_by_css( 469 css="button[aria-label='Close']", elem=self.shadow_host 470 ).click() 471 return bool(subject) 472 473 @resolve_url 474 def captcha_in_support_form(self): 475 """ 476 Check if the CAPTCHA is loaded correctly in the support form. 477 This is done by: 478 1. checking if the CAPTCHA checkbox is present 479 2. clicking on the CAPTCHA checkbox 480 3. checking if the CAPTCHA input field is present AND 481 its value is not empty 482 """ 483 if self.support_form(close_modal=False): 484 altcha_checkbox = self.selenium.wait_until( 485 css="input#altcha_checkbox", 486 elem=self.shadow_host, 487 ) 488 if altcha_checkbox: 489 altcha_checkbox.click() 490 altcha_input = self.selenium.wait_until( 491 css="input[type='hidden'][name='altcha']", 492 elem=self.shadow_host, 493 ) 494 if altcha_input and altcha_input.get_attribute("value") != "": 495 return True 496 return False 497 498 @resolve_url 499 def _solr(self): 500 """ 501 Check if the Solr login page is loaded correctly. 502 This is done by checking if the Solr logo is present. 503 """ 504 login = self.selenium.wait_until(css="button.btn-danger") 505 if login: 506 return login is not None and login.text == "Login" 507 508 def solr(self): 509 return self._solr(path="/solr/#/", 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