diff --git a/Docs/tasks.md b/Docs/tasks.md
index ed795c4..656e374 100644
--- a/Docs/tasks.md
+++ b/Docs/tasks.md
@@ -1,19 +1,3 @@
-## Task 1: API Config - Update Config
-
-**Suite:** `Robot.Api.Config`
-**Test:** `Update Config`
-**Result:** FAIL
-**Error:** `Url: http://127.0.0.1:8765/api/config Expected status: 422 != 200`
-
-**Instructions:**
-- Investigate the `PUT /api/config` endpoint in the FastAPI application.
-- The test sends a valid config update but receives HTTP 422 (Unprocessable Entity) instead of 200.
-- Check the Pydantic model used for config updates — a field may be missing, have the wrong type, or have an unexpected validator.
-- Compare the test payload in `tests/robot/api/config.robot` with the request model in the backend.
-- Fix either the API endpoint validation or the test payload so the update succeeds.
-
----
-
## Task 2: API Download - Remove Item From Queue
**Suite:** `Robot.Api.Download`
@@ -421,5 +405,4 @@
**Instructions:**
- Same root cause as Task 22: the setup form is not visible.
- Fix the suite setup so the app is in an unconfigured state before each setup flow test.
-- Ensure `#setup-form` is rendered when navigating to the setup page.
-
+- Ensure `#setup-form` is rendered when navigating to the setup page.
\ No newline at end of file
diff --git a/robot_output/log.html b/robot_output/log.html
index 90e0e43..f0746be 100644
--- a/robot_output/log.html
+++ b/robot_output/log.html
@@ -2073,31 +2073,31 @@ storage = function () {
window.output = {};
diff --git a/robot_output/output.xml b/robot_output/output.xml
index 788c196..eca039c 100644
--- a/robot_output/output.xml
+++ b/robot_output/output.xml
@@ -1,22 +1,23 @@
-
+
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -26,34 +27,160 @@
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=201, reason=Created
- headers={'date': 'Sat, 27 Jun 2026 11:55:21 GMT', 'server': 'uvicorn', 'content-length': '51', 'content-type': 'application/json'}
- body={"status":"ok","redirect":"/loading?phase=initial"}
-
-${resp} = <Response [201]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -62,18 +189,18 @@
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}
@@ -82,11 +209,11 @@
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+
-
+
-
+
@@ -94,284 +221,55 @@
${json}
${resp.text}
Convert String to JSON object
-
+
${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.
-
+
-
+
-
+
-Argument types are:
-<class 'int'>
-<class 'str'>
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:21 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-
-${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': 'Sat, 27 Jun 2026 11:55:21 GMT', 'server': 'uvicorn', 'content-length': '232', 'content-type': 'application/json'}
- body={"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs","token_type":"bearer","expires_at":"2026-06-28T11:55:22.863211Z"}
-
-${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.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'token_type': 'bearer', 'expire...
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${token} = ['eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs']
-${token}
-${json}
-$.access_token
-Get Value From JSON using JSONPath
-
-
-
-${token_str} = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs
-${token_str}
-${token}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${TOKEN} = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs
-${TOKEN}
-${token_str}
-Makes a variable available everywhere within the scope of the current suite.
-
-
-
-${token_str}
-
-
-${token} = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs
-${token}
-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.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${TOKEN}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -379,161 +277,60 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-
-GET Request : url=http://127.0.0.1:8765/api/config
- path_url=/api/config
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}
- body=None
-
-GET Response : url=http://127.0.0.1:8765/api/config
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:21 GMT', 'server': 'uvicorn', 'content-length': '829', 'content-type': 'application/json'}
- body={"name":"AniworldTest","data_dir":"data","scheduler":{"enabled":false,"interval_minutes":60,"schedule_time":"03:00","schedule_days":["mon","tue","wed","thu","fri","sat","sun"],"auto_download_after_rescan":false,"nfo_scan_after_rescan":true,"image_scan_after_rescan":true,"auto_download":null},"logging":{"level":"INFO","file":null,"max_bytes":null,"backup_count":3},"backup":{"enabled":false,"path":"data/backups","keep_days":30},"nfo":{"tmdb_api_key":null,"auto_create":true,"update_on_scan":true,"download_poster":true,"download_logo":true,"download_fanart":true,"image_size":"original"},"scan_key_overrides":{},"other":{"loading_complete":true,"master_password_hash":"$pbkdf2-sha256$29000$dm6NcU5JaU2p1dqbM2aMMQ$U4sJCHcdZe6kEYxBSqIoQ46pgtjyCt8N1flCTGj06tY","loading_started":true,"anime_directory":"/tmp/aniworld_test_anime"}}
-
-${resp} = <Response [200]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-/api/config
-Perform an authenticated GET request and return the response.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-200
-Assert that the response status code matches the expected value.
-
-
-
-
-${json} = {'name': 'AniworldTest', 'data_dir': 'data', 'scheduler': {'enabled': False, 'interval_minutes': 60, 'schedule_time': '03:00', 'schedule_days': ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'], 'auto...
-${json}
-${response.text}
-Convert String to JSON object
-
-
-
-
-
-${json}
-${key}
-Fails if ``key`` is not found from ``dictionary``.
-
-
-name
-
-
-
-
-${json}
-${key}
-Fails if ``key`` is not found from ``dictionary``.
-
-
-data_dir
-
-
-
-
-${json}
-${key}
-Fails if ``key`` is not found from ``dictionary``.
-
-
-scheduler
-
-
-
-
-${json}
-${key}
-Fails if ``key`` is not found from ``dictionary``.
-
-
-logging
-
-
-
-
-${json}
-${key}
-Fails if ``key`` is not found from ``dictionary``.
-
-
-backup
-
-
-
-
-${json}
-${key}
-Fails if ``key`` is not found from ``dictionary``.
-
-
-nfo
-
-
-${key}
-@{keys}
-
-
-${resp}
-name
-data_dir
-scheduler
-logging
-backup
-nfo
-Assert that the JSON response contains all the specified top-level keys.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
-Starting Browser process /home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js using at 127.0.0.1:50011
+Starting Browser process /home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js using at 127.0.0.1:36123
+Waiting for Playwright server at 127.0.0.1:36123 to start...
+<_InactiveRpcError of RPC that terminated with:
+ status = StatusCode.UNAVAILABLE
+ details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:36123: Failed to connect to remote host: Connection refused"
+ debug_error_string = "UNAVAILABLE:failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:36123: Failed to connect to remote host: Connection refused"
+>
+Waiting for Playwright server at 127.0.0.1:36123 to start...
+<_InactiveRpcError of RPC that terminated with:
+ status = StatusCode.UNAVAILABLE
+ details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:36123: Failed to connect to remote host: Connection refused"
+ debug_error_string = "UNAVAILABLE:failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:36123: Failed to connect to remote host: Connection refused"
+>
+Waiting for Playwright server at 127.0.0.1:36123 to start...
+<_InactiveRpcError of RPC that terminated with:
+ status = StatusCode.UNAVAILABLE
+ details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:36123: Failed to connect to remote host: Connection refused"
+ debug_error_string = "UNAVAILABLE:failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:36123: Failed to connect to remote host: Connection refused"
+>
+Waiting for Playwright server at 127.0.0.1:36123 to start...
+<_InactiveRpcError of RPC that terminated with:
+ status = StatusCode.UNAVAILABLE
+ details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:36123: Failed to connect to remote host: Connection refused"
+ debug_error_string = "UNAVAILABLE:failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:36123: Failed to connect to remote host: Connection refused"
+>
+Waiting for Playwright server at 127.0.0.1:36123 to start...
Retrieve the current configuration and verify its structure.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -543,34 +340,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -579,18 +502,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -599,46 +522,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -646,137 +567,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -784,156 +590,34 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-${payload} = {'name': 'UpdatedAniworld', 'data_dir': 'data', 'scheduler': "{'enabled': False, 'schedule_time': '04:00', 'schedule_days': ['mon', 'tue']}", 'logging': "{'level': 'DEBUG', 'file': 'logs/test.log', 'm...
-${payload}
-name=UpdatedAniworld
-data_dir=data
-scheduler={'enabled': False, 'schedule_time': '04:00', 'schedule_days': ['mon', 'tue']}
-logging={'level': 'DEBUG', 'file': 'logs/test.log', 'max_bytes': 1048576, 'backup_count': 5}
-backup={'enabled': False}
-nfo={'tmdb_api_key': '', 'auto_create': False, 'download_poster': False, 'download_logo': False, 'download_fanart': False}
-other={'anime_directory': '/tmp/aniworld_test_anime'}
-Creates and returns a dictionary based on the given ``items``.
-
-
-
-
-
-PUT Request : url=http://127.0.0.1:8765/api/config
- path_url=/api/config
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '461', 'Content-Type': 'application/json'}
- body=b'{"name": "UpdatedAniworld", "data_dir": "data", "scheduler": "{\'enabled\': False, \'schedule_time\': \'04:00\', \'schedule_days\': [\'mon\', \'tue\']}", "logging": "{\'level\': \'DEBUG\', \'file\': \'logs/test.log\', \'max_bytes\': 1048576, \'backup_count\': 5}", "backup": "{\'enabled\': False}", "nfo": "{\'tmdb_api_key\': \'\', \'auto_create\': False, \'download_poster\': False, \'download_logo\': False, \'download_fanart\': False}", "other": "{\'anime_directory\': \'/tmp/aniworld_test_anime\'}"}'
-
-PUT Response : url=http://127.0.0.1:8765/api/config
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '820', 'content-type': 'application/json'}
- body={"name":"UpdatedAniworld","data_dir":"data","scheduler":{"enabled":false,"interval_minutes":60,"schedule_time":"04:00","schedule_days":["mon","tue"],"auto_download_after_rescan":false,"nfo_scan_after_rescan":true,"image_scan_after_rescan":true,"auto_download":null},"logging":{"level":"DEBUG","file":"logs/test.log","max_bytes":1048576,"backup_count":5},"backup":{"enabled":false,"path":"data/backups","keep_days":30},"nfo":{"tmdb_api_key":"","auto_create":false,"update_on_scan":false,"download_poster":false,"download_logo":false,"download_fanart":false,"image_size":"original"},"scan_key_overrides":{},"other":{"loading_complete":true,"master_password_hash":"$pbkdf2-sha256$29000$dm6NcU5JaU2p1dqbM2aMMQ$U4sJCHcdZe6kEYxBSqIoQ46pgtjyCt8N1flCTGj06tY","loading_started":true,"anime_directory":"/tmp/aniworld_test_anime"}}
-
-${resp} = <Response [200]>
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a PUT request on a previously created HTTP Session.
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-/api/config
-${payload}
-Perform an authenticated PUT request with JSON payload.
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-${payload}
-PUT /api/config with the given payload.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-200
-Assert that the response status code matches the expected value.
-
-
-
-
-
-GET Request : url=http://127.0.0.1:8765/api/config
- path_url=/api/config
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}
- body=None
-
-GET Response : url=http://127.0.0.1:8765/api/config
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '820', 'content-type': 'application/json'}
- body={"name":"UpdatedAniworld","data_dir":"data","scheduler":{"enabled":false,"interval_minutes":60,"schedule_time":"04:00","schedule_days":["mon","tue"],"auto_download_after_rescan":false,"nfo_scan_after_rescan":true,"image_scan_after_rescan":true,"auto_download":null},"logging":{"level":"DEBUG","file":"logs/test.log","max_bytes":1048576,"backup_count":5},"backup":{"enabled":false,"path":"data/backups","keep_days":30},"nfo":{"tmdb_api_key":"","auto_create":false,"update_on_scan":false,"download_poster":false,"download_logo":false,"download_fanart":false,"image_size":"original"},"scan_key_overrides":{},"other":{"loading_complete":true,"master_password_hash":"$pbkdf2-sha256$29000$dm6NcU5JaU2p1dqbM2aMMQ$U4sJCHcdZe6kEYxBSqIoQ46pgtjyCt8N1flCTGj06tY","loading_started":true,"anime_directory":"/tmp/aniworld_test_anime"}}
-
-${resp} = <Response [200]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-/api/config
-Perform an authenticated GET request and return the response.
-
-
-
-${json} = {'name': 'UpdatedAniworld', 'data_dir': 'data', 'scheduler': {'enabled': False, 'interval_minutes': 60, 'schedule_time': '04:00', 'schedule_days': ['mon', 'tue'], 'auto_download_after_rescan': False, ...
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${json}
-
-
-${config} = {'name': 'UpdatedAniworld', 'data_dir': 'data', 'scheduler': {'enabled': False, 'interval_minutes': 60, 'schedule_time': '04:00', 'schedule_days': ['mon', 'tue'], 'auto_download_after_rescan': False, ...
-${config}
-GET /api/config and return the parsed JSON.
-
-
-
-${config}[name]
-UpdatedAniworld
-Fails if objects are unequal after converting them to strings.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
Update configuration fields and verify they are persisted.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -943,34 +627,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -979,18 +789,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -999,46 +809,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -1046,137 +854,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -1184,173 +877,34 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-${schedule_days} = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
-${schedule_days}
-mon
-tue
-wed
-thu
-fri
-sat
-sun
-Returns a list containing given items.
-
-
-
-${payload} = {'name': 'Aniworld', 'data_dir': 'data', 'scheduler': {'enabled': True, 'schedule_time': '03:00', 'schedule_days': ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']}, 'logging': {'level': 'INFO', 'bac...
-${payload}
-json.loads('''{"name": "Aniworld", "data_dir": "data", "scheduler": {"enabled": true, "schedule_time": "03:00", "schedule_days": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]}, "logging": {"level": "INFO", "backup_count": 3}, "backup": {"enabled": false}, "nfo": {"tmdb_api_key": "", "auto_create": true, "download_poster": true, "download_logo": true, "download_fanart": true}, "other": {}}''')
-modules=json
-Evaluates the given expression in Python and returns the result.
-
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/validate
- path_url=/api/config/validate
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '381', 'Content-Type': 'application/json'}
- body=b'{"name": "Aniworld", "data_dir": "data", "scheduler": {"enabled": true, "schedule_time": "03:00", "schedule_days": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]}, "logging": {"level": "INFO", "backup_count": 3}, "backup": {"enabled": false}, "nfo": {"tmdb_api_key": "", "auto_create": true, "download_poster": true, "download_logo": true, "download_fanart": true}, "other": {}}'
-
-POST Response : url=http://127.0.0.1:8765/api/config/validate
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '26', 'content-type': 'application/json'}
- body={"valid":true,"errors":[]}
-
-${resp} = <Response [200]>
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-/api/config/validate
-${payload}
-${expected_status}
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-${payload}
-200
-POST /api/config/validate with the given payload.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-200
-Assert that the response status code matches the expected value.
-
-
-
-
-${json} = {'valid': True, 'errors': []}
-${json}
-${response.text}
-Convert String to JSON object
-
-
-
-${values} = [True]
-${values}
-${json}
-${json_path}
-Get Value From JSON using JSONPath
-
-
-
-${value} = True
-${value}
-${values}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${value}
-
-
-${valid} = True
-${valid}
-${resp}
-$.valid
-Extract a value from a JSON response using JSONPath.
-
-
-
-Argument types are:
-<class 'bool'>
-<class 'str'>
-${valid}
-True
-Fails if objects are unequal after converting them to strings.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
Validate a well-formed configuration.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -1360,34 +914,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -1396,18 +1076,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -1416,46 +1096,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -1463,137 +1141,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -1601,121 +1164,34 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-${payload} = {'data_dir': 'data', 'scheduler': "{'enabled': True, 'schedule_time': '03:00', 'schedule_days': ['mon']}", 'logging': "{'level': 'INFO'}", 'backup': "{'enabled': False}", 'nfo': "{'auto_create': False...
-${payload}
-data_dir=data
-scheduler={'enabled': True, 'schedule_time': '03:00', 'schedule_days': ['mon']}
-logging={'level': 'INFO'}
-backup={'enabled': False}
-nfo={'auto_create': False}
-other={}
-Creates and returns a dictionary based on the given ``items``.
-
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/validate
- path_url=/api/config/validate
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '218', 'Content-Type': 'application/json'}
- body=b'{"data_dir": "data", "scheduler": "{\'enabled\': True, \'schedule_time\': \'03:00\', \'schedule_days\': [\'mon\']}", "logging": "{\'level\': \'INFO\'}", "backup": "{\'enabled\': False}", "nfo": "{\'auto_create\': False}", "other": "{}"}'
-
-POST Response : url=http://127.0.0.1:8765/api/config/validate
- status=422, reason=Unprocessable Content
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '1128', 'content-type': 'application/json'}
- body={"detail":[{"type":"model_attributes_type","loc":["body","scheduler"],"msg":"Input should be a valid dictionary or object to extract fields from","input":"{'enabled': True, 'schedule_time': '03:00', 'schedule_days': ['mon']}","url":"https://errors.pydantic.dev/2.12/v/model_attributes_type"},{"type":"model_attributes_type","loc":["body","logging"],"msg":"Input should be a valid dictionary or object to extract fields from","input":"{'level': 'INFO'}","url":"https://errors.pydantic.dev/2.12/v/model_attributes_type"},{"type":"model_attributes_type","loc":["body","backup"],"msg":"Input should be a valid dictionary or object to extract fields from","input":"{'enabled': False}","url":"https://errors.pydantic.dev/2.12/v/model_attributes_type"},{"type":"model_attributes_type","loc":["body","nfo"],"msg":"Input should be a valid dictionary or object to extract fields from","input":"{'auto_create': False}","url":"https://errors.pydantic.dev/2.12/v/model_attributes_type"},{"type":"dict_type","loc":["body","other"],"msg":"Input should be a valid dictionary","input":"{}","url":"https://errors.pydantic.dev/2.12/v/dict_type"}]}
-
-${resp} = <Response [422]>
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-${resp} = <Response [422]>
-${resp}
-/api/config/validate
-${payload}
-${expected_status}
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-${resp}
-
-
-${resp} = <Response [422]>
-${resp}
-${payload}
-422
-POST /api/config/validate with the given payload.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-422
-Assert that the response status code matches the expected value.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
Validate a config missing the required 'name' field.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -1725,34 +1201,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -1761,18 +1363,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -1781,46 +1383,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -1828,137 +1428,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -1966,122 +1451,34 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-${payload} = {'name': 'Aniworld', 'data_dir': 'data', 'scheduler': "{'enabled': True, 'schedule_time': '25:00', 'schedule_days': ['mon']}", 'logging': "{'level': 'INFO'}", 'backup': "{'enabled': False}", 'nfo': "{...
-${payload}
-name=Aniworld
-data_dir=data
-scheduler={'enabled': True, 'schedule_time': '25:00', 'schedule_days': ['mon']}
-logging={'level': 'INFO'}
-backup={'enabled': False}
-nfo={'auto_create': False}
-other={}
-Creates and returns a dictionary based on the given ``items``.
-
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/validate
- path_url=/api/config/validate
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '238', 'Content-Type': 'application/json'}
- body=b'{"name": "Aniworld", "data_dir": "data", "scheduler": "{\'enabled\': True, \'schedule_time\': \'25:00\', \'schedule_days\': [\'mon\']}", "logging": "{\'level\': \'INFO\'}", "backup": "{\'enabled\': False}", "nfo": "{\'auto_create\': False}", "other": "{}"}'
-
-POST Response : url=http://127.0.0.1:8765/api/config/validate
- status=422, reason=Unprocessable Content
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '1128', 'content-type': 'application/json'}
- body={"detail":[{"type":"model_attributes_type","loc":["body","scheduler"],"msg":"Input should be a valid dictionary or object to extract fields from","input":"{'enabled': True, 'schedule_time': '25:00', 'schedule_days': ['mon']}","url":"https://errors.pydantic.dev/2.12/v/model_attributes_type"},{"type":"model_attributes_type","loc":["body","logging"],"msg":"Input should be a valid dictionary or object to extract fields from","input":"{'level': 'INFO'}","url":"https://errors.pydantic.dev/2.12/v/model_attributes_type"},{"type":"model_attributes_type","loc":["body","backup"],"msg":"Input should be a valid dictionary or object to extract fields from","input":"{'enabled': False}","url":"https://errors.pydantic.dev/2.12/v/model_attributes_type"},{"type":"model_attributes_type","loc":["body","nfo"],"msg":"Input should be a valid dictionary or object to extract fields from","input":"{'auto_create': False}","url":"https://errors.pydantic.dev/2.12/v/model_attributes_type"},{"type":"dict_type","loc":["body","other"],"msg":"Input should be a valid dictionary","input":"{}","url":"https://errors.pydantic.dev/2.12/v/dict_type"}]}
-
-${resp} = <Response [422]>
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-${resp} = <Response [422]>
-${resp}
-/api/config/validate
-${payload}
-${expected_status}
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-${resp}
-
-
-${resp} = <Response [422]>
-${resp}
-${payload}
-422
-POST /api/config/validate with the given payload.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-422
-Assert that the response status code matches the expected value.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
Validate a config with malformed schedule_time.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -2091,34 +1488,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -2127,18 +1650,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -2147,46 +1670,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -2194,137 +1715,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -2332,117 +1738,34 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-${payload} = {'name': 'Aniworld', 'data_dir': 'data', 'scheduler': {'enabled': True, 'schedule_time': '03:00', 'schedule_days': ['mon']}, 'logging': {'level': 'INVALID', 'backup_count': 3}, 'backup': {'enabled': F...
-${payload}
-json.loads('''{"name": "Aniworld", "data_dir": "data", "scheduler": {"enabled": true, "schedule_time": "03:00", "schedule_days": ["mon"]}, "logging": {"level": "INVALID", "backup_count": 3}, "backup": {"enabled": false}, "nfo": {"auto_create": false}, "other": {}}''')
-modules=json
-Evaluates the given expression in Python and returns the result.
-
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/validate
- path_url=/api/config/validate
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '250', 'Content-Type': 'application/json'}
- body=b'{"name": "Aniworld", "data_dir": "data", "scheduler": {"enabled": true, "schedule_time": "03:00", "schedule_days": ["mon"]}, "logging": {"level": "INVALID", "backup_count": 3}, "backup": {"enabled": false}, "nfo": {"auto_create": false}, "other": {}}'
-
-POST Response : url=http://127.0.0.1:8765/api/config/validate
- status=422, reason=Unprocessable Content
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '212', 'content-type': 'application/json'}
- body={"detail":[{"type":"value_error","loc":["body","logging","level"],"msg":"Value error, invalid logging level: INVALID","input":"INVALID","ctx":{"error":{}},"url":"https://errors.pydantic.dev/2.12/v/value_error"}]}
-
-${resp} = <Response [422]>
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-${resp} = <Response [422]>
-${resp}
-/api/config/validate
-${payload}
-${expected_status}
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-${resp}
-
-
-${resp} = <Response [422]>
-${resp}
-${payload}
-422
-POST /api/config/validate with the given payload.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-422
-Assert that the response status code matches the expected value.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
Validate a config with an invalid logging level.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -2452,34 +1775,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -2488,18 +1937,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -2508,46 +1957,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -2555,137 +2002,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -2693,96 +2025,34 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/backups
- path_url=/api/config/backups
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '0'}
- body=None
-
-POST Response : url=http://127.0.0.1:8765/api/config/backups
- status=201, reason=Created
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '85', 'content-type': 'application/json'}
- body={"name":"config_backup_20260627_135523.json","message":"Backup created successfully"}
-
-${resp} = <Response [201]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-${resp} = <Response [201]>
-${resp}
-/api/config/backups
-expected_status=201
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-201
-Assert that the response status code matches the expected value.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
Create a configuration backup and verify it exists.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -2792,34 +2062,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -2828,18 +2224,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -2848,46 +2244,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -2895,137 +2289,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -3033,152 +2312,34 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/backups
- path_url=/api/config/backups
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '0'}
- body=None
-
-POST Response : url=http://127.0.0.1:8765/api/config/backups
- status=201, reason=Created
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '85', 'content-type': 'application/json'}
- body={"name":"config_backup_20260627_135523.json","message":"Backup created successfully"}
-
-${resp} = <Response [201]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-/api/config/backups
-expected_status=201
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-
-GET Request : url=http://127.0.0.1:8765/api/config/backups
- path_url=/api/config/backups
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}
- body=None
-
-GET Response : url=http://127.0.0.1:8765/api/config/backups
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '1054', 'content-type': 'application/json'}
- body={"backups":[{"name":"config_backup_20260627_135523.json","size_bytes":1038,"created_at":"2026-06-27T13:55:23.370415"},{"name":"pre_restore.json","size_bytes":1006,"created_at":"2026-06-27T13:54:18.929110"},{"name":"config_backup_20260627_135413.json","size_bytes":1082,"created_at":"2026-06-27T13:54:13.524603"},{"name":"config_backup_20260627_135334.json","size_bytes":1082,"created_at":"2026-06-27T13:53:33.987485"},{"name":"config_backup_20260627_135300.json","size_bytes":1005,"created_at":"2026-06-27T13:52:52.824097"},{"name":"config_backup_20260627_135224.json","size_bytes":1005,"created_at":"2026-06-27T13:52:24.663837"},{"name":"config_backup_20260627_135252.json","size_bytes":1005,"created_at":"2026-06-27T13:52:24.663837"},{"name":"config_backup_20260627_135150.json","size_bytes":1005,"created_at":"2026-06-27T13:51:50.613557"},{"name":"config_backup_20260627_135110.json","size_bytes":848,"created_at":"2026-06-27T13:50:57.578964"},{"name":"config_backup_20260627_134732.json","size_bytes":1082,"created_at":"2026-06-27T13:37:13.232168"}]}
-
-${resp} = <Response [200]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-/api/config/backups
-Perform an authenticated GET request and return the response.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-200
-Assert that the response status code matches the expected value.
-
-
-
-
-${json} = {'backups': [{'name': 'config_backup_20260627_135523.json', 'size_bytes': 1038, 'created_at': '2026-06-27T13:55:23.370415'}, {'name': 'pre_restore.json', 'size_bytes': 1006, 'created_at': '2026-06-27T...
-${json}
-${response.text}
-Convert String to JSON object
-
-
-
-${values} = [[{'name': 'config_backup_20260627_135523.json', 'size_bytes': 1038, 'created_at': '2026-06-27T13:55:23.370415'}, {'name': 'pre_restore.json', 'size_bytes': 1006, 'created_at': '2026-06-27T13:54:18.92...
-${values}
-${json}
-${json_path}
-Get Value From JSON using JSONPath
-
-
-
-Length is 1.
-${values}
-Expected JSON path '${json_path}' not found in response
-Verifies that the given item is not empty.
-
-
-${resp}
-$.backups
-Assert that the JSON response contains the given JSONPath key.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
List configuration backups and verify the response structure.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -3188,34 +2349,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -3224,18 +2511,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -3244,46 +2531,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -3291,137 +2576,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -3429,255 +2599,34 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/backups
- path_url=/api/config/backups
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '0'}
- body=None
-
-POST Response : url=http://127.0.0.1:8765/api/config/backups
- status=201, reason=Created
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '85', 'content-type': 'application/json'}
- body={"name":"config_backup_20260627_135523.json","message":"Backup created successfully"}
-
-${resp} = <Response [201]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-${resp} = <Response [201]>
-${resp}
-/api/config/backups
-expected_status=201
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-${json} = {'name': 'config_backup_20260627_135523.json', 'message': 'Backup created successfully'}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${backup_name} = ['config_backup_20260627_135523.json']
-${backup_name}
-${json}
-$.name
-Get Value From JSON using JSONPath
-
-
-
-${name_before} = config_backup_20260627_135523.json
-${name_before}
-${backup_name}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${scheduler} = {'enabled': False, 'schedule_time': '03:00', 'schedule_days': ['mon']}
-${scheduler}
-{'enabled': False, 'schedule_time': '03:00', 'schedule_days': ['mon']}
-Evaluates the given expression in Python and returns the result.
-
-
-
-${logging} = {'level': 'INFO', 'file': None, 'max_bytes': None, 'backup_count': 3}
-${logging}
-{'level': 'INFO', 'file': None, 'max_bytes': None, 'backup_count': 3}
-Evaluates the given expression in Python and returns the result.
-
-
-
-${backup} = {'enabled': False}
-${backup}
-{'enabled': False}
-Evaluates the given expression in Python and returns the result.
-
-
-
-${nfo} = {'auto_create': False}
-${nfo}
-{'auto_create': False}
-Evaluates the given expression in Python and returns the result.
-
-
-
-${other} = {}
-${other}
-{}
-Evaluates the given expression in Python and returns the result.
-
-
-
-${payload} = {'name': 'BeforeRestore', 'data_dir': 'data', 'scheduler': {'enabled': False, 'schedule_time': '03:00', 'schedule_days': ['mon']}, 'logging': {'level': 'INFO', 'file': None, 'max_bytes': None, 'backup...
-${payload}
-name=BeforeRestore
-data_dir=data
-scheduler=${scheduler}
-logging=${logging}
-backup=${backup}
-nfo=${nfo}
-other=${other}
-Creates and returns a dictionary based on the given ``items``.
-
-
-
-
-
-PUT Request : url=http://127.0.0.1:8765/api/config
- path_url=/api/config
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '286', 'Content-Type': 'application/json'}
- body=b'{"name": "BeforeRestore", "data_dir": "data", "scheduler": {"enabled": false, "schedule_time": "03:00", "schedule_days": ["mon"]}, "logging": {"level": "INFO", "file": null, "max_bytes": null, "backup_count": 3}, "backup": {"enabled": false}, "nfo": {"auto_create": false}, "other": {}}'
-
-PUT Response : url=http://127.0.0.1:8765/api/config
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '796', 'content-type': 'application/json'}
- body={"name":"BeforeRestore","data_dir":"data","scheduler":{"enabled":false,"interval_minutes":60,"schedule_time":"03:00","schedule_days":["mon"],"auto_download_after_rescan":false,"nfo_scan_after_rescan":true,"image_scan_after_rescan":true,"auto_download":null},"logging":{"level":"INFO","file":null,"max_bytes":null,"backup_count":3},"backup":{"enabled":false,"path":"data/backups","keep_days":30},"nfo":{"tmdb_api_key":null,"auto_create":false,"update_on_scan":false,"download_poster":true,"download_logo":true,"download_fanart":true,"image_size":"original"},"scan_key_overrides":{},"other":{"loading_complete":true,"master_password_hash":"$pbkdf2-sha256$29000$dm6NcU5JaU2p1dqbM2aMMQ$U4sJCHcdZe6kEYxBSqIoQ46pgtjyCt8N1flCTGj06tY","loading_started":true,"anime_directory":"/tmp/aniworld_test_anime"}}
-
-${resp} = <Response [200]>
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a PUT request on a previously created HTTP Session.
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-/api/config
-${payload}
-Perform an authenticated PUT request with JSON payload.
-
-
-
-${resp}
-
-
-${payload}
-PUT /api/config with the given payload.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/backups/config_backup_20260627_135523.json/restore
- path_url=/api/config/backups/config_backup_20260627_135523.json/restore
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '0'}
- body=None
-
-POST Response : url=http://127.0.0.1:8765/api/config/backups/config_backup_20260627_135523.json/restore
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '820', 'content-type': 'application/json'}
- body={"name":"UpdatedAniworld","data_dir":"data","scheduler":{"enabled":false,"interval_minutes":60,"schedule_time":"04:00","schedule_days":["mon","tue"],"auto_download_after_rescan":false,"nfo_scan_after_rescan":true,"image_scan_after_rescan":true,"auto_download":null},"logging":{"level":"DEBUG","file":"logs/test.log","max_bytes":1048576,"backup_count":5},"backup":{"enabled":false,"path":"data/backups","keep_days":30},"nfo":{"tmdb_api_key":"","auto_create":false,"update_on_scan":false,"download_poster":false,"download_logo":false,"download_fanart":false,"image_size":"original"},"scan_key_overrides":{},"other":{"loading_complete":true,"master_password_hash":"$pbkdf2-sha256$29000$dm6NcU5JaU2p1dqbM2aMMQ$U4sJCHcdZe6kEYxBSqIoQ46pgtjyCt8N1flCTGj06tY","loading_started":true,"anime_directory":"/tmp/aniworld_test_anime"}}
-
-${resp} = <Response [200]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-${resp} = <Response [200]>
-${resp}
-/api/config/backups/${name_before}/restore
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${resp}
-200
-Assert that the response status code matches the expected value.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
Create a backup, change config, then restore and verify reversion.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
+Creating session: anon
anon
${BASE_URL}
Create Session: create a HTTP session to a server
-
+
Create an unauthenticated HTTP session.
-
+
-${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': '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
@@ -3687,34 +2636,160 @@ Skips setup/login if already authenticated (suite-level setup done).
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': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
- body={"detail":"Master password already configured"}
-
-${resp} = <Response [400]>
+Starting new HTTP connection (1): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (2): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (3): 127.0.0.1:8765
+Incremented Retry for (url='/api/auth/setup'): RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Starting new HTTP connection (4): 127.0.0.1:8765
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 204, in _new_conn
+ sock = connection.create_connection(
+ (self._dns_host, self.port),
+ ...<2 lines>...
+ socket_options=self.socket_options,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 85, in create_connection
+ raise err
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/connection.py", line 73, in create_connection
+ sock.connect(sa)
+ ~~~~~~~~~~~~^^^^
+ConnectionRefusedError: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 788, in urlopen
+ response = self._make_request(
+ conn,
+ ...<10 lines>...
+ **response_kw,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 493, in _make_request
+ conn.request(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<6 lines>...
+ enforce_content_length=enforce_content_length,
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 500, in request
+ self.endheaders()
+ ~~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1333, in endheaders
+ self._send_output(message_body, encode_chunked=encode_chunked)
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1093, in _send_output
+ self.send(msg)
+ ~~~~~~~~~^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/http/client.py", line 1037, in send
+ self.connect()
+ ~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 331, in connect
+ self.sock = self._new_conn()
+ ~~~~~~~~~~~~~~^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connection.py", line 219, in _new_conn
+ raise NewConnectionError(
+ self, f"Failed to establish a new connection: {e}"
+ ) from e
+urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused
+
+The above exception was the direct cause of the following exception:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 645, in send
+ resp = conn.urlopen(
+ method=request.method,
+ ...<9 lines>...
+ chunked=chunked,
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 872, in urlopen
+ return self.urlopen(
+ ~~~~~~~~~~~~^
+ method,
+ ^^^^^^^
+ ...<13 lines>...
+ **response_kw,
+ ^^^^^^^^^^^^^^
+ )
+ ^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/connectionpool.py", line 842, in urlopen
+ retries = retries.increment(
+ method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
+ )
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/urllib3/util/retry.py", line 543, in increment
+ raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
+
+During handling of the above exception, another exception occurred:
+
+Traceback (most recent call last):
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/utils.py", line 154, in decorator
+ return func(*args, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsOnSessionKeywords.py", line 60, in post_on_session
+ response = self._common_request("post", session, url,
+ data=data, json=json, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/RequestsLibrary/RequestsKeywords.py", line 37, in _common_request
+ resp = method_function(
+ self._merge_url(session, uri),
+ timeout=self._get_timeout(kwargs.pop('timeout', None)),
+ cookies=kwargs.pop('cookies', self.cookies),
+ **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 640, in post
+ return self.request("POST", url, data=data, json=json, **kwargs)
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 592, in request
+ resp = self.send(prep, **send_kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/sessions.py", line 706, in send
+ r = adapter.send(request, **kwargs)
+ File "/home/lukas/miniconda3/lib/python3.13/site-packages/requests/adapters.py", line 678, in send
+ raise ConnectionError(e, request=request)
+requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
${resp}
anon
/api/auth/setup
json=${payload}
expected_status=any
Sends a POST request on a previously created HTTP Session.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
45s
Pauses the test executed for the given time.
-
+
${resp}
@@ -3723,18 +2798,18 @@ Skips setup/login if already authenticated (suite-level setup done).
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}
@@ -3743,46 +2818,44 @@ Skips setup/login if already authenticated (suite-level setup done).
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.
-
+
-
+
-
+
@@ -3790,137 +2863,22 @@ Skips setup/login if already authenticated (suite-level setup done).
${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.
-
-
-
-
-
-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/api/auth/status
- path_url=/api/auth/status
- 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/api/auth/status
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '41', 'content-type': 'application/json'}
- body={"configured":true,"authenticated":false}
-
-${resp} = <Response [200]>
-${resp}
-anon
-/api/auth/status
-expected_status=200
-Sends a GET request on a previously created HTTP Session.
-
-
-
-${json} = {'configured': True, 'authenticated': False}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${configured} = [True]
-${configured}
-${json}
-$.configured
-Get Value From JSON using JSONPath
-
-
-
-${configured_val} = True
-${configured_val}
-${configured}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-${configured_val}
-
-
-${configured} = True
-${configured}
-Check if the master password has already been configured.
-
-
-
-
-
-Configure the master password via the setup endpoint.
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-${token}
-Log in with the master password and return the JWT access token.
-
-
-
-auth
-${BASE_URL}
-headers={'Authorization': 'Bearer ${token}'}
-Create Session: create a HTTP session to a server
-
-
-
-
-
-
-Creating Session using : alias=auth, url=http://127.0.0.1:8765, headers={'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs'}, 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
-
-
-
-
-
-
-Create an authenticated HTTP session. Performs setup if needed, then logs in.
-Skips setup/login if already authenticated (suite-level setup done).
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Create Anonymous Session
AND
@@ -3928,146 +2886,61 @@ Skips setup/login if already authenticated (suite-level setup done).
AND
Create Authenticated Session
Executes all the given keywords in a sequence.
-
-
-
-
-
-
-POST Request : url=http://127.0.0.1:8765/api/config/backups
- path_url=/api/config/backups
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '0'}
- body=None
-
-POST Response : url=http://127.0.0.1:8765/api/config/backups
- status=201, reason=Created
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '85', 'content-type': 'application/json'}
- body={"name":"config_backup_20260627_135523.json","message":"Backup created successfully"}
-
-${resp} = <Response [201]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-${resp}
-${session}
-${endpoint}
-json=${payload}
-expected_status=${expected_status}
-Sends a POST request on a previously created HTTP Session.
-
-
-
-
-
-
-
-${resp}
-
-
-${resp} = <Response [201]>
-${resp}
-/api/config/backups
-expected_status=201
-Perform an authenticated POST request with optional JSON payload.
-
-
-
-${json} = {'name': 'config_backup_20260627_135523.json', 'message': 'Backup created successfully'}
-${json}
-${resp.text}
-Convert String to JSON object
-
-
-
-${backup_name} = ['config_backup_20260627_135523.json']
-${backup_name}
-${json}
-$.name
-Get Value From JSON using JSONPath
-
-
-
-${name} = config_backup_20260627_135523.json
-${name}
-${backup_name}[0]
-Returns the given values which can then be assigned to a variables.
-
-
-
-
-DELETE Request : url=http://127.0.0.1:8765/api/config/backups/config_backup_20260627_135523.json
- path_url=/api/config/backups/config_backup_20260627_135523.json
- headers={'User-Agent': 'python-requests/2.33.1', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYXN0ZXIiLCJleHAiOjE3ODI2NDc3MjIsImlhdCI6MTc4MjU2MTMyMn0.--vlbTAAA2hgaD0fZcM-E01gJMfeZI9wU6wqkY3O9Fs', 'Content-Length': '0'}
- body=None
-
-DELETE Response : url=http://127.0.0.1:8765/api/config/backups/config_backup_20260627_135523.json
- status=200, reason=OK
- headers={'date': 'Sat, 27 Jun 2026 11:55:22 GMT', 'server': 'uvicorn', 'content-length': '78', 'content-type': 'application/json'}
- body={"message":"Backup 'config_backup_20260627_135523.json' deleted successfully"}
-
-${resp} = <Response [200]>
-${resp}
-${session}
-${endpoint}
-expected_status=${expected_status}
-Sends a DELETE request on a previously created HTTP Session.
-
-
-
-${resp}
-
-
-${del_resp} = <Response [200]>
-${del_resp}
-/api/config/backups/${name}
-Perform an authenticated DELETE request.
-
-
-
-
-Argument types are:
-<class 'int'>
-<class 'str'>
-${response.status_code}
-${expected_status}
-Fails if objects are unequal after converting them to integers.
-
-
-${del_resp}
-200
-Assert that the response status code matches the expected value.
-
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
-Deleting All Sessions
+Deleting All Sessions
Removes all the session objects
-
+
Create a backup and then delete it.
-
+Setup failed:
+ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8765): Max retries exceeded with url: /api/auth/setup (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused"))
Configuration API tests for Aniworld.
Covers get, update, validate, backup create/list/restore/delete, and export/import.
-
+
-All Tests
+All Tests
-Config
+Config
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
+Retrying (RetryAdapter(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError("HTTPConnection(host='127.0.0.1', port=8765): Failed to establish a new connection: [Errno 111] Connection refused")': /api/auth/setup
diff --git a/robot_output/playwright-log.txt b/robot_output/playwright-log.txt
index ec68ac0..b5ed080 100644
--- a/robot_output/playwright-log.txt
+++ b/robot_output/playwright-log.txt
@@ -1,54 +1,54 @@
-{"level":"info","time":"2026-06-27T11:55:23.267Z","seq":1,"component":"browser-library","msg":"Listening on 127.0.0.1:50011"}
-{"level":"error","time":"2026-06-27T11:55:23.316Z","seq":2,"component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.320Z","seq":3,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.320Z","seq":4,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.323Z","seq":5,"suite_id":"s1","suite_name":"Config","test_name":"Config.Update Config","test_id":"s1-t2","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.324Z","seq":6,"suite_id":"s1","suite_name":"Config","test_name":"Config.Update Config","test_id":"s1-t2","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.379Z","seq":7,"suite_id":"s1","suite_name":"Config","test_name":"Config.Update Config","test_id":"s1-t2","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.382Z","seq":8,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.382Z","seq":9,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.385Z","seq":10,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Valid Config","test_id":"s1-t3","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.385Z","seq":11,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Valid Config","test_id":"s1-t3","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.441Z","seq":12,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Valid Config","test_id":"s1-t3","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.443Z","seq":13,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.444Z","seq":14,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.446Z","seq":15,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Config Missing Name","test_id":"s1-t4","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.446Z","seq":16,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Config Missing Name","test_id":"s1-t4","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.533Z","seq":17,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Config Missing Name","test_id":"s1-t4","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.536Z","seq":18,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.536Z","seq":19,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.539Z","seq":20,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Schedule Time","test_id":"s1-t5","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.539Z","seq":21,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Schedule Time","test_id":"s1-t5","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.580Z","seq":22,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Schedule Time","test_id":"s1-t5","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.583Z","seq":23,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.583Z","seq":24,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.586Z","seq":25,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Log Level","test_id":"s1-t6","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.586Z","seq":26,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Log Level","test_id":"s1-t6","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.629Z","seq":27,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Log Level","test_id":"s1-t6","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.632Z","seq":28,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.632Z","seq":29,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.635Z","seq":30,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Create","test_id":"s1-t7","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.635Z","seq":31,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Create","test_id":"s1-t7","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.676Z","seq":32,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Create","test_id":"s1-t7","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.679Z","seq":33,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.679Z","seq":34,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.681Z","seq":35,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup List","test_id":"s1-t8","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.681Z","seq":36,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup List","test_id":"s1-t8","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.739Z","seq":37,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup List","test_id":"s1-t8","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.742Z","seq":38,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.742Z","seq":39,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.744Z","seq":40,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Restore","test_id":"s1-t9","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.745Z","seq":41,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Restore","test_id":"s1-t9","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.814Z","seq":42,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Restore","test_id":"s1-t9","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.816Z","seq":43,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.816Z","seq":44,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.819Z","seq":45,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Delete","test_id":"s1-t10","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.819Z","seq":46,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Delete","test_id":"s1-t10","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.876Z","seq":47,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Delete","test_id":"s1-t10","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.878Z","seq":48,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.878Z","seq":49,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"error","time":"2026-06-27T11:55:23.880Z","seq":50,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
-{"level":"info","time":"2026-06-27T11:55:23.882Z","seq":51,"component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.882Z","seq":52,"component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
-{"level":"info","time":"2026-06-27T11:55:23.918Z","seq":53,"component":"browser-library","event_kind":"grpc","action":"closeAllBrowsers","status":"started"}
-{"level":"info","time":"2026-06-27T11:55:23.918Z","seq":54,"component":"browser-library","event_kind":"grpc","action":"closeAllBrowsers","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:34.302Z","seq":1,"component":"browser-library","msg":"Listening on 127.0.0.1:36123"}
+{"level":"error","time":"2026-06-28T13:57:34.371Z","seq":2,"component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:34.375Z","seq":3,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:34.375Z","seq":4,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:34.379Z","seq":5,"suite_id":"s1","suite_name":"Config","test_name":"Config.Update Config","test_id":"s1-t2","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:34.379Z","seq":6,"suite_id":"s1","suite_name":"Config","test_name":"Config.Update Config","test_id":"s1-t2","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:34.991Z","seq":7,"suite_id":"s1","suite_name":"Config","test_name":"Config.Update Config","test_id":"s1-t2","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:34.994Z","seq":8,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:34.994Z","seq":9,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:34.997Z","seq":10,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Valid Config","test_id":"s1-t3","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:34.997Z","seq":11,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Valid Config","test_id":"s1-t3","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:35.610Z","seq":12,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Valid Config","test_id":"s1-t3","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:35.613Z","seq":13,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:35.613Z","seq":14,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:35.615Z","seq":15,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Config Missing Name","test_id":"s1-t4","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:35.615Z","seq":16,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Config Missing Name","test_id":"s1-t4","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:36.228Z","seq":17,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Config Missing Name","test_id":"s1-t4","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:36.230Z","seq":18,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:36.230Z","seq":19,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:36.233Z","seq":20,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Schedule Time","test_id":"s1-t5","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:36.233Z","seq":21,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Schedule Time","test_id":"s1-t5","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:36.845Z","seq":22,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Schedule Time","test_id":"s1-t5","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:36.848Z","seq":23,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:36.848Z","seq":24,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:36.850Z","seq":25,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Log Level","test_id":"s1-t6","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:36.851Z","seq":26,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Log Level","test_id":"s1-t6","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:37.463Z","seq":27,"suite_id":"s1","suite_name":"Config","test_name":"Config.Validate Invalid Log Level","test_id":"s1-t6","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:37.465Z","seq":28,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:37.465Z","seq":29,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:37.468Z","seq":30,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Create","test_id":"s1-t7","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:37.468Z","seq":31,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Create","test_id":"s1-t7","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:38.080Z","seq":32,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Create","test_id":"s1-t7","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:38.082Z","seq":33,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:38.083Z","seq":34,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:38.085Z","seq":35,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup List","test_id":"s1-t8","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:38.085Z","seq":36,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup List","test_id":"s1-t8","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:38.699Z","seq":37,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup List","test_id":"s1-t8","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:38.701Z","seq":38,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:38.702Z","seq":39,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:38.704Z","seq":40,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Restore","test_id":"s1-t9","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:38.704Z","seq":41,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Restore","test_id":"s1-t9","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:39.317Z","seq":42,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Restore","test_id":"s1-t9","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:39.320Z","seq":43,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:39.320Z","seq":44,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:39.323Z","seq":45,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Delete","test_id":"s1-t10","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:39.323Z","seq":46,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Delete","test_id":"s1-t10","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:39.935Z","seq":47,"suite_id":"s1","suite_name":"Config","test_name":"Config.Config Backup Delete","test_id":"s1-t10","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:39.938Z","seq":48,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:39.938Z","seq":49,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"error","time":"2026-06-28T13:57:39.939Z","seq":50,"suite_id":"s1","suite_name":"Config","component":"browser-library","event_kind":"grpc_error","status":"failed","error_type":"Error","msg":"Error: Browser has been closed.\n at PlaywrightState.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:12594:13)\n at PlaywrightServer.getActiveBrowser (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13516:52)\n at PlaywrightServer.setTimeout (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js:13734:56)\n at Object.onReceiveHalfClose (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server.js:1478:25)\n at BaseServerInterceptingCall.maybePushNextMessage (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:594:31)\n at BaseServerInterceptingCall.handleEndEvent (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:634:14)\n at ServerHttp2Stream. (/home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/node_modules/@grpc/grpc-js/build/src/server-interceptors.js:387:18)\n at ServerHttp2Stream.emit (node:events:531:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:89:21)"}
+{"level":"info","time":"2026-06-28T13:57:39.942Z","seq":51,"component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:39.942Z","seq":52,"component":"browser-library","event_kind":"grpc","action":"getBrowserCatalog","status":"succeeded"}
+{"level":"info","time":"2026-06-28T13:57:39.966Z","seq":53,"component":"browser-library","event_kind":"grpc","action":"closeAllBrowsers","status":"started"}
+{"level":"info","time":"2026-06-28T13:57:39.967Z","seq":54,"component":"browser-library","event_kind":"grpc","action":"closeAllBrowsers","status":"succeeded"}
diff --git a/robot_output/report.html b/robot_output/report.html
index 446e685..5d8cf73 100644
--- a/robot_output/report.html
+++ b/robot_output/report.html
@@ -1881,22 +1881,22 @@ storage = function () {
window.output = {};