- Docs/Tasks.md: document 122 E2E test failures (fail2ban missing) - e2e/proxy_server.py: add HTTP proxy for frontend dev server - e2e/resources/common.resource: update test resource
98 lines
4.2 KiB
Plaintext
98 lines
4.2 KiB
Plaintext
*** Settings ***
|
|
Library Browser
|
|
Library RequestsLibrary
|
|
Library Process
|
|
Library String
|
|
Library Collections
|
|
Library DateTime
|
|
|
|
*** Variables ***
|
|
${FRONTEND_URL} http://localhost:5173
|
|
${BACKEND_URL} http://localhost:8000
|
|
${TEST_PASSWORD} Hallo123!
|
|
${XFF_HEADER} ${EMPTY}
|
|
|
|
*** Keywords ***
|
|
Wait For Backend Health
|
|
[Documentation] Polls /api/v1/health/live until 200 or timeout.
|
|
... Uses the liveness probe because it is independent of
|
|
... fail2ban availability, unlike the combined /api/v1/health
|
|
... which returns 503 when fail2ban is offline.
|
|
[Arguments] ${timeout}=120 ${interval}=5
|
|
${deadline}= Evaluate time.time() + ${timeout}
|
|
WHILE True
|
|
${now}= Evaluate time.time()
|
|
IF ${now} >= ${deadline} FAIL Backend did not become healthy within ${timeout} seconds
|
|
${response}= GET ${BACKEND_URL}/api/v1/health/live expected_status=any
|
|
IF ${response.status_code} == 200 BREAK
|
|
Sleep ${interval}
|
|
END
|
|
Log Backend is healthy.
|
|
|
|
Wait For Frontend
|
|
[Documentation] Polls ${FRONTEND_URL} until HTTP 200 or timeout.
|
|
[Arguments] ${timeout}=60 ${interval}=2
|
|
${deadline}= Evaluate time.time() + ${timeout}
|
|
WHILE True
|
|
${now}= Evaluate time.time()
|
|
IF ${now} >= ${deadline} FAIL Frontend did not respond within ${timeout} seconds
|
|
${result}= Run Keyword And Return Status GET ${FRONTEND_URL} expected_status=any
|
|
IF ${result}
|
|
BREAK
|
|
END
|
|
Sleep ${interval}
|
|
END
|
|
Log Frontend is reachable.
|
|
|
|
Set Random Xff Header
|
|
[Documentation] Generates a fresh documentation-only IP for X-Forwarded-For
|
|
... to bypass per-IP rate limits. RFC5737 192.0.2.0/24.
|
|
${octet}= Evaluate random.randint(1, 254) modules=random
|
|
${ip}= Set Variable 192.0.2.${octet}
|
|
Set Suite Variable ${XFF_HEADER} ${ip}
|
|
RETURN ${ip}
|
|
|
|
Generate Unique Ip
|
|
[Documentation] Returns a fresh IP from RFC5737 203.0.113.0/24.
|
|
${a}= Evaluate random.randint(1, 254) modules=random
|
|
${b}= Evaluate random.randint(1, 254) modules=random
|
|
${ip}= Set Variable 203.0.113.${a}
|
|
RETURN ${ip}
|
|
|
|
Generate Unique Jail Name
|
|
[Documentation] Returns a unique jail name with a timestamp suffix to avoid collisions.
|
|
${stamp}= Evaluate int(time.time()) modules=time
|
|
${name}= Set Variable test-jail-${stamp}
|
|
RETURN ${name}
|
|
|
|
Get First Active Jail Name
|
|
[Documentation] Returns the name of the first active jail via the API.
|
|
... Requires the caller to have an authenticated session named 'bangsess'.
|
|
${headers}= Create Dictionary X-BanGUI-Request 1
|
|
IF "${XFF_HEADER}" != ""
|
|
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
|
END
|
|
${resp}= GET On Session bangsess /api/v1/jails headers=${headers} expected_status=200
|
|
${items}= Set Variable ${resp.json()}[items]
|
|
${count}= Get Length ${items}
|
|
IF ${count} == 0 FAIL No active jails found via API
|
|
${first}= Get From List ${items} 0
|
|
RETURN ${first}[name]
|
|
|
|
Page Should Contain
|
|
[Documentation] Convenience wrapper around Browser's Get Text.
|
|
... Use a locator (default: body) and a substring; passes if substring is present.
|
|
[Arguments] ${text} ${locator}=body
|
|
${found}= Run Keyword And Return Status Get Text css=${locator} contains ${text}
|
|
Should Be True ${found} msg=Page text '${text}' not found in ${locator}
|
|
|
|
Page Should Not Contain
|
|
[Documentation] Inverse: passes if substring is absent from locator.
|
|
[Arguments] ${text} ${locator}=body
|
|
${found}= Run Keyword And Return Status Get Text css=${locator} contains ${text}
|
|
Should Not Be True ${found} msg=Page text '${text}' unexpectedly found in ${locator}
|
|
|
|
Reset Application State
|
|
[Documentation] Stub: not all deployments expose a reset endpoint.
|
|
... Logs the action and lets tests proceed with current state.
|
|
Log Reset Application State called (no-op in default stack) |