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

Run all checks defined in self.checks for the given instance.

def save_checks(self, path):
80    def save_checks(self, path):
81        """
82        Save the results of the checks to a file.
83        """
84        results = self.run_checks()
85        filename = f"{self.__class__.__name__}_{self.instance}.json"
86        with open(f"{path.rstrip('/')}/{filename}", "w") as f:
87            f.write(dumps(results))
88        return filename

Save the results of the checks to a file.

def create_var_url(self, env_var, instance, subdomain=None, path=''):
 90    def create_var_url(
 91        self,
 92        env_var,
 93        instance,
 94        subdomain=None,
 95        path="",
 96    ):
 97        """
 98        Cutting the url and setting subdomains based
 99        if production or testing instance set.
100        """
101
102        base_url = env_var.get(self.instance, None)
103
104        if base_url is None:
105            raise ValueError(
106                f"self.Instance '{instance}' is not supported. "
107                "Please provide a valid URL."
108            )
109        if subdomain is None:
110            var_url = f"https://{base_url.split('://')[1]}{path}"
111        else:
112            var_url = f"https://{subdomain}.{base_url.split('://')[1]}{path}"
113
114        return var_url

Cutting the url and setting subdomains based if production or testing instance set.

def quit(self):
116    def quit(self):
117        self.selenium.quit()
class CheckerWebApps(CheckerBase):
120class CheckerWebApps(CheckerBase):
121
122    checks = {"landing_page_webapps": ["prod"]}
123
124    @resolve_url
125    def _landing_page_webapps(self):
126
127        result = self.selenium.find_by_css(
128            css="img[alt='Logo des NFDI Konsortiums NFDI4Earth']"
129        )
130
131        return bool(result)
132
133    def landing_page_webapps(self):
134        """
135        Checks if the landing Page for Webapps is available
136        """
137        self.url = self.create_var_url(
138            WEBAPPS_URL,
139            self.instance,
140        )
141
142        return self._landing_page_webapps()
checks = {'landing_page_webapps': ['prod']}
def landing_page_webapps(self):
133    def landing_page_webapps(self):
134        """
135        Checks if the landing Page for Webapps is available
136        """
137        self.url = self.create_var_url(
138            WEBAPPS_URL,
139            self.instance,
140        )
141
142        return self._landing_page_webapps()

Checks if the landing Page for Webapps is available

class CheckerKnowledgeHub(CheckerBase):
145class CheckerKnowledgeHub(CheckerBase):
146    checks = {
147        "sparql": ["prod", "test"],
148        "cordra": ["prod", "test"],
149        "landing_page_knowledgehub": ["prod", "test"],
150        "more_examples_loaded": ["prod", "test"],
151        "table_is_displayed": ["prod", "test"],
152    }
153
154    @resolve_url
155    def _sparql(self):
156        result = self.selenium.find_by_css(css="circle[class='success']")
157
158        return bool(result)
159
160    def sparql(self):
161        """
162        Checks if the Knowledgehub-SPARQL Endpoint is availiable
163        This is done by checking for the "server status" circle.
164        """
165        self.url = self.create_var_url(
166            KNOWLEDGEHUB_URL,
167            self.instance,
168            subdomain="sparql",
169        )
170
171        return self._sparql()
172
173    @resolve_url
174    def _cordra(self):
175        result = self.selenium.find_by_css(css="input[placeholder='Search']")
176
177        return bool(result)
178
179    def cordra(self):
180        """
181        Checks if cordra is available,
182        This is done by checking for the searchbar.
183        """
184        self.url = self.create_var_url(
185            KNOWLEDGEHUB_URL, self.instance, subdomain="cordra"
186        )
187
188        return self._cordra()
189
190    @resolve_url
191    def _landing_page_knowledgehub(self):
192        current_url = self.selenium.get_url()
193        result = current_url.startswith("https://knowledgehub")
194
195        return bool(result)
196
197    def landing_page_knowledgehub(self):
198        """
199        Checks if the Landingpage of Knowlegehub is available.
200        """
201        self.url = self.create_var_url(KNOWLEDGEHUB_URL, self.instance)
202        return self._landing_page_knowledgehub()
203
204    @resolve_url
205    def _more_examples_loaded(self):
206        toggle_button = self.selenium.find_by_css(
207            css=("#hidden-card-deck-toggle")
208        )
209        if toggle_button is None:
210            log.warning(f"{toggle_button} not found")
211            return False
212        else:
213            self.selenium.zoom()
214            toggle_button.click()
215            result = self.selenium.wait_until(
216                css="div[class='row mb-3'][id='card-deck']", want_bool=True
217            )
218        return result
219
220    def more_examples_loaded(self):
221        """
222        Check if more cards appear after button click.
223        """
224        self.url = self.create_var_url(KNOWLEDGEHUB_URL, self.instance)
225        return self._more_examples_loaded()
226
227    @resolve_url
228    def _table_is_displayed(self):
229        self.selenium.zoom()
230        self.selenium.save_screenshot("/tmp/table.png")
231        self.selenium.wait_until(css=".col-3.border")
232        result = self.selenium.amount_of_elements(css=".col-3.border")
233        return bool(result)
234
235    def table_is_displayed(self):
236        """
237        Checks if the "Harvested Ressources table appears
238        with atleast 10 Entries fetched.
239        """
240        self.url = self.create_var_url(KNOWLEDGEHUB_URL, self.instance)
241        return self._table_is_displayed()
checks = {'sparql': ['prod', 'test'], 'cordra': ['prod', 'test'], 'landing_page_knowledgehub': ['prod', 'test'], 'more_examples_loaded': ['prod', 'test'], 'table_is_displayed': ['prod', 'test']}
def sparql(self):
160    def sparql(self):
161        """
162        Checks if the Knowledgehub-SPARQL Endpoint is availiable
163        This is done by checking for the "server status" circle.
164        """
165        self.url = self.create_var_url(
166            KNOWLEDGEHUB_URL,
167            self.instance,
168            subdomain="sparql",
169        )
170
171        return self._sparql()

Checks if the Knowledgehub-SPARQL Endpoint is availiable This is done by checking for the "server status" circle.

def cordra(self):
179    def cordra(self):
180        """
181        Checks if cordra is available,
182        This is done by checking for the searchbar.
183        """
184        self.url = self.create_var_url(
185            KNOWLEDGEHUB_URL, self.instance, subdomain="cordra"
186        )
187
188        return self._cordra()

Checks if cordra is available, This is done by checking for the searchbar.

def landing_page_knowledgehub(self):
197    def landing_page_knowledgehub(self):
198        """
199        Checks if the Landingpage of Knowlegehub is available.
200        """
201        self.url = self.create_var_url(KNOWLEDGEHUB_URL, self.instance)
202        return self._landing_page_knowledgehub()

Checks if the Landingpage of Knowlegehub is available.

def more_examples_loaded(self):
220    def more_examples_loaded(self):
221        """
222        Check if more cards appear after button click.
223        """
224        self.url = self.create_var_url(KNOWLEDGEHUB_URL, self.instance)
225        return self._more_examples_loaded()

Check if more cards appear after button click.

def table_is_displayed(self):
235    def table_is_displayed(self):
236        """
237        Checks if the "Harvested Ressources table appears
238        with atleast 10 Entries fetched.
239        """
240        self.url = self.create_var_url(KNOWLEDGEHUB_URL, self.instance)
241        return self._table_is_displayed()

Checks if the "Harvested Ressources table appears with atleast 10 Entries fetched.

class CheckerSupportApps(CheckerBase):
244class CheckerSupportApps(CheckerBase):
245    # define checks to run in `run_checks` AND
246    # define for which instances to run them
247    checks = {"jupyterhub": ["prod"]}
248
249    @resolve_url
250    def _jupyterhub(self):
251        """
252        Checks if entry level of JupyterHub is restricted / service is running
253        This is done by checking if Logo and corresponding error code is shown.
254        """
255
256        results = []
257
258        #  Check error
259        result = self.selenium.find_by_text(
260            css=".error",
261            text="405 : Method Not Allowed",
262            case_sensitive=False,
263        )
264        results.append(result)
265
266        #  Check logo
267        result = self.selenium.find_by_css(css="img[src='/hub/logo']")
268        results.append(result)
269
270        return all(results)
271
272    def jupyterhub(self):
273        self.url = self.create_var_url(
274            SUPPORT_APPS_URL, self.instance, subdomain="jupyterhub"
275        )
276        return self._jupyterhub()
checks = {'jupyterhub': ['prod']}
def jupyterhub(self):
272    def jupyterhub(self):
273        self.url = self.create_var_url(
274            SUPPORT_APPS_URL, self.instance, subdomain="jupyterhub"
275        )
276        return self._jupyterhub()
class CheckerEduTrain(CheckerBase):
279class CheckerEduTrain(CheckerBase):
280    # define checks to run in `run_checks` AND
281    # define for which instances to run them
282    checks = {
283        "openedx_lms": ["prod", "test"],
284        "openedx_cms": ["prod", "test"],
285        "authentication": ["prod", "test"],
286    }
287
288    def openedx_lms(self):
289        """
290        Check if the main page is loaded correctly.
291        This is done by checking if the DFG logo is present.
292        """
293
294        self.url = self.create_var_url(
295            EDU_URL, self.instance, subdomain="teacher"
296        )
297        self.selenium.get(self.url)
298        return self._openedx_lms()
299
300    @resolve_url
301    def _openedx_lms(self):
302        result = self.selenium.find_by_css(
303            # Path may change on a regular, check again once more
304            css='img[src="/static/studio/edutrain/images/studio-logo.419852c6db47.png"]'
305        )
306
307        return bool(result)
308
309    @resolve_url
310    def _openedx_cms(self):
311        result = self.selenium.find_by_css(
312            css='img[src="/static/studio/edutrain/images/studio-logo.419852c6db47.png"]'
313        )
314        return bool(result)
315
316    def openedx_cms(self):
317        """
318        Check if Educational Portal is Working
319        This is achieved by checking for the appearance of the logo
320        """
321
322        self.url = self.create_var_url(
323            EDU_URL, self.instance, subdomain="teacher"
324        )
325
326        return self._openedx_cms()
327
328    @resolve_url
329    def _authentication(self):
330        results = []
331        academy_button = self.selenium.find_by_css(
332            css='button[id="oa2-academicid-oauth2"]'
333        )
334
335        academy_button.click()
336
337        current_url = self.selenium.get_url()
338        target_page_reached = current_url.startswith(
339            "https://sso.academiccloud.de/simplesaml/module.php/"
340        )
341
342        results.append(target_page_reached)
343        return all(results)
344
345    def authentication(self):
346        """
347        Check if URL is available, if "AcademicID" button
348        is available and leads to login page
349        """
350
351        self.url = self.create_var_url(
352            EDU_URL,
353            self.instance,
354            subdomain="apps",
355            path="/authn/login?next=%2F",
356        )
357
358        return self._authentication()
checks = {'openedx_lms': ['prod', 'test'], 'openedx_cms': ['prod', 'test'], 'authentication': ['prod', 'test']}
def openedx_lms(self):
288    def openedx_lms(self):
289        """
290        Check if the main page is loaded correctly.
291        This is done by checking if the DFG logo is present.
292        """
293
294        self.url = self.create_var_url(
295            EDU_URL, self.instance, subdomain="teacher"
296        )
297        self.selenium.get(self.url)
298        return self._openedx_lms()

Check if the main page is loaded correctly. This is done by checking if the DFG logo is present.

def openedx_cms(self):
316    def openedx_cms(self):
317        """
318        Check if Educational Portal is Working
319        This is achieved by checking for the appearance of the logo
320        """
321
322        self.url = self.create_var_url(
323            EDU_URL, self.instance, subdomain="teacher"
324        )
325
326        return self._openedx_cms()

Check if Educational Portal is Working This is achieved by checking for the appearance of the logo

def authentication(self):
345    def authentication(self):
346        """
347        Check if URL is available, if "AcademicID" button
348        is available and leads to login page
349        """
350
351        self.url = self.create_var_url(
352            EDU_URL,
353            self.instance,
354            subdomain="apps",
355            path="/authn/login?next=%2F",
356        )
357
358        return self._authentication()

Check if URL is available, if "AcademicID" button is available and leads to login page

class CheckerOneStop4All(CheckerBase):
361class CheckerOneStop4All(CheckerBase):
362    # define checks to run in `run_checks` AND
363    # define for which instances to run them
364    checks = {
365        "main_page": ["prod", "test"],
366        "number_of_entities": ["prod"],
367        "involvement": ["prod", "test"],
368        "support_form": ["prod", "test"],
369        "captcha_in_support_form": ["prod", "test"],
370        "solr": ["prod", "test"],
371    }
372
373    def __init__(self, url=None, instance=None, *args, **kwargs):
374        super().__init__(url=url, instance=instance, *args, **kwargs)
375
376        self.url = self.create_var_url(O4A_URL, self.instance)
377
378        self.shadow_root = "onestop4all-app"
379
380    @resolve_url
381    def main_page(self):
382        """
383        Check if the main page is loaded correctly.
384        This is done by checking if the DFG logo is present.
385        """
386        result = self.selenium.find_by_css(
387            css='img[src="/dfg-logo.svg"]', elem=self.shadow_host
388        )
389        return bool(result)
390
391    @resolve_url
392    def number_of_entities(self):
393        """
394        Check if the number of entities is correct.
395        By checking if there is the correct amount of buttons on the webpage.
396        """
397        results = self.selenium.find_by_css(
398            css="div.resourceEntries",
399            elem=self.shadow_host,
400            as_list=True,
401        )
402        return len(results) == O4A_ENTITIES_COUNT
403
404    @resolve_url
405    def involvement(self):
406        """
407        Check if the buttons withing involvement section is loaded correctly.
408        This is simply done, by checking if there are any buttons.
409        """
410        results = self.selenium.find_by_css(
411            css="div.get-involved div.overlap > img",
412            elem=self.shadow_host,
413            as_list=True,
414        )
415        return len(results) > 0
416
417    @resolve_url
418    def support_form(self, close_modal=True):
419        """
420        Check if the support form is loaded correctly.
421        This is done by checking if the subject input field is present.
422        """
423        # try to find the support form button
424        support_form_button = self.selenium.find_by_text(
425            css=".chakra-link",
426            text="user Support",
427            elem=self.shadow_host,
428            case_sensitive=False,
429        )
430
431        # stop check if no support form button was found
432        if not support_form_button:
433            return False
434
435        # click on the support form button to open modal window
436        support_form_button.click()
437
438        subject = self.selenium.find_by_css(
439            css="input[name='subject']", elem=self.shadow_host
440        )
441        if subject and close_modal:
442            # close the modal window finally
443            self.selenium.find_by_css(
444                css="button[aria-label='Close']", elem=self.shadow_host
445            ).click()
446        return bool(subject)
447
448    @resolve_url
449    def captcha_in_support_form(self):
450        """
451        Check if the CAPTCHA is loaded correctly in the support form.
452        This is done by:
453            1. checking if the CAPTCHA checkbox is present
454            2. clicking on the CAPTCHA checkbox
455            3. checking if the CAPTCHA input field is present AND
456                its value is not empty
457        """
458        if self.support_form(close_modal=False):
459            altcha_checkbox = self.selenium.wait_until(
460                css="input#altcha_checkbox",
461                elem=self.shadow_host,
462            )
463            if altcha_checkbox:
464                altcha_checkbox.click()
465                altcha_input = self.selenium.wait_until(
466                    css="input[type='hidden'][name='altcha']",
467                    elem=self.shadow_host,
468                )
469                if altcha_input and altcha_input.get_attribute("value") != "":
470                    return True
471        return False
472
473    @property
474    def _solr_url(self):
475        return f"{self.url.rstrip('/')}/{O4A_SOLR_SUBPATH.lstrip('/')}"
476
477    @resolve_url
478    def solr(self):
479        """
480        Check if the Solr login page is loaded correctly.
481        This is done by checking if the Solr logo is present.
482        """
483        self.selenium.get(self._solr_url)
484        logo = self.selenium.find_by_css(css="a#solr span")
485        return bool(logo)
CheckerOneStop4All(url=None, instance=None, *args, **kwargs)
373    def __init__(self, url=None, instance=None, *args, **kwargs):
374        super().__init__(url=url, instance=instance, *args, **kwargs)
375
376        self.url = self.create_var_url(O4A_URL, self.instance)
377
378        self.shadow_root = "onestop4all-app"
checks = {'main_page': ['prod', 'test'], 'number_of_entities': ['prod'], 'involvement': ['prod', 'test'], 'support_form': ['prod', 'test'], 'captcha_in_support_form': ['prod', 'test'], 'solr': ['prod', 'test']}
url
shadow_root
def main_page(self, *args, **kwargs):
26    def wrap(self, *args, **kwargs):
27        current_url = self.selenium.get_url()
28        if current_url != self.url:
29            try:
30                self.selenium.get(self.url)
31                if getattr(self, "shadow_root", None):
32                    self.shadow_host = self.selenium.get_shadow_root(
33                        self.shadow_root
34                    )
35            except Exception as e:
36                log.error(f"Unable to open URL: {self.url}")
37                log.error(e)
38                return False
39
40            return func(self, *args, **kwargs)
41        else:
42            return func(self, *args, **kwargs)

Check if the main page is loaded correctly. This is done by checking if the DFG logo is present.

def number_of_entities(self, *args, **kwargs):
26    def wrap(self, *args, **kwargs):
27        current_url = self.selenium.get_url()
28        if current_url != self.url:
29            try:
30                self.selenium.get(self.url)
31                if getattr(self, "shadow_root", None):
32                    self.shadow_host = self.selenium.get_shadow_root(
33                        self.shadow_root
34                    )
35            except Exception as e:
36                log.error(f"Unable to open URL: {self.url}")
37                log.error(e)
38                return False
39
40            return func(self, *args, **kwargs)
41        else:
42            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.

def involvement(self, *args, **kwargs):
26    def wrap(self, *args, **kwargs):
27        current_url = self.selenium.get_url()
28        if current_url != self.url:
29            try:
30                self.selenium.get(self.url)
31                if getattr(self, "shadow_root", None):
32                    self.shadow_host = self.selenium.get_shadow_root(
33                        self.shadow_root
34                    )
35            except Exception as e:
36                log.error(f"Unable to open URL: {self.url}")
37                log.error(e)
38                return False
39
40            return func(self, *args, **kwargs)
41        else:
42            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.

def support_form(self, *args, **kwargs):
26    def wrap(self, *args, **kwargs):
27        current_url = self.selenium.get_url()
28        if current_url != self.url:
29            try:
30                self.selenium.get(self.url)
31                if getattr(self, "shadow_root", None):
32                    self.shadow_host = self.selenium.get_shadow_root(
33                        self.shadow_root
34                    )
35            except Exception as e:
36                log.error(f"Unable to open URL: {self.url}")
37                log.error(e)
38                return False
39
40            return func(self, *args, **kwargs)
41        else:
42            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.

def captcha_in_support_form(self, *args, **kwargs):
26    def wrap(self, *args, **kwargs):
27        current_url = self.selenium.get_url()
28        if current_url != self.url:
29            try:
30                self.selenium.get(self.url)
31                if getattr(self, "shadow_root", None):
32                    self.shadow_host = self.selenium.get_shadow_root(
33                        self.shadow_root
34                    )
35            except Exception as e:
36                log.error(f"Unable to open URL: {self.url}")
37                log.error(e)
38                return False
39
40            return func(self, *args, **kwargs)
41        else:
42            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

def solr(self, *args, **kwargs):
26    def wrap(self, *args, **kwargs):
27        current_url = self.selenium.get_url()
28        if current_url != self.url:
29            try:
30                self.selenium.get(self.url)
31                if getattr(self, "shadow_root", None):
32                    self.shadow_host = self.selenium.get_shadow_root(
33                        self.shadow_root
34                    )
35            except Exception as e:
36                log.error(f"Unable to open URL: {self.url}")
37                log.error(e)
38                return False
39
40            return func(self, *args, **kwargs)
41        else:
42            return func(self, *args, **kwargs)

Check if the Solr login page is loaded correctly. This is done by checking if the Solr logo is present.