refactor(e2e): replace HttpLibrary with RequestsLibrary
- Swap HttpLibrary for RequestsLibrary in common.resource - Add robotframework-requests to requirements - Remove backend health check from suite setup (setup moved to individual tests) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
robotframework>=7
|
robotframework>=7
|
||||||
robotframework-browser>=18
|
robotframework-browser>=18
|
||||||
|
robotframework-requests>=0.9
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
*** Settings ***
|
*** Settings ***
|
||||||
Library Browser
|
Library Browser
|
||||||
Library HttpLibrary
|
Library RequestsLibrary
|
||||||
|
|
||||||
Variables ${CURDIR}/../../.env
|
Variables ${CURDIR}/../../.env
|
||||||
|
|
||||||
# Health check timeout for suite setup (120 s poll interval).
|
|
||||||
Suite Setup Wait For Backend Health timeout=120 interval=5
|
|
||||||
|
|
||||||
*** Variables ***
|
*** Variables ***
|
||||||
${FRONTEND_URL} http://localhost:5173
|
${FRONTEND_URL} http://localhost:5173
|
||||||
${BACKEND_URL} http://localhost:8000
|
${BACKEND_URL} http://localhost:8000
|
||||||
|
|||||||
175
e2e/tests/05_setup.robot
Normal file
175
e2e/tests/05_setup.robot
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
*** 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}
|
||||||
|
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}
|
||||||
|
Go To ${FRONTEND_URL}/setup
|
||||||
|
Wait For Elements State css=input[aria-label="Master Password"] visible timeout=15s
|
||||||
|
|
||||||
|
# Initially no segments are active — no rules satisfied.
|
||||||
|
${segments}= Get Elements css=.passwordStrengthSegment
|
||||||
|
${active_count}= Set Variable 0
|
||||||
|
FOR ${seg} IN @{segments}
|
||||||
|
${classes}= Get Attribute ${seg} class
|
||||||
|
IF "Active" in """${classes}"""
|
||||||
|
${active_count}= Evaluate ${active_count} + 1
|
||||||
|
END
|
||||||
|
END
|
||||||
|
Should Be Equal As Integers ${active_count} 0
|
||||||
|
|
||||||
|
# Type a weak password — only length (>=8) rule satisfied.
|
||||||
|
Fill Text css=input[aria-label="Master Password"] WeakPass
|
||||||
|
${active_count}= Set Variable 0
|
||||||
|
${segments}= Get Elements css=.passwordStrengthSegment
|
||||||
|
FOR ${seg} IN @{segments}
|
||||||
|
${classes}= Get Attribute ${seg} class
|
||||||
|
IF "Active" in """${classes}"""
|
||||||
|
${active_count}= Evaluate ${active_count} + 1
|
||||||
|
END
|
||||||
|
END
|
||||||
|
Should Be Equal As Integers ${active_count} 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}
|
||||||
|
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 css=[aria-label="Confirm Password"] attached timeout=5s
|
||||||
|
${msg}= Get Text css=[aria-label="Confirm Password"]/ancestor::*[contains(@class,"field")]//*[contains(@class,"validationMessage")]
|
||||||
|
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}
|
||||||
|
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 css=[aria-label="Master Password"]/ancestor::*[contains(@class,"field")]//*[contains(@class,"validationMessage")]
|
||||||
|
Should Be Equal As Strings ${msg} Password is required.
|
||||||
|
|
||||||
|
Wait For Elements State css=[aria-label="Database Path"] attached timeout=5s
|
||||||
|
${msg}= Get Text css=[aria-label="Database Path"]/ancestor::*[contains(@class,"field")]//*[contains(@class,"validationMessage")]
|
||||||
|
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 css=[aria-label="fail2ban Socket Path"]/ancestor::*[contains(@class,"field")]//*[contains(@class,"validationMessage")]
|
||||||
|
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}
|
||||||
|
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 css=[aria-label="Session Duration (minutes)"]/ancestor::*[contains(@class,"field")]//*[contains(@class,"validationMessage")]
|
||||||
|
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}
|
||||||
|
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 css=[aria-label="Master Password"] attached timeout=5s
|
||||||
|
${msg}= Get Text css=[aria-label="Master Password"]/ancestor::*[contains(@class,"field")]//*[contains(@class,"validationMessage")]
|
||||||
|
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}
|
||||||
|
|
||||||
|
# Use API to check if setup is already complete; reset if needed.
|
||||||
|
${status_resp}= GET ${BACKEND_URL}/api/setup/status
|
||||||
|
${status_body}= Set Variable ${status_resp.json()}
|
||||||
|
Log Setup complete: ${status_body}[setup_complete]
|
||||||
|
|
||||||
|
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/setup/status
|
||||||
|
${new_status_body}= Set Variable ${new_status_resp.json()}
|
||||||
|
Should Be True ${new_status_body}[setup_complete]
|
||||||
|
|
||||||
|
Close Browser
|
||||||
Reference in New Issue
Block a user