-
Notifications
You must be signed in to change notification settings - Fork 763
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
emanlove
merged 24 commits into
robotframework:master
from
emanlove:add-expected-conditions-1827
Apr 14, 2024
Merged
Changes from 19 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 583c9e6
Added dynamic and delayed title change as initial test framework for
emanlove fc60e23
Merge branch 'master' into add-expected-conditions-1827
emanlove 2b10abf
Initial (working) prototype of wait for.. keyword
emanlove eb49c98
Bumped number of library keywords by one
emanlove 129e9b0
Moved previous expected condition tests out of current test suite
emanlove 36e7da3
Adding another sample tests and modifying keyword behavior
emanlove 48376f7
Added sample test case where an expected timeout would occur
emanlove 3083459
added timeout argument to keyword wait_for_expected_condition
yuriverweij 754e793
Merge pull request #3 from yuriverweij/feature/add_expected_condition…
emanlove 98d8f89
Some intial parsing and validation for parsing condition argument
emanlove 7ad5296
Basic working keyword for wait
emanlove b022031
Added test case for capitals within expected condition name
emanlove d23700e
Added example test where expected condition expected "locator" tuple
emanlove 7bdca3c
Added keyword documentation for new `Wait For Expected Condition` key…
emanlove bd05dfd
Merge branch 'master' into add-expected-conditions-1827
emanlove fd751bb
Fix Firefox unit tests
emanlove 204ceda
Reduced the timeout on the expected timeout within expected conditions
emanlove e1a4f4c
Expanded selenium versions upto 4.19.0
emanlove f17f8f0
Fix acceptance tests
emanlove de1a4fb
Append results to zip file
emanlove 8db00db
Added selenium version and browser name to archive
emanlove a0e241d
Upload only failed artifacts
emanlove cc41bc1
Updated some expected log messages in chrome tests
emanlove File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
emanlove marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Copyright 2016- Robot Framework Foundation | ||
yuriverweij marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
import string | ||
from typing import Optional | ||
|
||
from SeleniumLibrary.base import LibraryComponent, keyword | ||
from SeleniumLibrary.errors import UnkownExpectedCondition | ||
from selenium.webdriver.support.wait import WebDriverWait | ||
from selenium.webdriver.support import expected_conditions as EC | ||
|
||
class ExpectedConditionKeywords(LibraryComponent): | ||
@keyword | ||
def wait_for_expected_condition(self, condition: string, *args, timeout: Optional[float]=10): | ||
"""Waits until ``condition`` is true or ``timeout`` expires. | ||
|
||
The condition must be one of selenium's expected condition which | ||
can be found within the selenium | ||
[https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html#module-selenium.webdriver.support.expected_conditions Python API] | ||
documentation. The expected condition can written as snake_case | ||
(ex title_is) or it can be space delimited (ex Title Is). Some | ||
conditions require additional arguments or ``args`` which should | ||
be passed along after the expected condition. | ||
|
||
Fails if the timeout expires before the condition becomes true. | ||
The default value is 10 seconds. | ||
|
||
Examples: | ||
| `Wait For Expected Condition` | alert_is_present | | ||
| `Wait For Expected Condition` | Title Is | New Title | | ||
|
||
If the expected condition expects a locator then one can pass | ||
as arguments a tuple containing the selenium locator strategies | ||
and the locator. | ||
|
||
Example of expected condition expecting locator: | ||
| ${byElem}= | Evaluate ("id","added_btn") | ||
| `Wait For Expected Condition` | Presence Of Element Located | ${byElem} | ||
""" | ||
|
||
condition = self._parse_condition(condition) | ||
wait = WebDriverWait(self.driver, timeout, 0.1) | ||
try: | ||
c = getattr(EC, condition) | ||
except: | ||
# ToDo: provide hints as to what is avaialbel or find closet match | ||
raise UnkownExpectedCondition(f"{condition} is an unknown expected condition") | ||
result = wait.until(c(*args), message="Expected Condition not met within set timeout of " + str(timeout)) | ||
return result | ||
|
||
def _parse_condition(self, condition: string): | ||
parsed = condition.replace(' ','_').lower() | ||
return parsed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import unittest | ||
|
||
from SeleniumLibrary.keywords import ExpectedConditionKeywords | ||
|
||
# Test cases | ||
|
||
# Parsing expected condition | ||
# expect to match .. | ||
# element_to_be_clickable | ||
# Element To Be Clickable | ||
# eLEment TO be ClIcKable | ||
# expect to not match .. | ||
# element__to_be_clickable | ||
# elementtobeclickable | ||
# element_to_be_clickble | ||
# Ice Cream Cone Has Three Scopes | ||
|
||
# what about ..? | ||
# ${ec_var} | ||
# Element\ To\ Be\ Clickable | ||
# Element${SPACE}To${SPACE}Be${SPACE}Clickable | ||
|
||
class ExpectedConditionKeywords(unittest.TestCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
cls.ec_keywords = ExpectedConditionKeywords(None) | ||
|
||
def WorkInProgresstest_parse_condition(self): | ||
results = [] | ||
results.append(self.ec_keywords._parse_condition("Element To Be Clickable")) | ||
results.append(self.ec_keywords._parse_condition("eLEment TO be ClIcKable")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,8 +56,21 @@ def test_single_method(self): | |
|
||
def _parse_result(self, result): | ||
to_str = "" | ||
if "key1" in result.default_preferences: | ||
to_str = f"{to_str} key1 {result.default_preferences['key1']}" | ||
if "key2" in result.default_preferences: | ||
to_str = f"{to_str} key2 {result.default_preferences['key2']}" | ||
result_attr = self._get_preferences_attribute(result) | ||
if "key1" in result_attr: | ||
to_str = f"{to_str} key1 {result_attr['key1']}" | ||
if "key2" in result_attr: | ||
to_str = f"{to_str} key2 {result_attr['key2']}" | ||
self.results.append(to_str) | ||
|
||
def _get_preferences_attribute(self, result): | ||
# -- temporary fix to transition selenium to v4.17.2 from v4.16.0 and prior | ||
# from inspect import signature | ||
# sig = signature(result) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These comments can be removed I assume? |
||
if hasattr(result,'default_preferences'): | ||
return result.default_preferences | ||
elif hasattr(result,'_desired_preferences'): | ||
return result._desired_preferences | ||
else: | ||
return None | ||
# -- |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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.