*** Settings *** Resource ${CURDIR}/../resources/common.resource Resource ${CURDIR}/../resources/auth.resource Suite Setup Wait For Backend Health *** Test Cases *** Setup Page Renders All Form Fields [Documentation] Verify all setup wizard fields are present and labelled correctly. New Browser chromium headless=${TRUE} New Context New Page Go To ${FRONTEND_URL}/setup Wait For Elements State css=form visible timeout=15s # Hidden username field for password manager (aria-hidden, not focusable). Get Element States css=input[autocomplete="username"] contains hidden # Required fields. Wait For Elements State css=[aria-label="Master Password"] visible timeout=5s Wait For Elements State css=[aria-label="Confirm Password"] visible timeout=5s Wait For Elements State css=[aria-label="Database Path"] visible timeout=5s Wait For Elements State css=[aria-label="fail2ban Socket Path"] visible timeout=5s Wait For Elements State css=[aria-label="Timezone"] visible timeout=5s Wait For Elements State css=[aria-label="Session Duration (minutes)"] visible timeout=5s # Submit button. Wait For Elements State css=button[type="submit"] visible timeout=5s Get Text css=button[type="submit"] equals Complete Setup Close Browser Password Strength Indicator Updates On Input [Documentation] The four-segment strength bar and rule count reflect password complexity. New Browser chromium headless=${TRUE} New Context New Page Go To ${FRONTEND_URL}/setup Wait For Elements State css=input[aria-label="Master Password"] visible timeout=15s # Verify initial strength text shows "0 of 4 rules satisfied". ${text_0}= Get Text xpath=//div[@aria-live="polite"] Should Contain ${text_0} 0 of 4 rules satisfied Log Initial strength: ${text_0} # Type a weak password — only length (>=8) rule satisfied. Fill Text css=input[aria-label="Master Password"] longpassword # Verify strength text updates to "1 of 4 rules satisfied" (only length rule, no uppercase/number/special). ${text_1}= Get Text xpath=//div[@aria-live="polite"] Should Contain ${text_1} 1 of 4 rules satisfied Log After longpassword: ${text_1} Close Browser Password Mismatch Shows Validation Error [Documentation] Submitting with non-matching passwords surfaces an error on Confirm Password. New Browser chromium headless=${TRUE} New Context New Page Go To ${FRONTEND_URL}/setup Wait For Elements State css=input[aria-label="Master Password"] visible timeout=15s Fill Text css=input[aria-label="Master Password"] Hallo123! Fill Text css=input[aria-label="Confirm Password"] Different123! Click css=button[type="submit"] Wait For Elements State xpath=//*[@aria-label="Confirm Password"]/ancestor::*[contains(@class,"field")]//*[@role="alert"] visible timeout=10s ${msg}= Get Text xpath=//*[@aria-label="Confirm Password"]/ancestor::*[contains(@class,"field")]//*[@role="alert"] timeout=10s Should Be Equal As Strings ${msg} Passwords do not match. Close Browser Empty Required Fields Show Validation Errors [Documentation] Submitting with blank required fields shows field-level error messages. New Browser chromium headless=${TRUE} New Context New Page Go To ${FRONTEND_URL}/setup Wait For Elements State css=input[aria-label="Master Password"] visible timeout=15s Click css=button[type="submit"] Wait For Elements State css=[aria-label="Master Password"] attached timeout=5s ${msg}= Get Text xpath=//*[@aria-label="Master Password"]/ancestor::*[contains(@class,"field")]//*[@role="alert"] Should Be Equal As Strings ${msg} Password is required. Wait For Elements State css=[aria-label="Database Path"] attached timeout=5s ${msg}= Get Text xpath=//*[@aria-label="Database Path"]/ancestor::*[contains(@class,"field")]//*[@role="alert"] Should Be Equal As Strings ${msg} Database path is required. Wait For Elements State css=[aria-label="fail2ban Socket Path"] attached timeout=5s ${msg}= Get Text xpath=//*[@aria-label="fail2ban Socket Path"]/ancestor::*[contains(@class,"field")]//*[@role="alert"] Should Be Equal As Strings ${msg} Socket path is required. Close Browser Invalid Session Duration Shows Validation Error [Documentation] Session duration below 1 minute triggers a validation error. New Browser chromium headless=${TRUE} New Context New Page Go To ${FRONTEND_URL}/setup Wait For Elements State css=input[aria-label="Master Password"] visible timeout=15s Fill Text css=input[aria-label="Master Password"] Hallo123! Fill Text css=input[aria-label="Confirm Password"] Hallo123! Fill Text css=input[aria-label="Database Path"] bangui.db Fill Text css=input[aria-label="fail2ban Socket Path"] /var/run/fail2ban/fail2ban.sock Fill Text css=input[aria-label="Session Duration (minutes)"] 0 Click css=button[type="submit"] Wait For Elements State css=[aria-label="Session Duration (minutes)"] attached timeout=5s ${msg}= Get Text xpath=//*[@aria-label="Session Duration (minutes)"]/ancestor::*[contains(@class,"field")]//*[@role="alert"] Should Be Equal As Strings ${msg} Session duration must be at least 1 minute. Close Browser Incomplete Password Shows Complexity Error [Documentation] Submitting a password that meets length but not all rules shows complexity error. New Browser chromium headless=${TRUE} New Context New Page Go To ${FRONTEND_URL}/setup Wait For Elements State css=input[aria-label="Master Password"] visible timeout=15s Fill Text css=input[aria-label="Master Password"] short Click css=button[type="submit"] Wait For Elements State xpath=//*[@aria-label="Master Password"]/ancestor::*[contains(@class,"field")]//*[@role="alert"] visible timeout=10s ${msg}= Get Text xpath=//*[@aria-label="Master Password"]/ancestor::*[contains(@class,"field")]//*[@role="alert"] Should Contain ${msg} Password must meet all complexity requirements. Close Browser Setup Completes Successfully And Redirects To Login [Documentation] Filling all fields and submitting completes setup and navigates to /login. New Browser chromium headless=${TRUE} New Context New Page # Use API to check if setup is already complete; reset if needed. ${status_resp}= GET ${BACKEND_URL}/api/v1/setup ${status_body}= Set Variable ${status_resp.json()} Log Setup complete: ${status_body}[completed] Go To ${FRONTEND_URL}/setup Wait For Elements State css=input[aria-label="Master Password"] visible timeout=15s Fill Text css=input[aria-label="Master Password"] Hallo123! Fill Text css=input[aria-label="Confirm Password"] Hallo123! Fill Text css=input[aria-label="Database Path"] bangui.db Fill Text css=input[aria-label="fail2ban Socket Path"] /var/run/fail2ban/fail2ban.sock Fill Text css=input[aria-label="Timezone"] UTC Fill Text css=input[aria-label="Session Duration (minutes)"] 60 Click css=button[type="submit"] # Wait for redirect to /login (or / if already authenticated). ${current_url}= Get URL IF "login" not in """${current_url}""" # Poll until URL matches /login. ${deadline}= Evaluate time.time() + 15 WHILE True ${now}= Evaluate time.time() IF ${now} >= ${deadline} BREAK ${url}= Get URL IF "login" in """${url}""" BREAK Sleep 0.5 END END # Verify setup is now marked complete. ${new_status_resp}= GET ${BACKEND_URL}/api/v1/setup ${new_status_body}= Set Variable ${new_status_resp.json()} Should Be True ${new_status_body}[completed] Close Browser