Skip to content

Commit b218330

Browse files
authored
Input text and input password with grid should upload file to the node (robotframework#1417)
Fixes robotframework#1404
1 parent c6e4a6b commit b218330

File tree

14 files changed

+344
-104
lines changed

14 files changed

+344
-104
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
*** Settings ***
2+
Test Setup Go To Page "forms/named_submit_buttons.html"
3+
Resource ../resource.robot
4+
5+
*** Test Cases ***
6+
Choose File
7+
[Setup] Navigate To File Upload Form And Create Temp File To Upload
8+
Choose File file_to_upload ${CURDIR}${/}temp.txt
9+
# Not sure do you get "C:\fakepath\" prefix with all browsers but at least
10+
# Chrome and Firefox use it regardless the OS.
11+
Textfield Value Should Be file_to_upload C:\\fakepath\\temp.txt
12+
[Teardown] Remove File ${CURDIR}${/}temp.txt
13+
14+
Choose File And File Does Not Exist
15+
[Setup] Go To Page "forms/file_upload_form.html"
16+
Run Keyword And Expect Error
17+
... InvalidArgumentException: Message:*
18+
... Choose File file_to_upload ${CURDIR}${/}NotHere.txt
19+
20+
Choose File And Folder
21+
[Setup] Go To Page "forms/file_upload_form.html"
22+
Choose File file_to_upload ${CURDIR}
23+
Textfield Value Should Be file_to_upload C:\\fakepath\\keywords
24+
25+
Choose File With Grid
26+
[Documentation]
27+
... LOG 2:6 DEBUG GLOB: POST*/session/*/file*"file": "*
28+
[Tags] OnlyGrid
29+
[Setup] Touch ${CURDIR}${/}temp2.txt
30+
Choose File file_to_upload ${CURDIR}${/}temp2.txt
31+
Textfield Value Should Be file_to_upload C:\\fakepath\\temp2.txt
32+
[Teardown] Remove File ${CURDIR}${/}temp2.txt
33+
34+
Input Text Should Work Same Way When Not Using Grid
35+
[Documentation]
36+
... LOG 2:5 DEBUG GLOB: POST*/session/*/clear {"*
37+
... LOG 2:7 DEBUG Finished Request
38+
... LOG 2:8 DEBUG GLOB: POST*/session/*/value*"text": "*
39+
... LOG 2:10 DEBUG Finished Request
40+
... LOG 2:11 DEBUG NONE
41+
[Tags] NoGrid
42+
[Setup] Touch ${CURDIR}${/}temp.txt
43+
Input Text file_to_upload ${CURDIR}${/}temp.txt
44+
Textfield Value Should Be file_to_upload C:\\fakepath\\temp.txt
45+
[Teardown] Remove File ${CURDIR}${/}temp.txt
46+
47+
Input Text Should Work Same Way When Using Grid
48+
[Tags] OnlyGrid
49+
[Setup] Touch ${CURDIR}${/}temp3.txt
50+
Input Text file_to_upload ${CURDIR}${/}temp3.txt
51+
Textfield Value Should Be file_to_upload C:\\fakepath\\temp3.txt
52+
[Teardown] Remove File ${CURDIR}${/}temp3.txt
53+
54+
Running Keyword Is Saved Correctly
55+
${keyword_method} = get_running_keyword
56+
Should Be Equal get_running_keyword ${keyword_method}
57+
${keyword_method} = Get Running Keyword
58+
Should Be Equal get_running_keyword ${keyword_method}
59+
${keyword_method} = Get Running Keyword By Decorator
60+
Should Be Equal Get Running Keyword By Decorator ${keyword_method}
61+
${keyword_method} = get_running_keyword_by_decorator
62+
Should Be Equal Get Running Keyword By Decorator ${keyword_method}
63+
64+
Running Keyword Is Cleared Correctly
65+
${sl} = Get Library Instance SeleniumLibrary
66+
Should Be Equal ${sl._running_keyword} ${None}
67+
${keyword_method} = Get Running Keyword
68+
Should Be Equal get_running_keyword ${keyword_method}
69+
${sl} = Get Library Instance SeleniumLibrary
70+
Should Be Equal ${sl._running_keyword} ${None}
71+
72+
Running Keyword Is Cleared Correctly When Error
73+
${sl} = Get Library Instance SeleniumLibrary
74+
Should Be Equal ${sl._running_keyword} ${None}
75+
Run Keyword And Expect Error Page should have contained text 'Is not here' but did not.
76+
... Page Should Contain Is not here
77+
${sl} = Get Library Instance SeleniumLibrary
78+
Should Be Equal ${sl._running_keyword} ${None}
79+
80+
*** Keywords ***
81+
Navigate To File Upload Form And Create Temp File To Upload
82+
Cannot Be Executed in IE
83+
Go To Page "forms/file_upload_form.html"
84+
Touch ${CURDIR}${/}temp.txt

atest/acceptance/keywords/forms_and_buttons.robot

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
*** Settings ***
22
Test Setup Go To Page "forms/named_submit_buttons.html"
33
Resource ../resource.robot
4-
Library OperatingSystem
54

65
*** Variables ***
76
${FORM SUBMITTED} forms/submit.html
@@ -50,25 +49,6 @@ Click button created with <button> by tag content
5049
Click Button Sisään
5150
Verify Location Is "${FORM SUBMITTED}"
5251

53-
Choose File
54-
[Setup] Navigate To File Upload Form And Create Temp File To Upload
55-
Choose File file_to_upload ${CURDIR}${/}temp.txt
56-
# Not sure do you get "C:\fakepath\" prefix with all browsers but at least
57-
# Chrome and Firefox use it regardless the OS.
58-
Textfield Value Should Be file_to_upload C:\\fakepath\\temp.txt
59-
[Teardown] Remove File ${CURDIR}${/}temp.txt
60-
61-
Choose File And File Does Not Exist
62-
[Setup] Go To Page "forms/file_upload_form.html"
63-
Run Keyword And Expect Error
64-
... InvalidArgumentException: Message:*
65-
... Choose File file_to_upload ${CURDIR}${/}NotHere.txt
66-
67-
Choose File And Folder
68-
[Setup] Go To Page "forms/file_upload_form.html"
69-
Choose File file_to_upload ${CURDIR}
70-
Textfield Value Should Be file_to_upload C:\\fakepath\\keywords
71-
7252
Click Image With Submit Type Images
7353
[Setup] Go To Page "forms/form_with_image_submit.html"
7454
Click Image robot.bmp
@@ -78,8 +58,3 @@ Click Image With Submit Type Images
7858
Value Should Be Cancel
7959
${value} = Get Value textfield
8060
Should Be Equal ${value} Cancel
81-
82-
Navigate To File Upload Form And Create Temp File To Upload
83-
Cannot Be Executed in IE
84-
Go To Page "forms/file_upload_form.html"
85-
Touch ${CURDIR}${/}temp.txt

atest/acceptance/resource.robot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
*** Setting ***
2-
Library SeleniumLibrary run_on_failure=Nothing implicit_wait=0.2 seconds
2+
Library SeleniumLibrary run_on_failure=Nothing implicit_wait=0.2 seconds plugins=RunningKeyword.RunningKeyword
33
Library Collections
44
Library OperatingSystem
55
Library DateTime
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from SeleniumLibrary.base import LibraryComponent, keyword
2+
3+
4+
class RunningKeyword(LibraryComponent):
5+
6+
@keyword
7+
def get_running_keyword(self):
8+
return self.ctx._running_keyword
9+
10+
@keyword(name='Get Running Keyword By Decorator')
11+
def get_running_keyword_2(self):
12+
return self.get_running_keyword()

atest/run.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
More details about the Selenium grid can be found from:
1515
https://github.com/SeleniumHQ/selenium/wiki/Grid2
1616
17+
When Selenium Grid is used, it is possible to include and exclude test.
18+
Generally speaking almost all test should work when Selenium Grid is used,
19+
but there few valid exceptions. If test uses `robotstatuschecker` tool
20+
to verify logging of the keyword, in some cases Selenium Grid adds
21+
some extra logging and causes test to fail. In this case, these test
22+
should be tagged with `NoGrid` tag to exclude the test when Selenium Grid
23+
is being used. Also there might be need write test that are only run
24+
when Selenium Grid is used. Then in this case, test should be tagged with
25+
`OnlyGrid` tag to include them only when Selenium Grid is used.
26+
1727
It is possible to pass Robot Framework command line arguments to the test
1828
execution as last arguments to the `run_tests.py` command. It is
1929
recommended to use arguments to select required suite or test for the
@@ -77,14 +87,6 @@
7787
]
7888

7989

80-
def unit_tests():
81-
print('Running unit tests')
82-
failures = run_unit_tests()
83-
if failures:
84-
print('\nUnit tests failed! Not running acceptance tests.')
85-
sys.exit(failures)
86-
87-
8890
def acceptance_tests(interpreter, browser, rf_options=None, grid=None):
8991
if os.path.exists(RESULTS_DIR):
9092
shutil.rmtree(RESULTS_DIR)
@@ -109,15 +111,15 @@ def start_grid():
109111
node_file = tempfile.TemporaryFile()
110112
hub_file = tempfile.TemporaryFile()
111113
selenium_jar = None
112-
for file in os.listdir():
114+
for file in os.listdir('.'):
113115
if file.startswith('selenium-server-standalone'):
114116
selenium_jar = file
115117
break
116118
if not selenium_jar:
117119
raise ValueError('Selenium server jar not found: %s' % selenium_jar)
118120
hub = subprocess.Popen(['java', '-jar', selenium_jar, '-role', 'hub', '-host', 'localhost'],
119121
stderr=subprocess.STDOUT, stdout=hub_file)
120-
time.sleep(1) # It takes about seconds to start the hub.
122+
time.sleep(2) # It takes about two seconds to start the hub.
121123
ready = _grid_status(False, 'hub')
122124
if not ready:
123125
hub.kill()
@@ -173,6 +175,8 @@ def execute_tests(interpreter, browser, rf_options, grid):
173175
if grid:
174176
command += ['--variable', 'REMOTE_URL:http://localhost:4444/wd/hub',
175177
'--exclude', 'NoGrid']
178+
else:
179+
command += ['--exclude', 'OnlyGrid']
176180
command += options + [ACCEPTANCE_TEST_DIR]
177181
log_start(command)
178182
syslog = os.path.join(RESULTS_DIR, 'syslog.txt')

src/SeleniumLibrary/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,13 +400,17 @@ def __init__(self, timeout=5.0, implicit_wait=0.0,
400400
self.event_firing_webdriver = self._parse_listener(event_firing_webdriver)
401401
else:
402402
self.event_firing_webdriver = None
403+
self._running_keyword = None
403404

404405
def run_keyword(self, name, args, kwargs):
406+
self._running_keyword = name
405407
try:
406408
return DynamicCore.run_keyword(self, name, args, kwargs)
407409
except Exception:
408410
self.failure_occurred()
409411
raise
412+
finally:
413+
self._running_keyword = None
410414

411415
def get_keyword_tags(self, name):
412416
tags = list(DynamicCore.get_keyword_tags(self, name))

src/SeleniumLibrary/keywords/formelement.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,19 @@ def input_text(self, locator, text, clear=True):
251251
is not cleared from the element. Use `Input Password` if you
252252
do not want the given ``text`` to be logged.
253253
254+
If [https://github.com/SeleniumHQ/selenium/wiki/Grid2|Selenium Grid]
255+
is used and the ``text`` argument points to a file in the file system,
256+
then this keyword prevents the Selenium to transfer the file to the
257+
Selenium Grid hub. Instead this keyword will send the ``text`` string
258+
as is to the element. If file should be transferred to the hub and
259+
upload should be performed, please use `Choose File` keyword.
260+
254261
See the `Locating elements` section for details about the locator
255262
syntax. See the `Boolean arguments` section how Boolean values are
256263
handled.
257264
258-
The `clear` argument is new in SeleniumLibrary 4.0
265+
Disabling the file upload the Selenium Grid node and the `clear`
266+
argument are new in SeleniumLibrary 4.0
259267
"""
260268
self.info("Typing text '%s' into text field '%s'." % (text, locator))
261269
self._input_text_into_text_field(locator, text, clear)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright 2008-2011 Nokia Networks
2+
# Copyright 2011-2016 Ryan Tomac, Ed Manlove and contributors
3+
# Copyright 2016- Robot Framework Foundation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from .webdrivertools import WebDriverCreator
18+
from .webdrivertools import WebDriverCache
19+
from .webdrivertools import SeleniumOptions
20+
from .sl_file_detector import SelLibLocalFileDetector
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright 2008-2011 Nokia Networks
2+
# Copyright 2011-2016 Ryan Tomac, Ed Manlove and contributors
3+
# Copyright 2016- Robot Framework Foundation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
from robot.libraries.BuiltIn import BuiltIn
17+
from selenium.webdriver.remote.file_detector import FileDetector, LocalFileDetector
18+
19+
import SeleniumLibrary
20+
21+
22+
class SelLibLocalFileDetector(FileDetector):
23+
24+
def __init__(self):
25+
self.selenium_file_detector = LocalFileDetector()
26+
27+
def is_local_file(self, *keys):
28+
if self.choose_file():
29+
return self.selenium_file_detector.is_local_file(*keys)
30+
return None
31+
32+
def choose_file(self):
33+
try:
34+
sl = self._get_sl()
35+
except Exception:
36+
sl = None
37+
if sl and sl._running_keyword == 'choose_file':
38+
return True
39+
return False
40+
41+
def _get_sl(self):
42+
libraries = BuiltIn().get_library_instance(all=True)
43+
for library in libraries:
44+
if isinstance(libraries[library], SeleniumLibrary.SeleniumLibrary):
45+
return libraries[library]

src/SeleniumLibrary/keywords/webdrivertools.py renamed to src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from selenium.webdriver import FirefoxProfile
2828

2929
from SeleniumLibrary.utils import is_falsy, is_truthy, is_noney, is_string
30+
from SeleniumLibrary.keywords.webdrivertools.sl_file_detector import SelLibLocalFileDetector
3031

3132

3233
class WebDriverCreator(object):
@@ -251,10 +252,16 @@ def create_iphone(self, desired_capabilities, remote_url, options=None, service_
251252
def _remote(self, desired_capabilities, remote_url,
252253
profile_dir=None, options=None):
253254
remote_url = str(remote_url)
255+
file_detector = self._get_sl_file_detector()
254256
return webdriver.Remote(command_executor=remote_url,
255257
browser_profile=profile_dir, options=options,
258+
file_detector=file_detector,
256259
**desired_capabilities)
257260

261+
def _get_sl_file_detector(self):
262+
# To ease unit testing.
263+
return SelLibLocalFileDetector()
264+
258265
def _get_log_path(self, log_file):
259266
if is_noney(log_file):
260267
return None

0 commit comments

Comments
 (0)