test(e2e): split suite by feature area with shared resources
Restructure 5 existing .robot files into 10 numbered files, one per feature area in Docs/Features.md. Each file is independently runnable. Add api.resource + data.resource for CSRF/XFF-aware wrappers and RFC5737 IP generators. Coverage: 110 new tests across login, dashboard, map, jails, config, history, blocklists, layout. Uses existing data-testid/aria-label/role selectors only — no frontend changes. Tests bypass per-IP rate limits via X-Forwarded-For header rotation. Hard rule preserved: failures are findings, never app-code fixes.
This commit is contained in:
161
e2e/tests/09_blocklists.robot
Normal file
161
e2e/tests/09_blocklists.robot
Normal file
@@ -0,0 +1,161 @@
|
||||
*** Settings ***
|
||||
Documentation External Blocklist Importer feature coverage — sources CRUD,
|
||||
... URL validation, schedule, preview, import log, delete restriction.
|
||||
Resource ${CURDIR}/../resources/common.resource
|
||||
Resource ${CURDIR}/../resources/auth.resource
|
||||
Suite Setup Wait For Backend Health
|
||||
|
||||
*** Test Cases ***
|
||||
Blocklists Page Renders
|
||||
Login As Admin
|
||||
Go To ${FRONTEND_URL}/blocklists
|
||||
Wait For Elements State css=[data-testid="blocklists-page"] visible timeout=15s
|
||||
Page Should Contain Blocklists
|
||||
Close Browser
|
||||
|
||||
Blocklists Sources List Endpoint
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${resp}= GET On Session bangsess /api/v1/blocklists
|
||||
... headers=${headers} expected_status=any
|
||||
Should Be True ${resp.status_code} in [200, 204]
|
||||
|
||||
Blocklist Source Create Rejects Invalid Scheme
|
||||
[Documentation] ftp://, file://, gopher:// must be rejected.
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${stamp}= Evaluate int(time.time()) modules=time
|
||||
${payload}= Create Dictionary
|
||||
... name test-scheme-${stamp}
|
||||
... url ftp://example.com/list.txt
|
||||
... enabled ${TRUE}
|
||||
${resp}= POST On Session bangsess /api/v1/blocklists
|
||||
... json=${payload} headers=${headers} expected_status=any
|
||||
Should Be Equal As Integers ${resp.status_code} 400
|
||||
... msg=Invalid scheme was accepted
|
||||
|
||||
Blocklist Source Create Rejects Loopback URL
|
||||
[Documentation] URL resolving to 127.0.0.1 must be rejected (SSRF guard).
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${stamp}= Evaluate int(time.time()) modules=time
|
||||
${payload}= Create Dictionary
|
||||
... name test-loopback-${stamp}
|
||||
... url http://127.0.0.1/list.txt
|
||||
... enabled ${TRUE}
|
||||
${resp}= POST On Session bangsess /api/v1/blocklists
|
||||
... json=${payload} headers=${headers} expected_status=any
|
||||
Should Be Equal As Integers ${resp.status_code} 400
|
||||
... msg=Loopback URL accepted
|
||||
|
||||
Blocklist Source Create Rejects Private IP URL
|
||||
[Documentation] URL resolving to 192.168.x.x must be rejected.
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${stamp}= Evaluate int(time.time()) modules=time
|
||||
${payload}= Create Dictionary
|
||||
... name test-private-${stamp}
|
||||
... url http://192.168.1.1/list.txt
|
||||
... enabled ${TRUE}
|
||||
${resp}= POST On Session bangsess /api/v1/blocklists
|
||||
... json=${payload} headers=${headers} expected_status=any
|
||||
Should Be Equal As Integers ${resp.status_code} 400
|
||||
... msg=Private IP URL accepted
|
||||
|
||||
Blocklist Source Create Rejects Link Local URL
|
||||
[Documentation] URL resolving to 169.254.x.x must be rejected.
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${stamp}= Evaluate int(time.time()) modules=time
|
||||
${payload}= Create Dictionary
|
||||
... name test-linklocal-${stamp}
|
||||
... url http://169.254.169.254/list.txt
|
||||
... enabled ${TRUE}
|
||||
${resp}= POST On Session bangsess /api/v1/blocklists
|
||||
... json=${payload} headers=${headers} expected_status=any
|
||||
Should Be Equal As Integers ${resp.status_code} 400
|
||||
... msg=Link-local URL accepted
|
||||
|
||||
Blocklist Schedule Endpoint Returns Config
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${resp}= GET On Session bangsess /api/v1/blocklists/schedule
|
||||
... headers=${headers} expected_status=any
|
||||
Should Be True ${resp.status_code} in [200, 204]
|
||||
|
||||
Blocklist Schedule Update Works
|
||||
[Documentation] PUT /api/v1/blocklists/schedule updates the import schedule.
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${payload}= Create Dictionary frequency daily hour 3 minute 0
|
||||
${resp}= PUT On Session bangsess /api/v1/blocklists/schedule
|
||||
... json=${payload} headers=${headers} expected_status=any
|
||||
Should Be True ${resp.status_code} in [200, 204]
|
||||
|
||||
Blocklist Manual Import Endpoint Reachable
|
||||
[Documentation] POST /api/v1/blocklists/import triggers a manual import.
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${resp}= POST On Session bangsess /api/v1/blocklists/import
|
||||
... json=${EMPTY} headers=${headers} expected_status=any
|
||||
Should Be True ${resp.status_code} in [200, 202, 429] msg=Unexpected import status: ${resp.status_code}
|
||||
|
||||
Blocklist Import Log Endpoint Returns Paginated Data
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${resp}= GET On Session bangsess /api/v1/blocklists/log
|
||||
... headers=${headers} expected_status=any
|
||||
Should Be True ${resp.status_code} in [200, 204]
|
||||
|
||||
Blocklist Delete Non Existent Returns 404
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
${resp}= DELETE On Session bangsess /api/v1/blocklists/999999
|
||||
... headers=${headers} expected_status=any
|
||||
Should Be Equal As Integers ${resp.status_code} 404
|
||||
|
||||
Blocklist Create And Delete Cycle
|
||||
[Documentation] Create a valid blocklist source then delete it.
|
||||
Set Random Xff Header
|
||||
Login Via HTTP
|
||||
${headers}= Create Dictionary X-BanGUI-Request 1
|
||||
Set To Dictionary ${headers} X-Forwarded-For ${XFF_HEADER}
|
||||
# Create via fetch POST (relative to backend) so we can use a public IP.
|
||||
${stamp}= Evaluate int(time.time()) modules=time
|
||||
${payload}= Create Dictionary
|
||||
... name cycle-test-${stamp}
|
||||
... url https://lists.blocklist.de/lists/ssh.txt
|
||||
... enabled ${FALSE}
|
||||
${create_resp}= POST On Session bangsess /api/v1/blocklists
|
||||
... json=${payload} headers=${headers} expected_status=any
|
||||
IF ${create_resp.status_code} in [200, 201]
|
||||
${body}= Set Variable ${create_resp.json()}
|
||||
${id}= Set Variable ${body}[id]
|
||||
# If source had import logs, delete would return 409. With no logs it should succeed.
|
||||
${del_resp}= DELETE On Session bangsess /api/v1/blocklists/${id}
|
||||
... headers=${headers} expected_status=any
|
||||
Should Be True ${del_resp.status_code} in [200, 204, 409]
|
||||
... msg=Unexpected delete status: ${del_resp.status_code}
|
||||
ELSE
|
||||
Log Could not create blocklist source (status ${create_resp.status_code}); skipping delete cycle
|
||||
END
|
||||
Reference in New Issue
Block a user