#!/usr/bin/env python3 """ Autofill-Script fuer das IBO-Angular-Formular (ng-zorro / Formly). Fuellt alle Inputfelder mit Mock-Daten. Weil es ein Angular-Formular ist, reicht ein einfaches value-Setzen nicht -> es werden echte input/change-Events via Selenium ausgeloest, damit Angular die Werte uebernimmt. Setup: pip install selenium (Chrome + passender chromedriver muessen installiert sein; bei aktuellem Selenium 4 wird der Driver automatisch verwaltet.) Benutzung: python autofill.py "http://localhost:4200/dein/formular" # oder eine lokale Datei: python autofill.py "file:///Users/timu/programming/momentrum/projekte/ibo/index.html" """ import sys import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # --------------------------------------------------------------------------- # Felder werden aus config.json (application) gebaut. Siehe config.py. # Die formly-IDs stammen aus dem gerenderten Formular (data-cy / id). # --------------------------------------------------------------------------- import config as _config def _build_fields(app): t1, t2 = app["tenant1"], app["tenant2"] text_fields = { # Vorgang "formly_2_input_reserveNumber_0": app["reserveNumber"], "formly_2_input_validUntil_1": app["validUntil"], # Mieter 1 "formly_3_input_firstName_0": t1["firstName"], "formly_3_input_lastName_1": t1["lastName"], "formly_3_input_dateOfBirth_2": t1["dateOfBirth"], "formly_4_input_street_0": t1["street"], "formly_4_input_housenumber_1": t1["housenumber"], "formly_4_input_zipcode_2": t1["zipcode"], "formly_4_input_city_3": t1["city"], "formly_5_input_phoneNumberPrivate_0": t1["phonePrivate"], "formly_5_input_phoneNumberBusiness_1": t1["phoneBusiness"], # Mieter 2 "formly_6_input_firstName2_0": t2["firstName"], "formly_6_input_lastName2_1": t2["lastName"], "formly_6_input_dateOfBirth2_2": t2["dateOfBirth"], "formly_7_input_street2_0": t2["street"], "formly_7_input_housenumber2_1": t2["housenumber"], "formly_7_input_zipcode2_2": t2["zipcode"], "formly_7_input_city2_3": t2["city"], "formly_8_input_phoneNumberPrivate2_0": t2["phonePrivate"], "formly_8_input_phoneNumberBusiness2_1": t2["phoneBusiness"], } checkboxes = [] if app.get("secondTenant", True): checkboxes.append("formly_5_checkbox_secondTenant_5") if app.get("consent", True): checkboxes += ["formly_18_checkbox_dataCorrectness_20", "formly_18_checkbox_dataPrivacy_21"] selects = {"formly_2_select_numberRooms_2": str(app["numberRooms"])} return text_fields, checkboxes, selects TEXT_FIELDS, CHECKBOXES, SELECTS = _build_fields(_config.CFG["application"]) def reload_fields(): """Uebernimmt geaenderte config.json-Werte.""" global TEXT_FIELDS, CHECKBOXES, SELECTS TEXT_FIELDS, CHECKBOXES, SELECTS = _build_fields( _config.reload()["application"]) # --------------------------------------------------------------------------- # Fuell-Logik # --------------------------------------------------------------------------- def fill_text(driver, wait, field_id, value): """Fuellt ein Textfeld und loest Angular-Events aus.""" try: el = wait.until(EC.presence_of_element_located((By.ID, field_id))) driver.execute_script("arguments[0].scrollIntoView({block:'center'});", el) el.clear() el.click() el.send_keys(value) # blur -> Angular validiert / uebernimmt el.send_keys(Keys.TAB) print(f" [ok] {field_id} = {value}") except Exception as e: print(f" [skip] {field_id}: {e.__class__.__name__}") def set_checkbox(driver, field_id, checked=True): try: el = driver.find_element(By.ID, field_id) driver.execute_script("arguments[0].scrollIntoView({block:'center'});", el) if el.is_selected() != checked: driver.execute_script("arguments[0].click();", el) print(f" [ok] checkbox {field_id} -> {checked}") except Exception as e: print(f" [skip] checkbox {field_id}: {e.__class__.__name__}") def select_option(driver, wait, field_id, option_text): """Bedient ein @ng-select/ng-select Dropdown (nicht ng-zorro!). Struktur: Input role=combobox oeffnet ein .ng-dropdown-panel mit Optionen als