diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3925894..07b4aaf 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -74,7 +74,7 @@ jobs: robot --outputdir results/playground --variable BROWSER:headlesschrome - tests/_diagnostic.robot + tests/playground - name: Upload playground test results if: always() diff --git a/resources/pages/playground_page.resource b/resources/pages/playground_page.resource index 7c36121..bd1e338 100644 --- a/resources/pages/playground_page.resource +++ b/resources/pages/playground_page.resource @@ -23,6 +23,7 @@ ${CLASS_ATTRIBUTE_TARGET_BUTTON} css:.btn-primary # Hidden Layers ${HIDING_BUTTON} css:#greenButton +${HIDDEN_BLUE_BUTTON} css:#blueButton # Load Delay ${LOAD_DELAY_BUTTON} css:.btn.btn-primary @@ -75,7 +76,7 @@ ${SAMPLE_APP_STATUS_MESSAGE} css:#loginstatus ${SAMPLE_APP_VALID_PASSWORD} pwd # Mouse Over -${MOUSE_OVER_LINK} xpath://a[@class="text-primary" and text()="Click me"] +${MOUSE_OVER_LINK} xpath://a[text()="Click me"] ${MOUSE_OVER_CLICK_COUNT} css:#clickCount ${MOUSE_OVER_BUTTON_LINK} xpath://a[@class="text-primary" and text()="Link Button"] ${MOUSE_OVER_BUTTON_CLICK_COUNT} css:#clickButtonCount @@ -86,6 +87,7 @@ ${NBSP_BUTTON_EXACT_TEXT} xpath://button[text()="My Button"] # Overlapped Element ${OVERLAPPED_NAME_FIELD} css:#name +${OVERLAPPED_NAME_FIELD_SELECTOR} input#name # Shadow DOM ${SHADOW_HOST} guid-generator @@ -203,18 +205,13 @@ Wait Until Animation Stops Fail Element '${locator}' never stopped moving. Set Value Via Javascript - [Documentation] Sets an input's value directly through JavaScript and dispatches an - ... input event so the page's own listeners see the change. Used for the - ... Overlapped Element challenge, where the field is covered by another - ... element and native Selenium keystrokes never register. - [Arguments] ${locator} ${value} - ${element}= Get WebElement ${locator} - Execute Javascript - ... arguments[0].value = arguments[1]; - ... arguments[0].dispatchEvent(new Event('input', {bubbles: true})); - ... ARGUMENTS - ... ${element} - ... ${value} + [Documentation] Sets an input's value directly through JavaScript. Used for the + ... Overlapped Element challenge, where a permanently positioned + ... covering element blocks native Selenium clicks and keystrokes; the + ... field carries no input/change listeners, so a plain property + ... assignment (confirmed against the live page) is sufficient. + [Arguments] ${selector} ${value} + Execute Javascript document.querySelector('${selector}').value = '${value}'; Get Row Cell Values [Documentation] Reads the ARIA role="row" elements of the Dynamic Table challenge diff --git a/tests/_diagnostic.robot b/tests/_diagnostic.robot deleted file mode 100644 index c36f8f0..0000000 --- a/tests/_diagnostic.robot +++ /dev/null @@ -1,62 +0,0 @@ -*** Settings *** -Documentation Temporary diagnostic, round 6: four assertions have now failed twice on -... guessed fixes (Hidden Layers' id-swap, Sample App's valid password, -... Mouse Over's link replacement, Overlapped's JS value-setting) -- this -... gets real evidence instead of guessing a third time. Not part of the -... portfolio. -Resource ../resources/pages/playground_page.resource -Suite Setup Open Browser about:blank ${BROWSER} -Suite Teardown Close All Browsers -Test Tags smoke - - -*** Test Cases *** -Dump Hidden Layers After Click - Go To Playground Page hiddenlayers - ${before}= Execute Javascript return document.querySelector('#spa').outerHTML; - Log SPA BEFORE CLICK: ${before} console=True - Click Element ${HIDING_BUTTON} - ${after}= Execute Javascript return document.querySelector('#spa').outerHTML; - Log SPA AFTER CLICK: ${after} console=True - -Dump Sample App Login Attempt - Go To Playground Page sampleapp - Input Text ${SAMPLE_APP_USERNAME_FIELD} Michelle - Input Text ${SAMPLE_APP_PASSWORD_FIELD} pwd - ${username_value}= Get Element Attribute ${SAMPLE_APP_USERNAME_FIELD} value - ${password_value}= Get Element Attribute ${SAMPLE_APP_PASSWORD_FIELD} value - Log FIELD VALUES BEFORE SUBMIT: username=${username_value} password=${password_value} console=True - Click Button ${SAMPLE_APP_LOGIN_BUTTON} - ${status}= Get Text ${SAMPLE_APP_STATUS_MESSAGE} - Log STATUS AFTER SUBMIT: ${status} console=True - -Dump Mouse Over Link Structure - Go To Playground Page mouseover - ${before}= Execute Javascript - ... return Array.from(document.querySelectorAll('a')).map(function(a) { - ... return 'outerHTML=' + a.outerHTML; - ... }).join(' || '); - Log LINKS BEFORE HOVER: ${before} console=True - Mouse Over css:a.text-primary - Sleep 300ms - ${after}= Execute Javascript - ... return Array.from(document.querySelectorAll('a')).map(function(a) { - ... return 'outerHTML=' + a.outerHTML; - ... }).join(' || '); - Log LINKS AFTER HOVER: ${after} console=True - -Dump Overlapped Field Framework And Direct Js Set - Go To Playground Page overlapped - ${framework}= Execute Javascript - ... var root = document.getElementById('root') || document.getElementById('app') || document.body.firstElementChild; - ... return 'reactroot=' + (root && !!Object.keys(root).find(function(k) { return k.startsWith('__reactContainer') || k.startsWith('_reactRootContainer'); })) + ' outerHTML=' + document.querySelector('#name').outerHTML; - Log OVERLAPPED FIELD INFO: ${framework} console=True - ${direct_result}= Execute Javascript - ... var el = document.querySelector('#name'); - ... el.value = 'Michelle Austria'; - ... el.dispatchEvent(new Event('input', {bubbles: true})); - ... return 'immediately after set: ' + el.value; - Log DIRECT SET RESULT: ${direct_result} console=True - Sleep 300ms - ${value_after_wait}= Get Element Attribute css:#name value - Log VALUE AFTER 300MS WAIT: ${value_after_wait} console=True diff --git a/tests/playground/ui_testing_playground.robot b/tests/playground/ui_testing_playground.robot index 82f5665..8df725e 100644 --- a/tests/playground/ui_testing_playground.robot +++ b/tests/playground/ui_testing_playground.robot @@ -44,16 +44,14 @@ Class Attribute Target Button Should Be Clicked By Its Unique Class ${alert_message}= Handle Alert action=ACCEPT Should Be Equal ${alert_message} Primary button pressed -Clicking The Green Button Should Swap In A Different Layer - [Documentation] The button under #spa is replaced by a different element after the - ... first click, demonstrating a DOM-caching pitfall: a second click against a - ... previously located WebElement reference would silently hit a stale layer. +Clicking The Green Button Should Add A Covering Layer On Top + [Documentation] Clicking the green button doesn't remove it -- it stacks a second, + ... higher z-index layer with a blue button directly on top, so a second click at + ... the same coordinates would silently hit the new layer instead. Go To Playground Page hiddenlayers Wait Until Element Is Visible ${HIDING_BUTTON} Click Element ${HIDING_BUTTON} - ${new_id}= Execute Javascript return document.querySelector('#spa button').id; - Should Not Be Equal ${new_id} greenButton - ... msg=Hidden Layers should swap in a different button after the first click. + Page Should Contain Element ${HIDDEN_BLUE_BUTTON} Button Appearing After Delay Should Eventually Become Clickable [Documentation] The button doesn't exist in a clickable state until the server @@ -163,6 +161,7 @@ Sample App Should Log In With The Valid Password And Reject An Invalid One Input Text ${SAMPLE_APP_PASSWORD_FIELD} wrong-password Click Button ${SAMPLE_APP_LOGIN_BUTTON} Element Text Should Be ${SAMPLE_APP_STATUS_MESSAGE} Invalid username/password + Input Text ${SAMPLE_APP_USERNAME_FIELD} Michelle Input Text ${SAMPLE_APP_PASSWORD_FIELD} ${SAMPLE_APP_VALID_PASSWORD} Click Button ${SAMPLE_APP_LOGIN_BUTTON} Element Text Should Be ${SAMPLE_APP_STATUS_MESSAGE} Welcome, Michelle! @@ -187,11 +186,11 @@ Non Breaking Space Button Should Not Match An Exact Text Locator Click Button ${NBSP_BUTTON} Overlapped Name Field Should Accept Text Set Through Javascript - [Documentation] The field is covered by another element, so native Selenium - ... keystrokes never register; setting the value directly through JavaScript and - ... dispatching an input event is the documented workaround. + [Documentation] A permanently positioned element covers the field, so native + ... Selenium clicks and keystrokes are intercepted; setting the value directly + ... through JavaScript is the workaround. Go To Playground Page overlapped - Set Value Via Javascript ${OVERLAPPED_NAME_FIELD} Michelle Austria + Set Value Via Javascript ${OVERLAPPED_NAME_FIELD_SELECTOR} Michelle Austria ${value}= Get Element Attribute ${OVERLAPPED_NAME_FIELD} value Should Be Equal ${value} Michelle Austria