- Remove completed Task 17 and 18 from Docs/tasks.md - Remove ANIWORLD_TESTING bypass in _check_locked (testing env now uses test auth service) - Remove redundant lock expiry cleanup (handled by _get_fail_record) - Fix login.html whitespace formatting - Increase setup retry wait from 6s to 45s for rate-limited CI environments
1680 lines
78 KiB
XML
1680 lines
78 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<robot generator="Robot 7.4.2 (Python 3.13.5 on linux)" generated="2026-06-26T21:00:40.600072" rpa="false" schemaversion="5">
|
|
<suite id="s1" name="Login" source="/home/lukas/Volume/repo/Aniworld/tests/robot/ui/login.robot">
|
|
<test id="s1-t1" name="Login Page Loads" line="18">
|
|
<kw name="Run Keywords" owner="BuiltIn" type="SETUP">
|
|
<kw name="Create Anonymous Session" owner="common">
|
|
<kw name="Create Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:00:40.814324" level="INFO">Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0 </msg>
|
|
<arg>anon</arg>
|
|
<arg>${BASE_URL}</arg>
|
|
<doc>Create Session: create a HTTP session to a server</doc>
|
|
<status status="PASS" start="2026-06-26T21:00:40.814151" elapsed="0.000325"/>
|
|
</kw>
|
|
<doc>Create an unauthenticated HTTP session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:00:40.813916" elapsed="0.000637"/>
|
|
</kw>
|
|
<kw name="Setup Master Password" owner="common">
|
|
<kw name="Create Dictionary" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:00:40.815395" level="INFO">${payload} = {'master_password': 'TestPass123!', 'anime_directory': '/tmp/aniworld_test_anime', 'name': 'AniworldTest', 'data_dir': 'data', 'scheduler_enabled': 'False', 'logging_level': 'INFO', 'backup_enabled': ...</msg>
|
|
<var>${payload}</var>
|
|
<arg>master_password=${SETUP_PASSWORD}</arg>
|
|
<arg>anime_directory=/tmp/aniworld_test_anime</arg>
|
|
<arg>name=AniworldTest</arg>
|
|
<arg>data_dir=data</arg>
|
|
<arg>scheduler_enabled=False</arg>
|
|
<arg>logging_level=INFO</arg>
|
|
<arg>backup_enabled=False</arg>
|
|
<doc>Creates and returns a dictionary based on the given ``items``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:00:40.815012" elapsed="0.000411"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:00:40.817588" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:00:40.817655" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=429, reason=Too Many Requests
|
|
headers={'date': 'Fri, 26 Jun 2026 19:00:40 GMT', 'server': 'uvicorn', 'content-length': '74', 'content-type': 'application/json'}
|
|
body={"detail":"Too many authentication attempts, try again later. IP lockout"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:00:40.817747" level="INFO">${resp} = <Response [429]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:00:40.815520" elapsed="0.002249"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:01:25.818635" level="INFO">Slept 45 seconds.</msg>
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="PASS" start="2026-06-26T21:00:40.818286" elapsed="45.000457"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:25.821519" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:25.821580" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=400, reason=Bad Request
|
|
headers={'date': 'Fri, 26 Jun 2026 19:01:25 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
|
|
body={"detail":"Master password already configured"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:25.821689" level="INFO">${resp} = <Response [400]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:25.818900" elapsed="0.002810"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:00:40.817870" elapsed="45.003901"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:00:40.817849" elapsed="45.003966"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.822413" elapsed="0.000057"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.822554" elapsed="0.000045"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.821879" elapsed="0.000757"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:25.821859" elapsed="0.000808"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '400'">
|
|
<kw name="Convert String To Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:01:25.823440" level="INFO">${json} = {'detail': 'Master password already configured'}</msg>
|
|
<var>${json}</var>
|
|
<arg>${resp.text}</arg>
|
|
<doc>Convert String to JSON object</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:25.823083" elapsed="0.000381"/>
|
|
</kw>
|
|
<kw name="Get Value From Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:01:25.836407" level="INFO">${detail} = ['Master password already configured']</msg>
|
|
<var>${detail}</var>
|
|
<arg>${json}</arg>
|
|
<arg>$.detail</arg>
|
|
<doc>Get Value From JSON using JSONPath</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:25.823548" elapsed="0.012899"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${detail}[0]' == 'Master password already configured'">
|
|
<return>
|
|
<status status="PASS" start="2026-06-26T21:01:25.836838" elapsed="0.000080"/>
|
|
</return>
|
|
<status status="PASS" start="2026-06-26T21:01:25.836550" elapsed="0.000411"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:25.836531" elapsed="0.000460"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Setup failed with 400: ${detail}</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.837087" elapsed="0.000055"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:01:25.822716" elapsed="0.014460"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:25.822703" elapsed="0.014500"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '201'">
|
|
<kw name="Should Be Equal As Integers" owner="BuiltIn">
|
|
<arg>${resp.status_code}</arg>
|
|
<arg>201</arg>
|
|
<doc>Fails if objects are unequal after converting them to integers.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.837342" elapsed="0.000043"/>
|
|
</kw>
|
|
<return>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.837423" elapsed="0.000038"/>
|
|
</return>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.837245" elapsed="0.000241"/>
|
|
</branch>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.837233" elapsed="0.000275"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Unexpected status ${resp.status_code} from /api/auth/setup</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:25.837575" elapsed="0.000054"/>
|
|
</kw>
|
|
<doc>Configure the master password via the setup endpoint.</doc>
|
|
<status status="PASS" start="2026-06-26T21:00:40.814798" elapsed="45.022908"/>
|
|
</kw>
|
|
<arg>Create Anonymous Session</arg>
|
|
<arg>AND</arg>
|
|
<arg>Setup Master Password</arg>
|
|
<doc>Executes all the given keywords in a sequence.</doc>
|
|
<status status="PASS" start="2026-06-26T21:00:40.813426" elapsed="45.024483"/>
|
|
</kw>
|
|
<kw name="Open Browser To Page" owner="common">
|
|
<kw name="New Page" owner="Browser">
|
|
<msg time="2026-06-26T21:01:25.842728" level="INFO">Starting Browser process /home/lukas/miniconda3/lib/python3.13/site-packages/Browser/wrapper/index.js using at 127.0.0.1:40597</msg>
|
|
<msg time="2026-06-26T21:01:26.652943" level="INFO">Successfully initialized new page object and opened url: http://127.0.0.1:8765/login</msg>
|
|
<msg time="2026-06-26T21:01:26.653006" level="INFO">No browser and context was open. New browser and context was automatically opened when page is created.</msg>
|
|
<arg>${BASE_URL}${path}</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Open a new Page.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:25.838440" elapsed="0.814700"/>
|
|
</kw>
|
|
<arg>/login</arg>
|
|
<doc>Open a new page at the given path relative to BASE_URL.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:25.838102" elapsed="0.815145"/>
|
|
</kw>
|
|
<kw name="Page Title Should Contain" owner="ui_keywords">
|
|
<kw name="Get Title" owner="Browser">
|
|
<msg time="2026-06-26T21:01:26.660636" level="INFO">Title: 'AniWorld Manager - Login'</msg>
|
|
<msg time="2026-06-26T21:01:26.660778" level="INFO">${title} = AniWorld Manager - Login</msg>
|
|
<var>${title}</var>
|
|
<tag>Assertion</tag>
|
|
<tag>Getter</tag>
|
|
<tag>PageContent</tag>
|
|
<doc>Returns the title of the current page.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.653770" elapsed="0.007031"/>
|
|
</kw>
|
|
<kw name="Should Contain" owner="BuiltIn">
|
|
<arg>${title}</arg>
|
|
<arg>${text}</arg>
|
|
<doc>Fails if ``container`` does not contain ``item`` one or more times.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.660960" elapsed="0.000559"/>
|
|
</kw>
|
|
<arg>Login</arg>
|
|
<doc>Assert that the page title contains the given text.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.653409" elapsed="0.008182"/>
|
|
</kw>
|
|
<kw name="Element Should Be Visible" owner="ui_keywords">
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:26.683394" level="INFO">Waited for Element with selector id=password-input at state visible</msg>
|
|
<arg>${selector}</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=5s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.662003" elapsed="0.021532"/>
|
|
</kw>
|
|
<arg>id=password-input</arg>
|
|
<doc>Assert that the element matching the selector is visible.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.661724" elapsed="0.021905"/>
|
|
</kw>
|
|
<kw name="Element Should Be Visible" owner="ui_keywords">
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:26.690216" level="INFO">Waited for Element with selector id=login-submit-btn at state visible</msg>
|
|
<arg>${selector}</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=5s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.684160" elapsed="0.006190"/>
|
|
</kw>
|
|
<arg>id=login-submit-btn</arg>
|
|
<doc>Assert that the element matching the selector is visible.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.683806" elapsed="0.006634"/>
|
|
</kw>
|
|
<kw name="Element Should Be Visible" owner="ui_keywords">
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:26.696018" level="INFO">Waited for Element with selector id=password-toggle at state visible</msg>
|
|
<arg>${selector}</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=5s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.690933" elapsed="0.005204"/>
|
|
</kw>
|
|
<arg>id=password-toggle</arg>
|
|
<doc>Assert that the element matching the selector is visible.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.690591" elapsed="0.005632"/>
|
|
</kw>
|
|
<kw name="Close Browser" owner="common" type="TEARDOWN">
|
|
<kw name="Close Browser" owner="Browser">
|
|
<msg time="2026-06-26T21:01:26.717808" level="INFO">Closed all browsers</msg>
|
|
<arg>ALL</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Closes the current browser.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.696733" elapsed="0.021216"/>
|
|
</kw>
|
|
<doc>Close all browser contexts and the browser itself.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.696425" elapsed="0.021616"/>
|
|
</kw>
|
|
<doc>Verify the login page loads with all form elements.</doc>
|
|
<status status="PASS" start="2026-06-26T21:00:40.812555" elapsed="45.905530"/>
|
|
</test>
|
|
<test id="s1-t2" name="Login With Valid Password" line="29">
|
|
<kw name="Run Keywords" owner="BuiltIn" type="SETUP">
|
|
<kw name="Create Anonymous Session" owner="common">
|
|
<kw name="Create Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:26.728162" level="INFO">Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0 </msg>
|
|
<arg>anon</arg>
|
|
<arg>${BASE_URL}</arg>
|
|
<doc>Create Session: create a HTTP session to a server</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.728022" elapsed="0.000261"/>
|
|
</kw>
|
|
<doc>Create an unauthenticated HTTP session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.727796" elapsed="0.000549"/>
|
|
</kw>
|
|
<kw name="Setup Master Password" owner="common">
|
|
<kw name="Create Dictionary" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:01:26.729118" level="INFO">${payload} = {'master_password': 'TestPass123!', 'anime_directory': '/tmp/aniworld_test_anime', 'name': 'AniworldTest', 'data_dir': 'data', 'scheduler_enabled': 'False', 'logging_level': 'INFO', 'backup_enabled': ...</msg>
|
|
<var>${payload}</var>
|
|
<arg>master_password=${SETUP_PASSWORD}</arg>
|
|
<arg>anime_directory=/tmp/aniworld_test_anime</arg>
|
|
<arg>name=AniworldTest</arg>
|
|
<arg>data_dir=data</arg>
|
|
<arg>scheduler_enabled=False</arg>
|
|
<arg>logging_level=INFO</arg>
|
|
<arg>backup_enabled=False</arg>
|
|
<doc>Creates and returns a dictionary based on the given ``items``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.728789" elapsed="0.000354"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:26.731060" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:26.731107" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=400, reason=Bad Request
|
|
headers={'date': 'Fri, 26 Jun 2026 19:01:26 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
|
|
body={"detail":"Master password already configured"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:26.731178" level="INFO">${resp} = <Response [400]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.729239" elapsed="0.001958"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.731751" elapsed="0.000094"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.731932" elapsed="0.000093"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.731277" elapsed="0.000896"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:26.731257" elapsed="0.000949"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.732622" elapsed="0.000047"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.732754" elapsed="0.000079"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.732250" elapsed="0.000618"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:26.732237" elapsed="0.000659"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '400'">
|
|
<kw name="Convert String To Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:01:26.733669" level="INFO">${json} = {'detail': 'Master password already configured'}</msg>
|
|
<var>${json}</var>
|
|
<arg>${resp.text}</arg>
|
|
<doc>Convert String to JSON object</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.733336" elapsed="0.000362"/>
|
|
</kw>
|
|
<kw name="Get Value From Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:01:26.744527" level="INFO">${detail} = ['Master password already configured']</msg>
|
|
<var>${detail}</var>
|
|
<arg>${json}</arg>
|
|
<arg>$.detail</arg>
|
|
<doc>Get Value From JSON using JSONPath</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.733804" elapsed="0.010755"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${detail}[0]' == 'Master password already configured'">
|
|
<return>
|
|
<status status="PASS" start="2026-06-26T21:01:26.744863" elapsed="0.000068"/>
|
|
</return>
|
|
<status status="PASS" start="2026-06-26T21:01:26.744644" elapsed="0.000326"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:26.744626" elapsed="0.000372"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Setup failed with 400: ${detail}</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.745088" elapsed="0.000051"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:01:26.732934" elapsed="0.012240"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:26.732923" elapsed="0.012277"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '201'">
|
|
<kw name="Should Be Equal As Integers" owner="BuiltIn">
|
|
<arg>${resp.status_code}</arg>
|
|
<arg>201</arg>
|
|
<doc>Fails if objects are unequal after converting them to integers.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.745337" elapsed="0.000041"/>
|
|
</kw>
|
|
<return>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.745415" elapsed="0.000036"/>
|
|
</return>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.745240" elapsed="0.000235"/>
|
|
</branch>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.745229" elapsed="0.000267"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Unexpected status ${resp.status_code} from /api/auth/setup</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:26.745550" elapsed="0.000038"/>
|
|
</kw>
|
|
<doc>Configure the master password via the setup endpoint.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.728557" elapsed="0.017084"/>
|
|
</kw>
|
|
<arg>Create Anonymous Session</arg>
|
|
<arg>AND</arg>
|
|
<arg>Setup Master Password</arg>
|
|
<doc>Executes all the given keywords in a sequence.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.727340" elapsed="0.018339"/>
|
|
</kw>
|
|
<kw name="Open Browser To Page" owner="common">
|
|
<kw name="New Page" owner="Browser">
|
|
<msg time="2026-06-26T21:01:27.136030" level="INFO">Successfully initialized new page object and opened url: http://127.0.0.1:8765/login</msg>
|
|
<msg time="2026-06-26T21:01:27.136091" level="INFO">No browser and context was open. New browser and context was automatically opened when page is created.</msg>
|
|
<arg>${BASE_URL}${path}</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Open a new Page.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.746050" elapsed="0.390160"/>
|
|
</kw>
|
|
<arg>/login</arg>
|
|
<doc>Open a new page at the given path relative to BASE_URL.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.745810" elapsed="0.390487"/>
|
|
</kw>
|
|
<kw name="Perform Login" owner="ui_keywords">
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:27.137293" level="INFO">Fills the text 'TestPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>${password}</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:27.136884" elapsed="0.025260"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:01:27.162730" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:27.162317" elapsed="0.034434"/>
|
|
</kw>
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:28.491647" level="INFO">Waited for Element with selector id=search-input at state visible</msg>
|
|
<arg>id=search-input</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=5s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:27.196925" elapsed="1.294947"/>
|
|
</kw>
|
|
<arg>${SETUP_PASSWORD}</arg>
|
|
<doc>Fill the login form and submit it.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:27.136450" elapsed="1.355549"/>
|
|
</kw>
|
|
<kw name="Page Title Should Contain" owner="ui_keywords">
|
|
<kw name="Get Title" owner="Browser">
|
|
<msg time="2026-06-26T21:01:28.495741" level="INFO">Title: 'AniWorld Manager'</msg>
|
|
<msg time="2026-06-26T21:01:28.495861" level="INFO">${title} = AniWorld Manager</msg>
|
|
<var>${title}</var>
|
|
<tag>Assertion</tag>
|
|
<tag>Getter</tag>
|
|
<tag>PageContent</tag>
|
|
<doc>Returns the title of the current page.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.492732" elapsed="0.003149"/>
|
|
</kw>
|
|
<kw name="Should Contain" owner="BuiltIn">
|
|
<arg>${title}</arg>
|
|
<arg>${text}</arg>
|
|
<doc>Fails if ``container`` does not contain ``item`` one or more times.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.496029" elapsed="0.000398"/>
|
|
</kw>
|
|
<arg>AniWorld</arg>
|
|
<doc>Assert that the page title contains the given text.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.492216" elapsed="0.004275"/>
|
|
</kw>
|
|
<kw name="Element Should Be Visible" owner="ui_keywords">
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:28.501119" level="INFO">Waited for Element with selector id=search-input at state visible</msg>
|
|
<arg>${selector}</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=5s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.496897" elapsed="0.004417"/>
|
|
</kw>
|
|
<arg>id=search-input</arg>
|
|
<doc>Assert that the element matching the selector is visible.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.496609" elapsed="0.004841"/>
|
|
</kw>
|
|
<kw name="Close Browser" owner="common" type="TEARDOWN">
|
|
<kw name="Close Browser" owner="Browser">
|
|
<msg time="2026-06-26T21:01:28.522061" level="INFO">Closed all browsers</msg>
|
|
<arg>ALL</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Closes the current browser.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.502075" elapsed="0.020125"/>
|
|
</kw>
|
|
<doc>Close all browser contexts and the browser itself.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.501750" elapsed="0.020548"/>
|
|
</kw>
|
|
<doc>Log in with the correct password and verify redirect to dashboard.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:26.724737" elapsed="1.797751"/>
|
|
</test>
|
|
<test id="s1-t3" name="Login With Invalid Password" line="39">
|
|
<kw name="Run Keywords" owner="BuiltIn" type="SETUP">
|
|
<kw name="Create Anonymous Session" owner="common">
|
|
<kw name="Create Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:28.530053" level="INFO">Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0 </msg>
|
|
<arg>anon</arg>
|
|
<arg>${BASE_URL}</arg>
|
|
<doc>Create Session: create a HTTP session to a server</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.529897" elapsed="0.000269"/>
|
|
</kw>
|
|
<doc>Create an unauthenticated HTTP session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.529654" elapsed="0.000576"/>
|
|
</kw>
|
|
<kw name="Setup Master Password" owner="common">
|
|
<kw name="Create Dictionary" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:01:28.531073" level="INFO">${payload} = {'master_password': 'TestPass123!', 'anime_directory': '/tmp/aniworld_test_anime', 'name': 'AniworldTest', 'data_dir': 'data', 'scheduler_enabled': 'False', 'logging_level': 'INFO', 'backup_enabled': ...</msg>
|
|
<var>${payload}</var>
|
|
<arg>master_password=${SETUP_PASSWORD}</arg>
|
|
<arg>anime_directory=/tmp/aniworld_test_anime</arg>
|
|
<arg>name=AniworldTest</arg>
|
|
<arg>data_dir=data</arg>
|
|
<arg>scheduler_enabled=False</arg>
|
|
<arg>logging_level=INFO</arg>
|
|
<arg>backup_enabled=False</arg>
|
|
<doc>Creates and returns a dictionary based on the given ``items``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.530645" elapsed="0.000459"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:28.533080" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:28.533124" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=400, reason=Bad Request
|
|
headers={'date': 'Fri, 26 Jun 2026 19:01:28 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
|
|
body={"detail":"Master password already configured"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:28.533193" level="INFO">${resp} = <Response [400]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.531210" elapsed="0.002001"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.533710" elapsed="0.000053"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.533844" elapsed="0.000042"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.533288" elapsed="0.000632"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:28.533270" elapsed="0.000681"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.534342" elapsed="0.000042"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.534456" elapsed="0.000038"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.533994" elapsed="0.000533"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:28.533981" elapsed="0.000572"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '400'">
|
|
<kw name="Convert String To Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:01:28.535246" level="INFO">${json} = {'detail': 'Master password already configured'}</msg>
|
|
<var>${json}</var>
|
|
<arg>${resp.text}</arg>
|
|
<doc>Convert String to JSON object</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.534919" elapsed="0.000348"/>
|
|
</kw>
|
|
<kw name="Get Value From Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:01:28.545940" level="INFO">${detail} = ['Master password already configured']</msg>
|
|
<var>${detail}</var>
|
|
<arg>${json}</arg>
|
|
<arg>$.detail</arg>
|
|
<doc>Get Value From JSON using JSONPath</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.535349" elapsed="0.010625"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${detail}[0]' == 'Master password already configured'">
|
|
<return>
|
|
<status status="PASS" start="2026-06-26T21:01:28.546267" elapsed="0.000058"/>
|
|
</return>
|
|
<status status="PASS" start="2026-06-26T21:01:28.546063" elapsed="0.000296"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:28.546044" elapsed="0.000341"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Setup failed with 400: ${detail}</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.546470" elapsed="0.000047"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:01:28.534589" elapsed="0.011959"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:28.534579" elapsed="0.011994"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '201'">
|
|
<kw name="Should Be Equal As Integers" owner="BuiltIn">
|
|
<arg>${resp.status_code}</arg>
|
|
<arg>201</arg>
|
|
<doc>Fails if objects are unequal after converting them to integers.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.546704" elapsed="0.000055"/>
|
|
</kw>
|
|
<return>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.546799" elapsed="0.000039"/>
|
|
</return>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.546609" elapsed="0.000254"/>
|
|
</branch>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.546599" elapsed="0.000287"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Unexpected status ${resp.status_code} from /api/auth/setup</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:28.546944" elapsed="0.000040"/>
|
|
</kw>
|
|
<doc>Configure the master password via the setup endpoint.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.530445" elapsed="0.016595"/>
|
|
</kw>
|
|
<arg>Create Anonymous Session</arg>
|
|
<arg>AND</arg>
|
|
<arg>Setup Master Password</arg>
|
|
<doc>Executes all the given keywords in a sequence.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.529219" elapsed="0.017862"/>
|
|
</kw>
|
|
<kw name="Open Browser To Page" owner="common">
|
|
<kw name="New Page" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.052219" level="INFO">Successfully initialized new page object and opened url: http://127.0.0.1:8765/login</msg>
|
|
<msg time="2026-06-26T21:01:29.052286" level="INFO">No browser and context was open. New browser and context was automatically opened when page is created.</msg>
|
|
<arg>${BASE_URL}${path}</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Open a new Page.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.547438" elapsed="0.504985"/>
|
|
</kw>
|
|
<arg>/login</arg>
|
|
<doc>Open a new page at the given path relative to BASE_URL.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.547198" elapsed="0.505343"/>
|
|
</kw>
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.053435" level="INFO">Fills the text 'WrongPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>WrongPass123!</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.052704" elapsed="0.023399"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.076713" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.076280" elapsed="0.035844"/>
|
|
</kw>
|
|
<kw name="Element Should Be Visible" owner="ui_keywords">
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.139954" level="INFO">Waited for Element with selector id=login-error at state visible</msg>
|
|
<arg>${selector}</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=5s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.112616" elapsed="0.027514"/>
|
|
</kw>
|
|
<arg>id=login-error</arg>
|
|
<doc>Assert that the element matching the selector is visible.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.112320" elapsed="0.027913"/>
|
|
</kw>
|
|
<kw name="Element Text Should Contain" owner="ui_keywords">
|
|
<kw name="Get Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.160376" level="INFO">Text: ['invalid credentials']</msg>
|
|
<msg time="2026-06-26T21:01:29.160498" level="INFO">${element_text} = invalid credentials</msg>
|
|
<var>${element_text}</var>
|
|
<arg>${selector}</arg>
|
|
<tag>Assertion</tag>
|
|
<tag>Getter</tag>
|
|
<tag>PageContent</tag>
|
|
<doc>Returns text attribute of the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.140736" elapsed="0.019783"/>
|
|
</kw>
|
|
<kw name="Should Contain" owner="BuiltIn">
|
|
<arg>${element_text}</arg>
|
|
<arg>${text}</arg>
|
|
<doc>Fails if ``container`` does not contain ``item`` one or more times.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.160669" elapsed="0.000376"/>
|
|
</kw>
|
|
<arg>id=login-error</arg>
|
|
<arg>invalid</arg>
|
|
<doc>Assert that the element's text contains the given substring.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.140394" elapsed="0.020717"/>
|
|
</kw>
|
|
<kw name="Close Browser" owner="common" type="TEARDOWN">
|
|
<kw name="Close Browser" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.177705" level="INFO">Closed all browsers</msg>
|
|
<arg>ALL</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Closes the current browser.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.161530" elapsed="0.016324"/>
|
|
</kw>
|
|
<doc>Close all browser contexts and the browser itself.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.161272" elapsed="0.016674"/>
|
|
</kw>
|
|
<doc>Log in with an incorrect password and verify error message.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:28.526756" elapsed="0.651233"/>
|
|
</test>
|
|
<test id="s1-t4" name="Login Rate Limit UI" line="50">
|
|
<kw name="Run Keywords" owner="BuiltIn" type="SETUP">
|
|
<kw name="Create Anonymous Session" owner="common">
|
|
<kw name="Create Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:29.185318" level="INFO">Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0 </msg>
|
|
<arg>anon</arg>
|
|
<arg>${BASE_URL}</arg>
|
|
<doc>Create Session: create a HTTP session to a server</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.185160" elapsed="0.000273"/>
|
|
</kw>
|
|
<doc>Create an unauthenticated HTTP session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.184905" elapsed="0.000593"/>
|
|
</kw>
|
|
<kw name="Setup Master Password" owner="common">
|
|
<kw name="Create Dictionary" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:01:29.186394" level="INFO">${payload} = {'master_password': 'TestPass123!', 'anime_directory': '/tmp/aniworld_test_anime', 'name': 'AniworldTest', 'data_dir': 'data', 'scheduler_enabled': 'False', 'logging_level': 'INFO', 'backup_enabled': ...</msg>
|
|
<var>${payload}</var>
|
|
<arg>master_password=${SETUP_PASSWORD}</arg>
|
|
<arg>anime_directory=/tmp/aniworld_test_anime</arg>
|
|
<arg>name=AniworldTest</arg>
|
|
<arg>data_dir=data</arg>
|
|
<arg>scheduler_enabled=False</arg>
|
|
<arg>logging_level=INFO</arg>
|
|
<arg>backup_enabled=False</arg>
|
|
<doc>Creates and returns a dictionary based on the given ``items``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.186041" elapsed="0.000378"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:29.188374" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:29.188437" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=400, reason=Bad Request
|
|
headers={'date': 'Fri, 26 Jun 2026 19:01:28 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
|
|
body={"detail":"Master password already configured"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:29.188521" level="INFO">${resp} = <Response [400]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.186519" elapsed="0.002021"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.189167" elapsed="0.000059"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.189315" elapsed="0.000076"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.188639" elapsed="0.000786"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:29.188613" elapsed="0.000844"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.189942" elapsed="0.000098"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.190196" elapsed="0.000070"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.189500" elapsed="0.000806"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:29.189488" elapsed="0.000849"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '400'">
|
|
<kw name="Convert String To Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:01:29.191243" level="INFO">${json} = {'detail': 'Master password already configured'}</msg>
|
|
<var>${json}</var>
|
|
<arg>${resp.text}</arg>
|
|
<doc>Convert String to JSON object</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.190865" elapsed="0.000402"/>
|
|
</kw>
|
|
<kw name="Get Value From Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:01:29.207546" level="INFO">${detail} = ['Master password already configured']</msg>
|
|
<var>${detail}</var>
|
|
<arg>${json}</arg>
|
|
<arg>$.detail</arg>
|
|
<doc>Get Value From JSON using JSONPath</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.191356" elapsed="0.016245"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${detail}[0]' == 'Master password already configured'">
|
|
<return>
|
|
<status status="PASS" start="2026-06-26T21:01:29.208194" elapsed="0.000089"/>
|
|
</return>
|
|
<status status="PASS" start="2026-06-26T21:01:29.207931" elapsed="0.000409"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:29.207898" elapsed="0.000486"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Setup failed with 400: ${detail}</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.208525" elapsed="0.000094"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:01:29.190387" elapsed="0.018286"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:29.190371" elapsed="0.018353"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '201'">
|
|
<kw name="Should Be Equal As Integers" owner="BuiltIn">
|
|
<arg>${resp.status_code}</arg>
|
|
<arg>201</arg>
|
|
<doc>Fails if objects are unequal after converting them to integers.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.208956" elapsed="0.000066"/>
|
|
</kw>
|
|
<return>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.209079" elapsed="0.000058"/>
|
|
</return>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.208787" elapsed="0.000385"/>
|
|
</branch>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.208771" elapsed="0.000435"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Unexpected status ${resp.status_code} from /api/auth/setup</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:01:29.209286" elapsed="0.000065"/>
|
|
</kw>
|
|
<doc>Configure the master password via the setup endpoint.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.185771" elapsed="0.023644"/>
|
|
</kw>
|
|
<arg>Create Anonymous Session</arg>
|
|
<arg>AND</arg>
|
|
<arg>Setup Master Password</arg>
|
|
<doc>Executes all the given keywords in a sequence.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.184436" elapsed="0.025023"/>
|
|
</kw>
|
|
<kw name="Open Browser To Page" owner="common">
|
|
<kw name="New Page" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.639749" level="INFO">Successfully initialized new page object and opened url: http://127.0.0.1:8765/login</msg>
|
|
<msg time="2026-06-26T21:01:29.639830" level="INFO">No browser and context was open. New browser and context was automatically opened when page is created.</msg>
|
|
<arg>${BASE_URL}${path}</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Open a new Page.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.209866" elapsed="0.430124"/>
|
|
</kw>
|
|
<arg>/login</arg>
|
|
<doc>Open a new page at the given path relative to BASE_URL.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.209585" elapsed="0.430534"/>
|
|
</kw>
|
|
<for flavor="IN RANGE">
|
|
<iter>
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.642695" level="INFO">Fills the text 'WrongPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>WrongPass123!</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.642190" elapsed="0.029472"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.672599" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.672008" elapsed="0.044643"/>
|
|
</kw>
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.748878" level="INFO">Waited for Element with selector id=login-error at state visible</msg>
|
|
<arg>id=login-error</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=3s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.716902" elapsed="0.032167"/>
|
|
</kw>
|
|
<var name="${i}">0</var>
|
|
<status status="PASS" start="2026-06-26T21:01:29.641666" elapsed="0.107504"/>
|
|
</iter>
|
|
<iter>
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.750027" level="INFO">Fills the text 'WrongPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>WrongPass123!</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.749623" elapsed="0.011487"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:01:29.761943" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.761362" elapsed="0.249246"/>
|
|
</kw>
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.041208" level="INFO">Waited for Element with selector id=login-error at state visible</msg>
|
|
<arg>id=login-error</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=3s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.010857" elapsed="0.030497"/>
|
|
</kw>
|
|
<var name="${i}">1</var>
|
|
<status status="PASS" start="2026-06-26T21:01:29.749362" elapsed="0.292059"/>
|
|
</iter>
|
|
<iter>
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.042108" level="INFO">Fills the text 'WrongPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>WrongPass123!</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.041746" elapsed="0.006007"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.048581" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.048002" elapsed="0.061963"/>
|
|
</kw>
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.135409" level="INFO">Waited for Element with selector id=login-error at state visible</msg>
|
|
<arg>id=login-error</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=3s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.110146" elapsed="0.025467"/>
|
|
</kw>
|
|
<var name="${i}">2</var>
|
|
<status status="PASS" start="2026-06-26T21:01:30.041547" elapsed="0.094174"/>
|
|
</iter>
|
|
<iter>
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.136650" level="INFO">Fills the text 'WrongPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>WrongPass123!</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.136150" elapsed="0.006710"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.143444" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.143035" elapsed="0.066844"/>
|
|
</kw>
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.235892" level="INFO">Waited for Element with selector id=login-error at state visible</msg>
|
|
<arg>id=login-error</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=3s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.210063" elapsed="0.026014"/>
|
|
</kw>
|
|
<var name="${i}">3</var>
|
|
<status status="PASS" start="2026-06-26T21:01:30.135895" elapsed="0.100266"/>
|
|
</iter>
|
|
<iter>
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.237188" level="INFO">Fills the text 'WrongPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>WrongPass123!</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.236540" elapsed="0.006670"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.243806" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.243387" elapsed="0.066894"/>
|
|
</kw>
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.336576" level="INFO">Waited for Element with selector id=login-error at state visible</msg>
|
|
<arg>id=login-error</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=3s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.310530" elapsed="0.026202"/>
|
|
</kw>
|
|
<var name="${i}">4</var>
|
|
<status status="PASS" start="2026-06-26T21:01:30.236309" elapsed="0.100494"/>
|
|
</iter>
|
|
<iter>
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.337572" level="INFO">Fills the text 'WrongPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>WrongPass123!</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.337122" elapsed="0.006515"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.344236" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.343826" elapsed="0.066726"/>
|
|
</kw>
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.436884" level="INFO">Waited for Element with selector id=login-error at state visible</msg>
|
|
<arg>id=login-error</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=3s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.410748" elapsed="0.026282"/>
|
|
</kw>
|
|
<var name="${i}">5</var>
|
|
<status status="PASS" start="2026-06-26T21:01:30.336927" elapsed="0.100174"/>
|
|
</iter>
|
|
<var>${i}</var>
|
|
<value>6</value>
|
|
<status status="PASS" start="2026-06-26T21:01:29.640222" elapsed="0.796923"/>
|
|
</for>
|
|
<kw name="Element Text Should Contain" owner="ui_keywords">
|
|
<kw name="Get Text" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.461240" level="INFO">Text: ['Too many authentication attempts, try again later. IP lockout']</msg>
|
|
<msg time="2026-06-26T21:01:30.461414" level="INFO">${element_text} = Too many authentication attempts, try again later. IP lockout</msg>
|
|
<var>${element_text}</var>
|
|
<arg>${selector}</arg>
|
|
<tag>Assertion</tag>
|
|
<tag>Getter</tag>
|
|
<tag>PageContent</tag>
|
|
<doc>Returns text attribute of the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.437832" elapsed="0.023615"/>
|
|
</kw>
|
|
<kw name="Should Contain" owner="BuiltIn">
|
|
<arg>${element_text}</arg>
|
|
<arg>${text}</arg>
|
|
<doc>Fails if ``container`` does not contain ``item`` one or more times.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.461662" elapsed="0.000509"/>
|
|
</kw>
|
|
<arg>id=login-error</arg>
|
|
<arg>lockout</arg>
|
|
<doc>Assert that the element's text contains the given substring.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.437327" elapsed="0.024935"/>
|
|
</kw>
|
|
<kw name="Close Browser" owner="common" type="TEARDOWN">
|
|
<kw name="Close Browser" owner="Browser">
|
|
<msg time="2026-06-26T21:01:30.486960" level="INFO">Closed all browsers</msg>
|
|
<arg>ALL</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Closes the current browser.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.462828" elapsed="0.024323"/>
|
|
</kw>
|
|
<doc>Close all browser contexts and the browser itself.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.462494" elapsed="0.024783"/>
|
|
</kw>
|
|
<doc>Submit multiple failed logins and verify lockout message appears.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:29.181789" elapsed="1.305547"/>
|
|
</test>
|
|
<test id="s1-t5" name="Password Visibility Toggle" line="63">
|
|
<kw name="Run Keywords" owner="BuiltIn" type="SETUP">
|
|
<kw name="Create Anonymous Session" owner="common">
|
|
<kw name="Create Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:30.499108" level="INFO">Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0 </msg>
|
|
<arg>anon</arg>
|
|
<arg>${BASE_URL}</arg>
|
|
<doc>Create Session: create a HTTP session to a server</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.498888" elapsed="0.000381"/>
|
|
</kw>
|
|
<doc>Create an unauthenticated HTTP session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.498539" elapsed="0.000822"/>
|
|
</kw>
|
|
<kw name="Setup Master Password" owner="common">
|
|
<kw name="Create Dictionary" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:01:30.500461" level="INFO">${payload} = {'master_password': 'TestPass123!', 'anime_directory': '/tmp/aniworld_test_anime', 'name': 'AniworldTest', 'data_dir': 'data', 'scheduler_enabled': 'False', 'logging_level': 'INFO', 'backup_enabled': ...</msg>
|
|
<var>${payload}</var>
|
|
<arg>master_password=${SETUP_PASSWORD}</arg>
|
|
<arg>anime_directory=/tmp/aniworld_test_anime</arg>
|
|
<arg>name=AniworldTest</arg>
|
|
<arg>data_dir=data</arg>
|
|
<arg>scheduler_enabled=False</arg>
|
|
<arg>logging_level=INFO</arg>
|
|
<arg>backup_enabled=False</arg>
|
|
<doc>Creates and returns a dictionary based on the given ``items``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.499992" elapsed="0.000504"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:01:30.502433" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:30.502505" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=429, reason=Too Many Requests
|
|
headers={'date': 'Fri, 26 Jun 2026 19:01:30 GMT', 'server': 'uvicorn', 'content-length': '74', 'content-type': 'application/json'}
|
|
body={"detail":"Too many authentication attempts, try again later. IP lockout"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:01:30.502631" level="INFO">${resp} = <Response [429]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.500640" elapsed="0.002019"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:02:15.503807" level="INFO">Slept 45 seconds.</msg>
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.503382" elapsed="45.000514"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:02:15.506036" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:02:15.506308" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=429, reason=Too Many Requests
|
|
headers={'date': 'Fri, 26 Jun 2026 19:02:15 GMT', 'server': 'uvicorn', 'content-length': '74', 'content-type': 'application/json'}
|
|
body={"detail":"Too many authentication attempts, try again later. IP lockout"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:02:15.506399" level="INFO">${resp} = <Response [429]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:02:15.504038" elapsed="0.002380"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:01:30.502795" elapsed="45.003675"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:01:30.502769" elapsed="45.003737"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:03:00.507364" level="INFO">Slept 45 seconds.</msg>
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="PASS" start="2026-06-26T21:02:15.507003" elapsed="45.000463"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:03:00.510007" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:03:00.510057" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=400, reason=Bad Request
|
|
headers={'date': 'Fri, 26 Jun 2026 19:03:00 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
|
|
body={"detail":"Master password already configured"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:03:00.510146" level="INFO">${resp} = <Response [400]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:00.507623" elapsed="0.002543"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:02:15.506554" elapsed="45.003666"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:02:15.506539" elapsed="45.003717"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '400'">
|
|
<kw name="Convert String To Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:03:00.511140" level="INFO">${json} = {'detail': 'Master password already configured'}</msg>
|
|
<var>${json}</var>
|
|
<arg>${resp.text}</arg>
|
|
<doc>Convert String to JSON object</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:00.510759" elapsed="0.000405"/>
|
|
</kw>
|
|
<kw name="Get Value From Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:03:00.521814" level="INFO">${detail} = ['Master password already configured']</msg>
|
|
<var>${detail}</var>
|
|
<arg>${json}</arg>
|
|
<arg>$.detail</arg>
|
|
<doc>Get Value From JSON using JSONPath</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:00.511259" elapsed="0.010594"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${detail}[0]' == 'Master password already configured'">
|
|
<return>
|
|
<status status="PASS" start="2026-06-26T21:03:00.522158" elapsed="0.000067"/>
|
|
</return>
|
|
<status status="PASS" start="2026-06-26T21:03:00.521952" elapsed="0.000309"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:03:00.521932" elapsed="0.000356"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Setup failed with 400: ${detail}</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:00.522381" elapsed="0.000050"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:03:00.510306" elapsed="0.012159"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:03:00.510291" elapsed="0.012200"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '201'">
|
|
<kw name="Should Be Equal As Integers" owner="BuiltIn">
|
|
<arg>${resp.status_code}</arg>
|
|
<arg>201</arg>
|
|
<doc>Fails if objects are unequal after converting them to integers.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:00.522625" elapsed="0.000042"/>
|
|
</kw>
|
|
<return>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:00.522714" elapsed="0.000041"/>
|
|
</return>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:00.522529" elapsed="0.000250"/>
|
|
</branch>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:00.522518" elapsed="0.000283"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Unexpected status ${resp.status_code} from /api/auth/setup</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:00.522854" elapsed="0.000041"/>
|
|
</kw>
|
|
<doc>Configure the master password via the setup endpoint.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.499675" elapsed="90.023275"/>
|
|
</kw>
|
|
<arg>Create Anonymous Session</arg>
|
|
<arg>AND</arg>
|
|
<arg>Setup Master Password</arg>
|
|
<doc>Executes all the given keywords in a sequence.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.497893" elapsed="90.025097"/>
|
|
</kw>
|
|
<kw name="Open Browser To Page" owner="common">
|
|
<kw name="New Page" owner="Browser">
|
|
<msg time="2026-06-26T21:03:00.965152" level="INFO">Successfully initialized new page object and opened url: http://127.0.0.1:8765/login</msg>
|
|
<msg time="2026-06-26T21:03:00.965217" level="INFO">No browser and context was open. New browser and context was automatically opened when page is created.</msg>
|
|
<arg>${BASE_URL}${path}</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Open a new Page.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:00.523394" elapsed="0.441950"/>
|
|
</kw>
|
|
<arg>/login</arg>
|
|
<doc>Open a new page at the given path relative to BASE_URL.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:00.523108" elapsed="0.442331"/>
|
|
</kw>
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:03:00.966049" level="INFO">Fills the text 'TestPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>${SETUP_PASSWORD}</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:00.965566" elapsed="0.030035"/>
|
|
</kw>
|
|
<kw name="Get Attribute" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.015959" level="INFO">Attribute is: 'password'</msg>
|
|
<msg time="2026-06-26T21:03:01.016089" level="INFO">${type_before} = password</msg>
|
|
<var>${type_before}</var>
|
|
<arg>id=password-input</arg>
|
|
<arg>type</arg>
|
|
<tag>Assertion</tag>
|
|
<tag>Getter</tag>
|
|
<tag>PageContent</tag>
|
|
<doc>Returns the HTML ``attribute`` of the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:00.995796" elapsed="0.020314"/>
|
|
</kw>
|
|
<kw name="Should Be Equal As Strings" owner="BuiltIn">
|
|
<arg>${type_before}</arg>
|
|
<arg>password</arg>
|
|
<doc>Fails if objects are unequal after converting them to strings.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.016291" elapsed="0.000390"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.017161" level="INFO">Clicks the element 'id=password-toggle'.</msg>
|
|
<arg>id=password-toggle</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.016807" elapsed="0.041433"/>
|
|
</kw>
|
|
<kw name="Get Attribute" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.064323" level="INFO">Attribute is: 'text'</msg>
|
|
<msg time="2026-06-26T21:03:01.064444" level="INFO">${type_after} = text</msg>
|
|
<var>${type_after}</var>
|
|
<arg>id=password-input</arg>
|
|
<arg>type</arg>
|
|
<tag>Assertion</tag>
|
|
<tag>Getter</tag>
|
|
<tag>PageContent</tag>
|
|
<doc>Returns the HTML ``attribute`` of the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.058421" elapsed="0.006045"/>
|
|
</kw>
|
|
<kw name="Should Be Equal As Strings" owner="BuiltIn">
|
|
<arg>${type_after}</arg>
|
|
<arg>text</arg>
|
|
<doc>Fails if objects are unequal after converting them to strings.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.064779" elapsed="0.000341"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.065532" level="INFO">Clicks the element 'id=password-toggle'.</msg>
|
|
<arg>id=password-toggle</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.065229" elapsed="0.041586"/>
|
|
</kw>
|
|
<kw name="Get Attribute" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.113044" level="INFO">Attribute is: 'password'</msg>
|
|
<msg time="2026-06-26T21:03:01.113166" level="INFO">${type_final} = password</msg>
|
|
<var>${type_final}</var>
|
|
<arg>id=password-input</arg>
|
|
<arg>type</arg>
|
|
<tag>Assertion</tag>
|
|
<tag>Getter</tag>
|
|
<tag>PageContent</tag>
|
|
<doc>Returns the HTML ``attribute`` of the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.107025" elapsed="0.006162"/>
|
|
</kw>
|
|
<kw name="Should Be Equal As Strings" owner="BuiltIn">
|
|
<arg>${type_final}</arg>
|
|
<arg>password</arg>
|
|
<doc>Fails if objects are unequal after converting them to strings.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.113337" elapsed="0.000378"/>
|
|
</kw>
|
|
<kw name="Close Browser" owner="common" type="TEARDOWN">
|
|
<kw name="Close Browser" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.136141" level="INFO">Closed all browsers</msg>
|
|
<arg>ALL</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Closes the current browser.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.114128" elapsed="0.022158"/>
|
|
</kw>
|
|
<doc>Close all browser contexts and the browser itself.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.113895" elapsed="0.022486"/>
|
|
</kw>
|
|
<doc>Click the eye icon and verify the password field type toggles.</doc>
|
|
<status status="PASS" start="2026-06-26T21:01:30.494554" elapsed="90.641867"/>
|
|
</test>
|
|
<test id="s1-t6" name="Logout" line="79">
|
|
<kw name="Run Keywords" owner="BuiltIn" type="SETUP">
|
|
<kw name="Create Anonymous Session" owner="common">
|
|
<kw name="Create Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:03:01.145131" level="INFO">Creating Session using : alias=anon, url=http://127.0.0.1:8765, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0 </msg>
|
|
<arg>anon</arg>
|
|
<arg>${BASE_URL}</arg>
|
|
<doc>Create Session: create a HTTP session to a server</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.144991" elapsed="0.000251"/>
|
|
</kw>
|
|
<doc>Create an unauthenticated HTTP session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.144758" elapsed="0.000547"/>
|
|
</kw>
|
|
<kw name="Setup Master Password" owner="common">
|
|
<kw name="Create Dictionary" owner="BuiltIn">
|
|
<msg time="2026-06-26T21:03:01.146063" level="INFO">${payload} = {'master_password': 'TestPass123!', 'anime_directory': '/tmp/aniworld_test_anime', 'name': 'AniworldTest', 'data_dir': 'data', 'scheduler_enabled': 'False', 'logging_level': 'INFO', 'backup_enabled': ...</msg>
|
|
<var>${payload}</var>
|
|
<arg>master_password=${SETUP_PASSWORD}</arg>
|
|
<arg>anime_directory=/tmp/aniworld_test_anime</arg>
|
|
<arg>name=AniworldTest</arg>
|
|
<arg>data_dir=data</arg>
|
|
<arg>scheduler_enabled=False</arg>
|
|
<arg>logging_level=INFO</arg>
|
|
<arg>backup_enabled=False</arg>
|
|
<doc>Creates and returns a dictionary based on the given ``items``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.145739" elapsed="0.000346"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<msg time="2026-06-26T21:03:01.148344" level="INFO">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"}'
|
|
</msg>
|
|
<msg time="2026-06-26T21:03:01.148393" level="INFO">POST Response : url=http://127.0.0.1:8765/api/auth/setup
|
|
status=400, reason=Bad Request
|
|
headers={'date': 'Fri, 26 Jun 2026 19:03:00 GMT', 'server': 'uvicorn', 'content-length': '47', 'content-type': 'application/json'}
|
|
body={"detail":"Master password already configured"}
|
|
</msg>
|
|
<msg time="2026-06-26T21:03:01.148466" level="INFO">${resp} = <Response [400]></msg>
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.146178" elapsed="0.002307"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.149034" elapsed="0.000058"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.149177" elapsed="0.000045"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.148570" elapsed="0.000689"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:03:01.148551" elapsed="0.000740"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '429'">
|
|
<kw name="Sleep" owner="BuiltIn">
|
|
<arg>45s</arg>
|
|
<doc>Pauses the test executed for the given time.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.149702" elapsed="0.000047"/>
|
|
</kw>
|
|
<kw name="POST On Session" owner="RequestsLibrary">
|
|
<var>${resp}</var>
|
|
<arg>anon</arg>
|
|
<arg>/api/auth/setup</arg>
|
|
<arg>json=${payload}</arg>
|
|
<arg>expected_status=any</arg>
|
|
<doc>Sends a POST request on a previously created HTTP Session.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.149823" elapsed="0.000040"/>
|
|
</kw>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.149334" elapsed="0.000562"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:03:01.149322" elapsed="0.000600"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '400'">
|
|
<kw name="Convert String To Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:03:01.150626" level="INFO">${json} = {'detail': 'Master password already configured'}</msg>
|
|
<var>${json}</var>
|
|
<arg>${resp.text}</arg>
|
|
<doc>Convert String to JSON object</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.150291" elapsed="0.000357"/>
|
|
</kw>
|
|
<kw name="Get Value From Json" owner="JSONLibrary">
|
|
<msg time="2026-06-26T21:03:01.161500" level="INFO">${detail} = ['Master password already configured']</msg>
|
|
<var>${detail}</var>
|
|
<arg>${json}</arg>
|
|
<arg>$.detail</arg>
|
|
<doc>Get Value From JSON using JSONPath</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.150736" elapsed="0.010805"/>
|
|
</kw>
|
|
<if>
|
|
<branch type="IF" condition="'${detail}[0]' == 'Master password already configured'">
|
|
<return>
|
|
<status status="PASS" start="2026-06-26T21:03:01.161884" elapsed="0.000065"/>
|
|
</return>
|
|
<status status="PASS" start="2026-06-26T21:03:01.161639" elapsed="0.000349"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:03:01.161620" elapsed="0.000397"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Setup failed with 400: ${detail}</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.162115" elapsed="0.000053"/>
|
|
</kw>
|
|
<status status="PASS" start="2026-06-26T21:03:01.149959" elapsed="0.012244"/>
|
|
</branch>
|
|
<status status="PASS" start="2026-06-26T21:03:01.149948" elapsed="0.012283"/>
|
|
</if>
|
|
<if>
|
|
<branch type="IF" condition="'${resp.status_code}' == '201'">
|
|
<kw name="Should Be Equal As Integers" owner="BuiltIn">
|
|
<arg>${resp.status_code}</arg>
|
|
<arg>201</arg>
|
|
<doc>Fails if objects are unequal after converting them to integers.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.162371" elapsed="0.000167"/>
|
|
</kw>
|
|
<return>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.162585" elapsed="0.000042"/>
|
|
</return>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.162272" elapsed="0.000381"/>
|
|
</branch>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.162260" elapsed="0.000417"/>
|
|
</if>
|
|
<kw name="Fail" owner="BuiltIn">
|
|
<arg>Unexpected status ${resp.status_code} from /api/auth/setup</arg>
|
|
<doc>Fails the test with the given message and optionally alters its tags.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:01.162747" elapsed="0.000057"/>
|
|
</kw>
|
|
<doc>Configure the master password via the setup endpoint.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.145519" elapsed="0.017346"/>
|
|
</kw>
|
|
<arg>Create Anonymous Session</arg>
|
|
<arg>AND</arg>
|
|
<arg>Setup Master Password</arg>
|
|
<doc>Executes all the given keywords in a sequence.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.144298" elapsed="0.018609"/>
|
|
</kw>
|
|
<kw name="Open Browser To Page" owner="common">
|
|
<kw name="New Page" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.494592" level="INFO">Successfully initialized new page object and opened url: http://127.0.0.1:8765/login</msg>
|
|
<msg time="2026-06-26T21:03:01.494658" level="INFO">No browser and context was open. New browser and context was automatically opened when page is created.</msg>
|
|
<arg>${BASE_URL}${path}</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Open a new Page.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.163292" elapsed="0.331503"/>
|
|
</kw>
|
|
<arg>/login</arg>
|
|
<doc>Open a new page at the given path relative to BASE_URL.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.163034" elapsed="0.331856"/>
|
|
</kw>
|
|
<kw name="Perform Login" owner="ui_keywords">
|
|
<kw name="Fill Text" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.495882" level="INFO">Fills the text 'TestPass123!' in the given field.</msg>
|
|
<arg>id=password-input</arg>
|
|
<arg>${password}</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Clears and fills the given ``txt`` into the text field found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.495447" elapsed="0.024224"/>
|
|
</kw>
|
|
<kw name="Click" owner="Browser">
|
|
<msg time="2026-06-26T21:03:01.520399" level="INFO">Clicks the element 'id=login-submit-btn'.</msg>
|
|
<arg>id=login-submit-btn</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Simulates mouse click on the element found by ``selector``.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:01.519889" elapsed="0.038702"/>
|
|
</kw>
|
|
<kw name="Wait For Elements State" owner="Browser">
|
|
<msg time="2026-06-26T21:03:06.766514" level="INFO" html="true"></td></tr><tr><td colspan="3"><a href="browser/screenshot/fail-screenshot-1.png" target="_blank"><img src="browser/screenshot/fail-screenshot-1.png" width="800px"/></a></msg>
|
|
<msg time="2026-06-26T21:03:06.766674" level="INFO">See also file:///home/lukas/Volume/repo/Aniworld/robot_output/playwright-log.txt for additional details.</msg>
|
|
<msg time="2026-06-26T21:03:06.767070" level="FAIL">TimeoutError: locator.waitFor: Timeout 5000ms exceeded.
|
|
Call log:
|
|
- waiting for locator('id=search-input') to be visible
|
|
</msg>
|
|
<arg>id=search-input</arg>
|
|
<arg>visible</arg>
|
|
<arg>timeout=5s</arg>
|
|
<tag>PageContent</tag>
|
|
<tag>Wait</tag>
|
|
<doc>Waits for the element found by ``selector`` to satisfy state option.</doc>
|
|
<status status="FAIL" start="2026-06-26T21:03:01.558787" elapsed="5.211336">TimeoutError: locator.waitFor: Timeout 5000ms exceeded.
|
|
Call log:
|
|
- waiting for locator('id=search-input') to be visible
|
|
</status>
|
|
</kw>
|
|
<arg>${SETUP_PASSWORD}</arg>
|
|
<doc>Fill the login form and submit it.</doc>
|
|
<status status="FAIL" start="2026-06-26T21:03:01.495051" elapsed="5.275287">TimeoutError: locator.waitFor: Timeout 5000ms exceeded.
|
|
Call log:
|
|
- waiting for locator('id=search-input') to be visible
|
|
</status>
|
|
</kw>
|
|
<kw name="Perform Logout" owner="ui_keywords">
|
|
<doc>Click the logout button and wait for redirect to login.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:06.770558" elapsed="0.000139"/>
|
|
</kw>
|
|
<kw name="Page Title Should Contain" owner="ui_keywords">
|
|
<arg>Login</arg>
|
|
<doc>Assert that the page title contains the given text.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:06.770858" elapsed="0.000072"/>
|
|
</kw>
|
|
<kw name="Element Should Be Visible" owner="ui_keywords">
|
|
<arg>id=password-input</arg>
|
|
<doc>Assert that the element matching the selector is visible.</doc>
|
|
<status status="NOT RUN" start="2026-06-26T21:03:06.771053" elapsed="0.000063"/>
|
|
</kw>
|
|
<kw name="Close Browser" owner="common" type="TEARDOWN">
|
|
<kw name="Close Browser" owner="Browser">
|
|
<msg time="2026-06-26T21:03:06.790591" level="INFO">Closed all browsers</msg>
|
|
<arg>ALL</arg>
|
|
<tag>BrowserControl</tag>
|
|
<tag>Setter</tag>
|
|
<doc>Closes the current browser.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:06.771670" elapsed="0.019141"/>
|
|
</kw>
|
|
<doc>Close all browser contexts and the browser itself.</doc>
|
|
<status status="PASS" start="2026-06-26T21:03:06.771357" elapsed="0.019580"/>
|
|
</kw>
|
|
<doc>Log in then log out and verify redirect to login page.</doc>
|
|
<status status="FAIL" start="2026-06-26T21:03:01.141148" elapsed="5.649855">TimeoutError: locator.waitFor: Timeout 5000ms exceeded.
|
|
Call log:
|
|
- waiting for locator('id=search-input') to be visible
|
|
</status>
|
|
</test>
|
|
<doc>Login UI tests for Aniworld.
|
|
Covers login page load, valid/invalid login, rate limit UI, password visibility, and logout.</doc>
|
|
<status status="FAIL" start="2026-06-26T21:00:40.600889" elapsed="146.195442"/>
|
|
</suite>
|
|
<statistics>
|
|
<total>
|
|
<stat pass="5" fail="1" skip="0">All Tests</stat>
|
|
</total>
|
|
<tag>
|
|
</tag>
|
|
<suite>
|
|
<stat name="Login" id="s1" pass="5" fail="1" skip="0">Login</stat>
|
|
</suite>
|
|
</statistics>
|
|
<errors>
|
|
</errors>
|
|
</robot>
|