This commit is contained in:
2026-06-21 12:32:44 +02:00
parent 107158eb04
commit be3e180137
27 changed files with 5037 additions and 20 deletions

View File

@@ -0,0 +1,146 @@
*** Settings ***
Documentation Common shared resources for Aniworld Robot Framework tests.
... Provides keywords for server lifecycle, authentication, sessions, and cleanup.
Library Process
Library Browser
Library RequestsLibrary
Library JSONLibrary
Library OperatingSystem
Library String
Library Collections
Library DateTime
*** Variables ***
${BASE_URL} http://127.0.0.1:8765
${SERVER_HOST} 127.0.0.1
${SERVER_PORT} 8765
${SETUP_PASSWORD} TestPass123!
${BROWSER} chromium
${HEADLESS} True
${SERVER_PROCESS} ${EMPTY}
*** Keywords ***
# ---------------------------------------------------------------------------
# Server Lifecycle
# ---------------------------------------------------------------------------
Start Aniworld Server
[Documentation] Start the FastAPI uvicorn server as a background process.
${result}= Run Process conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app
... --host ${SERVER_HOST} --port ${SERVER_PORT}
... --no-access-log
... cwd=/home/lukas/Volume/repo/Aniworld
... stdout=${CURDIR}/../fixtures/server_stdout.log
... stderr=${CURDIR}/../fixtures/server_stderr.log
Set Suite Variable ${SERVER_PROCESS} ${result}
Sleep 3s
Stop Aniworld Server
[Documentation] Terminate the uvicorn server process and clean up log files.
Run Keyword And Ignore Error Terminate Process ${SERVER_PROCESS}
Run Keyword And Ignore Error Remove File ${CURDIR}/../fixtures/server_stdout.log
Run Keyword And Ignore Error Remove File ${CURDIR}/../fixtures/server_stderr.log
Wait For Server
[Documentation] Poll the health endpoint until the server responds with 200.
... Retries every 1 second for up to 30 seconds.
FOR ${i} IN RANGE 30
${resp}= Run Keyword And Ignore Error
... GET On Session anon /health expected_status=200
IF '${resp}[0]' == 'PASS'
RETURN
END
Sleep 1s
END
Fail Server did not become healthy within 30 seconds
Initialize Browser
[Documentation] Initialize Browser library with the configured browser and headless mode.
New Browser ${BROWSER} headless=${HEADLESS}
New Context viewport={'width': 1280, 'height': 720}
# ---------------------------------------------------------------------------
# HTTP Session Management
# ---------------------------------------------------------------------------
Create Anonymous Session
[Documentation] Create an unauthenticated HTTP session.
Create Session anon ${BASE_URL}
Create Authenticated Session
[Documentation] Create an authenticated HTTP session. Performs setup if needed, then logs in.
Create Anonymous Session
${configured}= Is Auth Configured
IF not ${configured}
Setup Master Password
END
${token}= Login And Get Token
Create Session auth ${BASE_URL} headers={'Authorization': 'Bearer ${token}'}
# ---------------------------------------------------------------------------
# Authentication Helpers
# ---------------------------------------------------------------------------
Is Auth Configured
[Documentation] Check if the master password has already been configured.
${resp}= GET On Session anon /api/auth/status expected_status=200
${json}= Convert String To Json ${resp.text}
${configured}= Get Value From Json ${json} $.configured
RETURN ${configured}[0]
Setup Master Password
[Documentation] Configure the master password via the setup endpoint.
${payload}= Create Dictionary
... master_password=${SETUP_PASSWORD}
... anime_directory=/tmp/aniworld_test_anime
... name=AniworldTest
... data_dir=data
... scheduler_enabled=False
... logging_level=INFO
... backup_enabled=False
${resp}= POST On Session anon /api/auth/setup json=${payload} expected_status=201
Should Be Equal As Integers ${resp.status_code} 201
Login And Get Token
[Documentation] Log in with the master password and return the JWT access token.
${payload}= Create Dictionary password=${SETUP_PASSWORD}
${resp}= POST On Session anon /api/auth/login json=${payload} expected_status=200
${json}= Convert String To Json ${resp.text}
${token}= Get Value From Json ${json} $.access_token
RETURN ${token}[0]
# ---------------------------------------------------------------------------
# State Reset
# ---------------------------------------------------------------------------
Reset Application State
[Documentation] Reset auth, config, and database state for test isolation.
... Calls internal cleanup endpoints if available; otherwise warns.
Run Keyword And Ignore Error POST On Session auth /api/admin/reset expected_status=200
# Fallback: clear local files
Run Keyword And Ignore Error Remove Directory /tmp/aniworld_test_anime recursive=True
Run Keyword And Ignore Error Create Directory /tmp/aniworld_test_anime
# ---------------------------------------------------------------------------
# Browser Navigation Helpers
# ---------------------------------------------------------------------------
Open Browser To Page
[Arguments] ${path}=/
[Documentation] Open a new page at the given path relative to BASE_URL.
New Page ${BASE_URL}${path}
Close Browser
[Documentation] Close all browser contexts and the browser itself.
Browser.Close Browser ALL
# ---------------------------------------------------------------------------
# Assertion Helpers
# ---------------------------------------------------------------------------
Response Should Contain Key
[Arguments] ${response} ${json_path}
[Documentation] Assert that the JSON response contains the given JSONPath key.
${json}= Convert String To Json ${response.text}
${values}= Get Value From Json ${json} ${json_path}
Should Not Be Empty ${values} Expected JSON path '${json_path}' not found in response
Response Should Have Status
[Arguments] ${response} ${expected_status}
[Documentation] Assert that the response status code matches the expected value.
Should Be Equal As Integers ${response.status_code} ${expected_status}