Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add expected conditions 1827 #1865

Merged
merged 24 commits into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5a6735c
Sketching out initial ideas for test suite on expected conditions
emanlove Jun 9, 2023
583c9e6
Added dynamic and delayed title change as initial test framework for
emanlove Nov 11, 2023
fc60e23
Merge branch 'master' into add-expected-conditions-1827
emanlove Nov 11, 2023
2b10abf
Initial (working) prototype of wait for.. keyword
emanlove Nov 11, 2023
eb49c98
Bumped number of library keywords by one
emanlove Nov 11, 2023
129e9b0
Moved previous expected condition tests out of current test suite
emanlove Nov 11, 2023
36e7da3
Adding another sample tests and modifying keyword behavior
emanlove Nov 11, 2023
48376f7
Added sample test case where an expected timeout would occur
emanlove Nov 11, 2023
3083459
added timeout argument to keyword wait_for_expected_condition
yuriverweij Nov 15, 2023
754e793
Merge pull request #3 from yuriverweij/feature/add_expected_condition…
emanlove Nov 22, 2023
98d8f89
Some intial parsing and validation for parsing condition argument
emanlove Nov 22, 2023
7ad5296
Basic working keyword for wait
emanlove Jan 18, 2024
b022031
Added test case for capitals within expected condition name
emanlove Jan 19, 2024
d23700e
Added example test where expected condition expected "locator" tuple
emanlove Jan 21, 2024
7bdca3c
Added keyword documentation for new `Wait For Expected Condition` key…
emanlove Mar 26, 2024
bd05dfd
Merge branch 'master' into add-expected-conditions-1827
emanlove Mar 26, 2024
fd751bb
Fix Firefox unit tests
emanlove Apr 2, 2024
204ceda
Reduced the timeout on the expected timeout within expected conditions
emanlove Apr 2, 2024
e1a4f4c
Expanded selenium versions upto 4.19.0
emanlove Apr 3, 2024
f17f8f0
Fix acceptance tests
emanlove Apr 5, 2024
de1a4fb
Append results to zip file
emanlove Apr 5, 2024
8db00db
Added selenium version and browser name to archive
emanlove Apr 14, 2024
a0e241d
Upload only failed artifacts
emanlove Apr 14, 2024
cc41bc1
Updated some expected log messages in chrome tests
emanlove Apr 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
matrix:
python-version: [3.8, 3.11] # 3.12, pypy-3.9
rf-version: [5.0.1, 6.1.1, 7.0]
selenium-version: [4.14.0, 4.15.2, 4.16.0] #4.17.0, 4.18.0
selenium-version: [4.14.0, 4.15.2, 4.16.0, 4.17.2, 4.18.1, 4.19.0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's becoming quite a long list again.

browser: [firefox, chrome, headlesschrome] #edge

steps:
Expand Down Expand Up @@ -88,7 +88,7 @@ jobs:
# xvfb-run --auto-servernum python atest/run.py --zip headlesschrome --grid True

- uses: actions/upload-artifact@v1
if: success() || failure()
if: failure()
with:
name: SeleniumLibrary Test results
path: atest/zip_results
34 changes: 34 additions & 0 deletions atest/acceptance/expected_conditions.robot.PROTOTYPE
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
*** Test Cases ***
# Wait Until Element State Is (Not)
# Get Element State
# Element States Should (Not) Be

Check waiting for condition that takes a element
Fail

Check waiting for condition that takes a title
Fail

Check waiting for condition that takes a url
Fail
Wait Until url contains google
# verify took 2 seconds

Check waiting for condition that takes locator and string
Wait Until Element State Is ${condition} ${locator} ${string}
Wait Until Element State Is ${condition} ${element}
Wait Until Condition Is ${condition} ${target}
Wait Until Condition Is ${condition} ${whatelse you need for this condition}


Wait Until State Is number_of_windows_to_be
Wait Until Expected Condition Is number_of_windows_to_be
Wait Until Condition Is number of windows to be 5
Wait Until Condition Is text to be present in element attribute //some/xpath/to/an/element href http://hello

Wait Until Condition Is number of windows to be 5 text to be present in element attribute //some/xpath/to/an/element href http://hello

Wait Until number of windows to be 5
Wait Until text to be present in element attribute //some/xpath/to/an/element href http://hello
Get Condition
Is number of windows to be 5
10 changes: 5 additions & 5 deletions atest/acceptance/keywords/choose_file.robot
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ Choose File With Grid From Library Using SL choose_file method

Input Text Should Work Same Way When Not Using Grid
[Documentation]
... LOG 1:6 DEBUG GLOB: POST*/session/*/clear {*
... LOG 1:9 DEBUG Finished Request
... LOG 1:10 DEBUG GLOB: POST*/session/*/value*"text": "*
... LOG 1:13 DEBUG Finished Request
... LOG 1:14 DEBUG NONE
... LOG 1:6 DEBUG GLOB: POST*/session/*/clear {*
... LOG 1:9 DEBUG Finished Request
... LOG 1:10 DEBUG REGEXP: POST.*/session/.*/value.*['\\\"]text['\\\"]: ['\\\"].*
... LOG 1:13 DEBUG Finished Request
... LOG 1:14 DEBUG NONE
[Tags] NoGrid
[Setup] Touch ${CURDIR}${/}temp.txt
Input Text file_to_upload ${CURDIR}${/}temp.txt
Expand Down
2 changes: 1 addition & 1 deletion atest/acceptance/keywords/click_element.robot
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Click Element Action Chain
[Tags] NoGrid
[Documentation]
... LOB 1:1 INFO Clicking 'singleClickButton' using an action chain.
... LOG 1:6 DEBUG GLOB: *actions {"actions": [{*
... LOG 1:6 DEBUG REGEXP: .*actions {['\\\"]actions['\\\"]: \\\[\\\{.*
Click Element singleClickButton action_chain=True
Element Text Should Be output single clicked

Expand Down
52 changes: 52 additions & 0 deletions atest/acceptance/keywords/expected_conditions.robot
emanlove marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
*** Settings ***
Test Setup Go To Page "javascript/expected_conditions.html"
Resource ../resource.robot

*** Test Cases ***
Wait For Expected Conditions One Argument
Title Should Be Original
Click Element link=delayed change title
Wait For Expected Condition title_is Delayed
emanlove marked this conversation as resolved.
Show resolved Hide resolved
Title Should Be Delayed

Wait For Expected Condition Times out within set timeout
[Documentation] FAIL REGEXP: TimeoutException: Message: Expected Condition not met within set timeout of 0.3*
Title Should Be Original
Click Element link=delayed change title
Wait For Expected Condition title_is Delayed timeout=0.3

Wait For Expected Conditions using WebElement as locator
Click Button Change the button state
${dynamic_btn}= Get WebElement id:enabledDisabledBtn
Wait For Expected Condition element_to_be_clickable ${dynamic_btn}

Wait For Expected Conditions Where Condition Written With Spaces
Title Should Be Original
Click Element link=delayed change title
Wait For Expected Condition title is Delayed
Title Should Be Delayed

Wait For Expected Conditions Where Condition Is Variable
${condition}= Set Variable title is
Title Should Be Original
Click Element link=delayed change title
Wait For Expected Condition ${condition} Delayed
Title Should Be Delayed

Wait For Expected Conditions Where Condition Is Strange Case
Click Button Change the button state
${dynamic_btn}= Get WebElement id:enabledDisabledBtn
Wait For Expected Condition EleMENT tO BE cLiCkAbLe ${dynamic_btn}

Wait For Non Existing Expected Conditions
Click Button Change the button state
${dynamic_btn}= Get WebElement id:enabledDisabledBtn
Run Keyword And Expect Error this_is_not_an_expected_con_dition is an unknown expected condition
... Wait For Expected Condition this_is not an expected con dition ${dynamic_btn}

Wait For Expected Conditions When Condition Includes Locator
Title Should Be Original
${byElem}= Evaluate ("id","added_btn")
Click Element link:delayed add element
Wait For Expected Condition Presence Of Element Located ${byElem}
Click Element id:added_btn
6 changes: 3 additions & 3 deletions atest/acceptance/keywords/page_load_timeout.robot
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Test Teardown Close Browser And Reset Page Load Timeout
*** Test Cases ***
Should Open Browser With Default Page Load Timeout
[Documentation] Verify that 'Open Browser' changes the page load timeout.
... LOG 1.1.1:27 DEBUG REGEXP: POST http://localhost:\\d{2,5}/session/[a-f0-9-]+/timeouts {"pageLoad": 300000}
... LOG 1.1.1:27 DEBUG REGEXP: POST http://localhost:\\d{2,5}/session/[a-f0-9-]+/timeouts {['\\\"]pageLoad['\\\"]: 300000}
... LOG 1.1.1:29 DEBUG STARTS: Remote response: status=200
# Note: previous log check was 33 and 37. Recording to see if something is swtiching back and forth
Open Browser To Start Page
Expand All @@ -21,8 +21,8 @@ Should Run Into Timeout Exception

Should Set Page Load Timeout For All Opened Browsers
[Documentation] One browser is already opened as global suite setup.
... LOG 2:1 DEBUG REGEXP: POST http://localhost:\\d{2,5}/session/[a-f0-9-]+/timeouts {"pageLoad": 5000}
... LOG 2:5 DEBUG REGEXP: POST http://localhost:\\d{2,5}/session/[a-f0-9-]+/timeouts {"pageLoad": 5000}
... LOG 2:1 DEBUG REGEXP: POST http://localhost:\\d{2,5}/session/[a-f0-9-]+/timeouts {['\\\"]pageLoad['\\\"]: 5000}
... LOG 2:5 DEBUG REGEXP: POST http://localhost:\\d{2,5}/session/[a-f0-9-]+/timeouts {['\\\"]pageLoad['\\\"]: 5000}
Open Browser To Start Page
Set Selenium Page Load Timeout 5 s

Expand Down
24 changes: 12 additions & 12 deletions atest/acceptance/multiple_browsers_options.robot
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,32 @@ Documentation Creating test which would work on all browser is not possible.
*** Test Cases ***
Chrome Browser With Selenium Options As String
[Documentation]
... LOG 1:14 DEBUG GLOB: *"goog:chromeOptions"*
... LOG 1:14 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?*
... LOG 1:14 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].*
... LOG 1:14 DEBUG REGEXP: .*args['\\\"]: \\\[['\\\"]--disable-dev-shm-usage['\\\"].*
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument("--disable-dev-shm-usage")

Chrome Browser With Selenium Options As String With Attribute As True
[Documentation]
... LOG 1:14 DEBUG GLOB: *"goog:chromeOptions"*
... LOG 1:14 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?*
... LOG 1:14 DEBUG GLOB: *"--headless=new"*
... LOG 1:14 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].*
... LOG 1:14 DEBUG REGEXP: .*args['\\\"]: \\\[['\\\"]--disable-dev-shm-usage['\\\"].*
... LOG 1:14 DEBUG REGEXP: .*['\\\"]--headless=new['\\\"].*
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument ( "--disable-dev-shm-usage" ) ; add_argument ( "--headless=new" )

Chrome Browser With Selenium Options With Complex Object
[Tags] NoGrid
[Documentation]
... LOG 1:14 DEBUG GLOB: *"goog:chromeOptions"*
... LOG 1:14 DEBUG GLOB: *"mobileEmulation": {"deviceName": "Galaxy S5"*
... LOG 1:14 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?*
... LOG 1:14 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].*
... LOG 1:14 DEBUG REGEXP: .*['\\\"]mobileEmulation['\\\"]: {['\\\"]deviceName['\\\"]: ['\\\"]Galaxy S5['\\\"].*
... LOG 1:14 DEBUG REGEXP: .*args['\\\"]: \\\[['\\\"]--disable-dev-shm-usage['\\\"].*
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument ( "--disable-dev-shm-usage" ) ; add_experimental_option( "mobileEmulation" , { 'deviceName' : 'Galaxy S5'})

Chrome Browser With Selenium Options Object
[Documentation]
... LOG 2:14 DEBUG GLOB: *"goog:chromeOptions"*
... LOG 2:14 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?*
... LOG 2:14 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].*
... LOG 2:14 DEBUG REGEXP: .*args['\\\"]: \\\[['\\\"]--disable-dev-shm-usage['\\\"].*
${options} = Get Chrome Options
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
... desired_capabilities=${DESIRED_CAPABILITIES} options=${options}
Expand All @@ -47,8 +47,8 @@ Chrome Browser With Selenium Options Invalid Method

Chrome Browser With Selenium Options Argument With Semicolon
[Documentation]
... LOG 1:14 DEBUG GLOB: *"goog:chromeOptions"*
... LOG 1:14 DEBUG GLOB: *["has;semicolon"*
... LOG 1:14 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].*
... LOG 1:14 DEBUG REGEXP: .*\\\[['\\\"]has;semicolon['\\\"].*
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument("has;semicolon")

Expand Down
7 changes: 7 additions & 0 deletions atest/resources/html/javascript/dynamic_content.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@
container = document.getElementById(target_container);
container.appendChild(p);
}

function delayed_title_change() {
setTimeout(function(){
document.title='Delayed';
},600);
}
</script>
</head>
<body>
<a href="javascript:return false;" onclick="document.title='Changed'; return false;">change title</a><br/>
<a href="javascript:return false;" onclick="delayed_title_change(); return false;">delayed change title</a><br/>
<a href="javascript:return false;" onclick="add_content('target', 'added content'); return false;">add content</a><br/>
<a id="unicode" href="javascript:return false;" onclick="document.title='äää'; return false;">title to ääää</a><br/>
<p>
Expand Down
95 changes: 95 additions & 0 deletions atest/resources/html/javascript/expected_conditions.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Original</title>
<!-- Note the timeouts in the functions are chosen such they constitute
a set with distinct subset sums. That is is a combination of any two
or more were to be executed the total time for that distinct combination
would be unique. This was done so we could do a ALL/AND/OR type of test
and know that with the combination of expected conditions the execution
was successful as the unique time took place. -->
<!-- The set we are using is {6,9,11,12,13} -->
<!-- (could also use {3,5,6,7} which would reduce total time)-->
<script type="text/javascript">
function add_content(target_container, content) {
p = document.createElement('p');
p.appendChild(document.createTextNode(content));
container = document.getElementById(target_container);
container.appendChild(p);
}

function delayed_button_state() {
setTimeout(function() {
state_btn = document.getElementById('enabledDisabledBtn')
if (state_btn.hasAttribute("disabled")) {
state_btn.removeAttribute("disabled")
state_btn.value = "Enabled"
} else {
state_btn.setAttribute("disabled", "")
state_btn.value = "Disabled"
}
},900)
}
function delayed_title_change() {
setTimeout(function(){
document.title='Delayed';
},600);
}

function delayed_add_element() {
setTimeout(function(){
const newElem = document.createElement("input");
newElem.setAttribute("type", "button");
newElem.setAttribute("id", "added_btn");
newElem.setAttribute("value", "Added Button");
const container = document.getElementById("container");
document.body.insertBefore(newElem, container);
},1100);
}
</script>
</head>
<body>
<a href="javascript:return false;" onclick="document.title='Changed'; return false;">change title</a><br/>
<a href="javascript:return false;" onclick="delayed_title_change(); return false;">delayed change title</a><br/>
<a href="javascript:return false;" onclick="delayed_add_element(); return fales;">delayed add element</a><br/>
<a href="javascript:return false;" onclick="add_content('target', 'added content'); return false;">add content</a><br/>
<a id="unicode" href="javascript:return false;" onclick="document.title='äää'; return false;">title to ääää</a><br/>
<p>
<input type="radio" name="group" value="title"
onclick="document.title='Changed by Button';" />Change Title<br/>
<input type="radio" name="group" value="content"
onclick="add_content('button_target', 'added by button');"/>Add Content<br/>
</p>
<div id="target">
</div>
<div id="button_target">
</div>
<form name=myform>
<input type=button value="Change the title"
onClick="if(confirm('Really change the title?'))
document.title += ' Changed!';" >
</form>
<p>
<input type=button id=stateChangeBtn value="Change the button state"
onClick="delayed_button_state()" />
<input type=button id=enabledDisabledBtn value="Disabled"
disabled />
</p>
<p>
<div id="container"></div>
</p>
<p>
<form name=titleChanger>
<td>
<input type=text id=titleChangeTxt value="Enter Title here">
</td>
<td>
<input type=button id=titleChangeBtn value="Set Title"
onClick="document.title = document.getElementById('titleChangeTxt').value;" >
</td>
</form>
</p>
</body>
</html>

9 changes: 5 additions & 4 deletions atest/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@

from robot import rebot_cli
from robot import __version__ as robot_version
from selenium import __version__ as selenium_version
from robot.utils import is_truthy

try:
Expand Down Expand Up @@ -251,15 +252,15 @@ def process_output(browser):
return exit.code


def create_zip():
def create_zip(browser = None):
if os.path.exists(ZIP_DIR):
shutil.rmtree(ZIP_DIR)
os.mkdir(ZIP_DIR)
python_version = platform.python_version()
zip_name = f"rf-{robot_version}-python-{python_version}.zip"
zip_name = f"rf-{robot_version}-python-{python_version}-selenium-{selenium_version}-{browser}.zip"
zip_path = os.path.join(ZIP_DIR, zip_name)
print("Zip created in: %s" % zip_path)
zip_file = zipfile.ZipFile(zip_path, "w")
zip_file = zipfile.ZipFile(zip_path, "a")
for root, dirs, files in os.walk(RESULTS_DIR):
for file in files:
file_path = os.path.join(root, file)
Expand Down Expand Up @@ -326,5 +327,5 @@ def create_zip():
interpreter, browser, rf_options, selenium_grid, event_firing_webdriver
)
if args.zip:
create_zip()
create_zip(browser)
sys.exit(failures)
2 changes: 2 additions & 0 deletions src/SeleniumLibrary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
BrowserManagementKeywords,
CookieKeywords,
ElementKeywords,
ExpectedConditionKeywords,
FormElementKeywords,
FrameKeywords,
JavaScriptKeywords,
Expand Down Expand Up @@ -490,6 +491,7 @@ def __init__(
BrowserManagementKeywords(self),
CookieKeywords(self),
ElementKeywords(self),
ExpectedConditionKeywords(self),
FormElementKeywords(self),
FrameKeywords(self),
JavaScriptKeywords(self),
Expand Down
4 changes: 4 additions & 0 deletions src/SeleniumLibrary/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ class NoOpenBrowser(SeleniumLibraryException):

class PluginError(SeleniumLibraryException):
pass


class UnkownExpectedCondition(SeleniumLibraryException):
pass
1 change: 1 addition & 0 deletions src/SeleniumLibrary/keywords/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .browsermanagement import BrowserManagementKeywords # noqa
from .cookie import CookieKeywords # noqa
from .element import ElementKeywords # noqa
from .expectedconditions import ExpectedConditionKeywords # noqa
from .formelement import FormElementKeywords # noqa
from .frames import FrameKeywords # noqa
from .javascript import JavaScriptKeywords # noqa
Expand Down
Loading