Starting process:
bash /home/lukas/Volume/repo/Aniworld/tests/robot/start_server.sh
${handle} = <Popen: returncode: None args: ['bash', '/home/lukas/Volume/repo/Aniworld/te...>
${handle}
bash
/home/lukas/Volume/repo/Aniworld/tests/robot/start_server.sh
cwd=/home/lukas/Volume/repo/Aniworld
stdout=/home/lukas/Volume/repo/Aniworld/tests/robot/resources/../fixtures/server_stdout.log
stderr=/home/lukas/Volume/repo/Aniworld/tests/robot/resources/../fixtures/server_stderr.log
Starts a new process on background.
${SERVER_PROCESS} = <Popen: returncode: None args: ['bash', '/home/lukas/Volume/repo/Aniworld/te...>
${SERVER_PROCESS}
${handle}
Makes a variable available everywhere within the scope of the current suite.
Slept 5 seconds.
5s
Pauses the test executed for the given time.
Start the FastAPI uvicorn server as a background process.
Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
anon
${BASE_URL}
Create Session: create a HTTP session to a server
Create an unauthenticated HTTP session.
GET Request : url=http://127.0.0.1:8765/health
path_url=/health
headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive'}
body=None
GET Response : url=http://127.0.0.1:8765/health
status=200, reason=OK
headers={'date': 'Fri, 26 Jun 2026 22:11:05 GMT', 'server': 'uvicorn', 'content-length': '583', 'content-type': 'application/json'}
body={"status":"healthy","timestamp":"2026-06-27T00:11:05.475722","version":"v1.4.17","service":"aniworld-api","series_app_initialized":true,"anime_directory_configured":true,"scheduler_next_run":"2026-06-27T03:00:00+02:00","scheduler_last_run":null,"checks":{"ffmpeg":{"status":"ok","message":"Found at /usr/bin/ffmpeg"},"dns_aniworld":{"status":"ok","message":"Resolved successfully"},"dns_tmdb":{"status":"ok","message":"Resolved successfully"},"anime_directory":{"status":"ok","message":"Directory exists and is writable: /tmp/aniworld_test_anime","path":"/tmp/aniworld_test_anime"}}}
anon
/health
expected_status=any
Sends a GET request on a previously created HTTP Session.
${resp} = ('PASS', <Response [200]>)
${resp}
GET On Session
anon
/health
expected_status=any
Runs the given keyword with the given arguments and ignores possible error.
${status_code} = 200
${status_code}
$resp[1].status_code
Evaluates the given expression in Python and returns the result.
1s
Pauses the test executed for the given time.
0
${i}
30
Server did not become healthy within 30 seconds
Fails the test with the given message and optionally alters its tags.
Poll the health endpoint until the server responds.
Accepts 200 or 503 (not configured yet) as valid responses.
Retries every 1 second for up to 30 seconds.
${payload} = {'master_password': 'TestPass123!', 'anime_directory': '/tmp/aniworld_test_anime', 'name': 'AniworldTest', 'data_dir': 'data', 'scheduler_enabled': 'False', 'logging_level': 'INFO', 'backup_enabled': ...
${payload}
master_password=${SETUP_PASSWORD}
anime_directory=/tmp/aniworld_test_anime
name=AniworldTest
data_dir=data
scheduler_enabled=False
logging_level=INFO
backup_enabled=False
Creates and returns a dictionary based on the given ``items``.
POST Request : url=http://127.0.0.1:8765/api/auth/setup
path_url=/api/auth/setup
headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '208', 'Content-Type': 'application/json'}
body=b'{"master_password": "TestPass123!", "anime_directory": "/tmp/aniworld_test_anime", "name": "AniworldTest", "data_dir": "data", "scheduler_enabled": "False", "logging_level": "INFO", "backup_enabled": "False"}'
POST Response : url=http://127.0.0.1:8765/api/auth/setup
status=400, reason=Bad Request
headers={'date': 'Fri, 26 Jun 2026 22:11:05 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
body={"detail":"Master password already configured"}
${resp} = <Response [400]>
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
45s
Pauses the test executed for the given time.
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
45s
Pauses the test executed for the given time.
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
${json} = {'detail': 'Master password already configured'}
${json}
${resp.text}
Convert String to JSON object
${detail} = ['Master password already configured']
${detail}
${json}
$.detail
Get Value From JSON using JSONPath
Setup failed with 400: ${detail}
Fails the test with the given message and optionally alters its tags.
${resp.status_code}
201
Fails if objects are unequal after converting them to integers.
Unexpected status ${resp.status_code} from /api/auth/setup
Fails the test with the given message and optionally alters its tags.
Configure the master password via the setup endpoint.
${payload} = {'password': 'TestPass123!'}
${payload}
password=${SETUP_PASSWORD}
Creates and returns a dictionary based on the given ``items``.
POST Request : url=http://127.0.0.1:8765/api/auth/login
path_url=/api/auth/login
headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '28', 'Content-Type': 'application/json'}
body=b'{"password": "TestPass123!"}'
POST Response : url=http://127.0.0.1:8765/api/auth/login
status=200, reason=OK
headers={'date': 'Fri, 26 Jun 2026 22:11:05 GMT', 'server': 'uvicorn', 'content-length': '232', 'content-type': 'application/json'}
body={"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI1OTgyNjUsImlhdCI6MTc4MjUxMTg2NX0.oQ307cnSsVWuTlBbwlWWrNTrbSD4kK2o9uqnC2s1KFY","token_type":"bearer","expires_at":"2026-06-27T22:11:05.521518Z"}
${resp} = <Response [200]>
${resp}
anon
/api/auth/login
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
6s
Pauses the test executed for the given time.
${resp}
anon
/api/auth/login
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
${json}
${resp.text}
Convert String to JSON object
${detail}
${json}
$.detail
Get Value From JSON using JSONPath
${detail_val}
${detail}[0]
Returns the given values which can then be assigned to a variables.
Login failed with ${resp.status_code}: ${detail_val}
Fails the test with the given message and optionally alters its tags.
${json} = {'access_token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI1OTgyNjUsImlhdCI6MTc4MjUxMTg2NX0.oQ307cnSsVWuTlBbwlWWrNTrbSD4kK2o9uqnC2s1KFY', 'token_type': 'bearer', 'expire...
${json}
${resp.text}
Convert String to JSON object
${token} = ['eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI1OTgyNjUsImlhdCI6MTc4MjUxMTg2NX0.oQ307cnSsVWuTlBbwlWWrNTrbSD4kK2o9uqnC2s1KFY']
${token}
${json}
$.access_token
Get Value From JSON using JSONPath
${token_str} = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI1OTgyNjUsImlhdCI6MTc4MjUxMTg2NX0.oQ307cnSsVWuTlBbwlWWrNTrbSD4kK2o9uqnC2s1KFY
${token_str}
${token}[0]
Returns the given values which can then be assigned to a variables.
${TOKEN} = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI1OTgyNjUsImlhdCI6MTc4MjUxMTg2NX0.oQ307cnSsVWuTlBbwlWWrNTrbSD4kK2o9uqnC2s1KFY
${TOKEN}
${token_str}
Makes a variable available everywhere within the scope of the current suite.
${token_str}
Log in with the master password and return the JWT access token.
Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI1OTgyNjUsImlhdCI6MTc4MjUxMTg2NX0.oQ307cnSsVWuTlBbwlWWrNTrbSD4kK2o9uqnC2s1KFY'}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
auth
${BASE_URL}
headers={'Authorization': 'Bearer ${TOKEN}'}
Create Session: create a HTTP session to a server
{"browser": "chromium", "headless": true, "chromiumSandbox": false, "devtools": false, "handleSIGHUP": true, "handleSIGINT": true, "handleSIGTERM": true, "slowMo": 0.0, "timeout": 30000.0, "tracesDir": "/home/lukas/Volume/repo/Aniworld/robot_output/browser/traces/temp/f808209d-8694-49b8-8298-841cb668b8c1"}
Starting Browser process /home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js using at 127.0.0.1:48397
Successfully created browser with options: {"browser":"chromium","headless":true,"chromiumSandbox":false,"devtools":false,"handleSIGHUP":true,"handleSIGINT":true,"handleSIGTERM":true,"slowMo":0,"timeout":30000,"tracesDir":"/home/lukas/Volume/repo/Aniworld/robot_output/browser/traces/temp/f808209d-8694-49b8-8298-841cb668b8c1"}
${BROWSER}
headless=${HEADLESS}
BrowserControl
Setter
Create a new playwright Browser with specified options.
{
"acceptDownloads": true,
"bypassCSP": false,
"forcedColors": "none",
"ignoreHTTPSErrors": false,
"javaScriptEnabled": true,
"offline": false,
"reducedMotion": "no-preference",
"serviceWorkers": "allow",
"viewport": {
"width": 1280,
"height": 720
}
}
Successfully created context.
{'acceptDownloads': True, 'bypassCSP': False, 'forcedColors': 'none', 'ignoreHTTPSErrors': False, 'javaScriptEnabled': True, 'offline': False, 'reducedMotion': 'no-preference', 'serviceWorkers': 'allow', 'viewport': {'width': 1280, 'height': 720}}
viewport={'width': 1280, 'height': 720}
BrowserControl
Setter
Create a new BrowserContext with specified options.
Initialize Browser library with the configured browser and headless mode.
Start Aniworld Server
AND
Create Anonymous Session
AND
Wait For Server
AND
Setup Master Password
AND
Login And Get Token
AND
Create Session
auth
${BASE_URL}
headers={'Authorization': 'Bearer ${TOKEN}'}
AND
Initialize Browser
Executes all the given keywords in a sequence.
Successfully initialized new page object and opened url: http://127.0.0.1:8765/login
${BASE_URL}${path}
BrowserControl
Setter
Open a new Page.
/login
Open a new page at the given path relative to BASE_URL.
Fills the text 'TestPass123!' in the given field.
id=password-input
${password}
PageContent
Setter
Clears and fills the given ``txt`` into the text field found by ``selector``.
Clicks the element 'id=login-submit-btn'.
id=login-submit-btn
PageContent
Setter
Simulates mouse click on the element found by ``selector``.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Fill the login form and submit it.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Open Browser To Page
/login
AND
Perform Login
AND
Wait For Elements State
id=search-input
visible
timeout=5s
Executes all the given keywords in a sequence.
Set viewport size to: {"width":375,"height":667}
375
667
BrowserControl
Setter
Sets current Pages viewport size to specified dimensions.
Resize the browser viewport to mobile dimensions.
Reloaded page with options: {"waitUntil": "load"}
BrowserControl
Setter
Reloads current active page.
Reload the current page.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Waited for Element with selector id=search-input at state visible
${selector}
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
id=search-input
Assert that the element matching the selector is visible.
Waited for Element with selector id=theme-toggle at state visible
${selector}
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
id=theme-toggle
Assert that the element matching the selector is visible.
Closed all browsers
ALL
BrowserControl
Setter
Closes the current browser.
Close all browser contexts and the browser itself.
Resize to mobile and verify layout adapts.
Successfully initialized new page object and opened url: http://127.0.0.1:8765/login
No browser and context was open. New browser and context was automatically opened when page is created.
${BASE_URL}${path}
BrowserControl
Setter
Open a new Page.
/login
Open a new page at the given path relative to BASE_URL.
Fills the text 'TestPass123!' in the given field.
id=password-input
${password}
PageContent
Setter
Clears and fills the given ``txt`` into the text field found by ``selector``.
Clicks the element 'id=login-submit-btn'.
id=login-submit-btn
PageContent
Setter
Simulates mouse click on the element found by ``selector``.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Fill the login form and submit it.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Open Browser To Page
/login
AND
Perform Login
AND
Wait For Elements State
id=search-input
visible
timeout=5s
Executes all the given keywords in a sequence.
Set viewport size to: {"width":375,"height":667}
375
667
BrowserControl
Setter
Sets current Pages viewport size to specified dimensions.
Resize the browser viewport to mobile dimensions.
Reloaded page with options: {"waitUntil": "load"}
BrowserControl
Setter
Reloads current active page.
Reload the current page.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Waited for Element with selector id=theme-toggle at state visible
${selector}
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
id=theme-toggle
Assert that the element matching the selector is visible.
Closed all browsers
ALL
BrowserControl
Setter
Closes the current browser.
Close all browser contexts and the browser itself.
Verify compact header on mobile.
Successfully initialized new page object and opened url: http://127.0.0.1:8765/login
No browser and context was open. New browser and context was automatically opened when page is created.
${BASE_URL}${path}
BrowserControl
Setter
Open a new Page.
/login
Open a new page at the given path relative to BASE_URL.
Fills the text 'TestPass123!' in the given field.
id=password-input
${password}
PageContent
Setter
Clears and fills the given ``txt`` into the text field found by ``selector``.
Clicks the element 'id=login-submit-btn'.
id=login-submit-btn
PageContent
Setter
Simulates mouse click on the element found by ``selector``.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Fill the login form and submit it.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Open Browser To Page
/login
AND
Perform Login
AND
Wait For Elements State
id=search-input
visible
timeout=5s
Executes all the given keywords in a sequence.
Set viewport size to: {"width":768,"height":1024}
768
1024
BrowserControl
Setter
Sets current Pages viewport size to specified dimensions.
Resize the browser viewport to tablet dimensions.
Reloaded page with options: {"waitUntil": "load"}
BrowserControl
Setter
Reloads current active page.
Reload the current page.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Waited for Element with selector id=search-input at state visible
${selector}
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
id=search-input
Assert that the element matching the selector is visible.
Waited for Element with selector id=rescan-btn at state visible
${selector}
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
id=rescan-btn
Assert that the element matching the selector is visible.
Closed all browsers
ALL
BrowserControl
Setter
Closes the current browser.
Close all browser contexts and the browser itself.
Resize to tablet and verify layout adapts.
Successfully initialized new page object and opened url: http://127.0.0.1:8765/login
No browser and context was open. New browser and context was automatically opened when page is created.
${BASE_URL}${path}
BrowserControl
Setter
Open a new Page.
/login
Open a new page at the given path relative to BASE_URL.
Fills the text 'TestPass123!' in the given field.
id=password-input
${password}
PageContent
Setter
Clears and fills the given ``txt`` into the text field found by ``selector``.
Clicks the element 'id=login-submit-btn'.
id=login-submit-btn
PageContent
Setter
Simulates mouse click on the element found by ``selector``.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Fill the login form and submit it.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Open Browser To Page
/login
AND
Perform Login
AND
Wait For Elements State
id=search-input
visible
timeout=5s
Executes all the given keywords in a sequence.
Set viewport size to: {"width":375,"height":667}
375
667
BrowserControl
Setter
Sets current Pages viewport size to specified dimensions.
Resize the browser viewport to mobile dimensions.
Reloaded page with options: {"waitUntil": "load"}
BrowserControl
Setter
Reloads current active page.
Reload the current page.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Clicks the element 'id=theme-toggle'.
id=theme-toggle
PageContent
Setter
Simulates mouse click on the element found by ``selector``.
Attribute is: 'dark'
${theme} = dark
${theme}
html
data-theme
Assertion
Getter
PageContent
Returns the HTML ``attribute`` of the element found by ``selector``.
${theme}
${theme} = dark
${theme}
Return the current theme attribute from the HTML element.
${theme}
dark
Fails if objects are unequal after converting them to strings.
Clicks the element 'id=theme-toggle'.
id=theme-toggle
PageContent
Setter
Simulates mouse click on the element found by ``selector``.
Attribute is: 'light'
${theme} = light
${theme}
html
data-theme
Assertion
Getter
PageContent
Returns the HTML ``attribute`` of the element found by ``selector``.
${theme}
${theme} = light
${theme}
Return the current theme attribute from the HTML element.
${theme}
light
Fails if objects are unequal after converting them to strings.
Closed all browsers
ALL
BrowserControl
Setter
Closes the current browser.
Close all browser contexts and the browser itself.
Verify buttons remain clickable on touch-sized viewport.
Successfully initialized new page object and opened url: http://127.0.0.1:8765/login
No browser and context was open. New browser and context was automatically opened when page is created.
${BASE_URL}${path}
BrowserControl
Setter
Open a new Page.
/login
Open a new page at the given path relative to BASE_URL.
Fills the text 'TestPass123!' in the given field.
id=password-input
${password}
PageContent
Setter
Clears and fills the given ``txt`` into the text field found by ``selector``.
Clicks the element 'id=login-submit-btn'.
id=login-submit-btn
PageContent
Setter
Simulates mouse click on the element found by ``selector``.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Fill the login form and submit it.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Open Browser To Page
/login
AND
Perform Login
AND
Wait For Elements State
id=search-input
visible
timeout=5s
Executes all the given keywords in a sequence.
Set viewport size to: {"width":1280,"height":720}
1280
720
BrowserControl
Setter
Sets current Pages viewport size to specified dimensions.
Resize the browser viewport to desktop dimensions.
Reloaded page with options: {"waitUntil": "load"}
BrowserControl
Setter
Reloads current active page.
Reload the current page.
Waited for Element with selector id=search-input at state visible
id=search-input
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
Waited for Element with selector id=search-input at state visible
${selector}
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
id=search-input
Assert that the element matching the selector is visible.
Waited for Element with selector id=rescan-btn at state visible
${selector}
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
id=rescan-btn
Assert that the element matching the selector is visible.
Waited for Element with selector id=config-btn at state visible
${selector}
visible
timeout=5s
PageContent
Wait
Waits for the element found by ``selector`` to satisfy state option.
id=config-btn
Assert that the element matching the selector is visible.
Closed all browsers
ALL
BrowserControl
Setter
Closes the current browser.
Close all browser contexts and the browser itself.
Resize back to desktop and verify normal layout.
Responsive design UI tests for Aniworld.
Covers mobile and tablet viewport layouts and touch interactions.
All Tests
Responsive