Skip to content

Recorder updates: Improve "Choose File" processing and more #995

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

Merged
merged 6 commits into from
Oct 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ lunr==0.6.0;python_version>="3.6"
nltk==3.6.4;python_version>="3.6"
watchdog==2.1.6;python_version>="3.6"
mkdocs==1.2.2;python_version>="3.6"
mkdocs-material==7.3.0;python_version>="3.6"
mkdocs-material==7.3.1;python_version>="3.6"
mkdocs-exclude-search==0.5.2;python_version>="3.6"
mkdocs-simple-hooks==0.1.3
mkdocs-material-extensions==1.0.3;python_version>="3.6"
Expand Down
2 changes: 1 addition & 1 deletion examples/ReadMe.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[<img src="https://seleniumbase.io/cdn/img/sb_logo_10t.png" title="SeleniumBase" width="220">](https://github.com/seleniumbase/SeleniumBase/)
[<img src="https://seleniumbase.io/cdn/img/sb_logo_10t.png" title="SeleniumBase" width="240">](https://github.com/seleniumbase/SeleniumBase/)

<h2><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> Running Example Tests:</h2>

Expand Down
26 changes: 26 additions & 0 deletions examples/test_show_file_choosers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
self.show_file_choosers() is used to show hidden file-upload fields.
Verify that one can choose a file after the hidden input is visible.
"""
import os
from seleniumbase import BaseCase


class FileUpload(BaseCase):
def test_show_file_choosers(self):
self.open("https://imgbb.com/upload")
choose_file_selector = 'input[type="file"]'
uploaded_image = "#anywhere-upload-queue li.queue-item"
self.assert_element_not_visible(choose_file_selector)
self.show_file_choosers()
self.assert_element(choose_file_selector)
self.assert_attribute(choose_file_selector, "value", "")
self.assert_element_not_visible(uploaded_image)
dir_name = os.path.dirname(os.path.abspath(__file__))
my_file = "screenshot.png"
file_path = os.path.join(dir_name, "example_logs/%s" % my_file)
self.choose_file(choose_file_selector, file_path)
seen_path = "%s\\%s" % ("C:\\fakepath", my_file)
self.assert_attribute(choose_file_selector, "value", seen_path)
self.demo_mode = True
self.assert_element(uploaded_image)
2 changes: 1 addition & 1 deletion help_docs/customizing_test_runs.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[<img src="https://seleniumbase.io/cdn/img/sb_logo_10t.png" title="SeleniumBase" width="220">](https://github.com/seleniumbase/SeleniumBase/)
[<img src="https://seleniumbase.io/cdn/img/sb_logo_10t.png" title="SeleniumBase" width="240">](https://github.com/seleniumbase/SeleniumBase/)

## pytest options for SeleniumBase

Expand Down
10 changes: 7 additions & 3 deletions help_docs/recorder_mode.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[<img src="https://seleniumbase.io/cdn/img/sb_logo_10t.png" title="SeleniumBase" width="220">](https://github.com/seleniumbase/SeleniumBase/)
[<img src="https://seleniumbase.io/cdn/img/sb_logo_10t.png" title="SeleniumBase" width="240">](https://github.com/seleniumbase/SeleniumBase/)

<h2><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> Recorder Mode</h2>

Expand All @@ -12,12 +12,14 @@
pytest TEST_NAME.py --recorder -s
```

🔴 To add your own actions inside the test, you'll need to create a breakpoint inside your test to activate Debug Mode:
🔴 To add manual actions, you'll need to create a breakpoint inside your test to activate "Debug Mode" while in "Recorder Mode": (For reference, "Debug Mode" is also known as the "ipdb debugger".)

```python
import ipdb; ipdb.set_trace()
```

🔴 The Recorder will capture browser actions on URLs that begin with ``https:``, ``http:``, and ``file:``. (The Recorder won't work on ``data:`` URLS.)

🔴 You can also activate Debug Mode at the start of your test by adding ``--trace`` as a ``pytest`` command-line option:

```bash
Expand Down Expand Up @@ -58,7 +60,7 @@ class RecorderTest(BaseCase):

<p>🔴 (Note that <b>same domain/origin</b> is not the same as <b>same URL</b>. Example: <code>https://xkcd.com/353/</code> and <code>https://xkcd.com/1537/</code> are two different URLs with the <b>same domain/origin</b>. That means that both URLs will share the same <code>sessionStorage</code> data, and that any changes to <code>sessionStorage</code> from one URL will carry on to the <code>sessionStorage</code> of a different URL when the domain/origin is the same. If you want to find out a website's origin during a test, just call: <code>self.get_origin()</code>, which returns the value of <code>window.location.origin</code> from the browser's console.)</p>

<p>🔴 The launch of Recorder Mode has brought a new SeleniumBase method along with it: <code>self.open_if_not_url(URL)</code>. This method will open the URL given if the browser is not currently on that page. This is used as a method in recorded scripts when SeleniumBase detects that a click action has already brought the test to the given page. This method not only prevents an extra page load if not needed, but it also lets people know the current page of the browser at that point in the test.</p>
<p>🔴 The launch of Recorder Mode has brought a new SeleniumBase method along with it: <code>self.open_if_not_url(URL)</code>. This method will open the URL given if the browser is not currently on that page. This is used as a method in recorded scripts when SeleniumBase detects that a click action has already brought the test to the given page. This method not only prevents an extra page load if not needed, but it also lets people know the current page of the browser during that part of the test.</p>

<p>🔴 SeleniumBase <code>1.66.1</code> adds the ability to record changes to <i>"Choose File"</i> <code>input</code> fields. Sometimes the <i>"Choose File"</i> input field is hidden on websites, so <code>self.show_file_choosers()</code> was added to get around this edge case. Version <code>1.66.1</code> also adds <code>self.set_content_to_frame(frame)</code>, which lets you record actions inside of iframes.</p>

Expand All @@ -72,6 +74,8 @@ class RecorderTest(BaseCase):

<p>🔴 SeleniumBase <code>1.66.6</code> adds more selector options and improves the algorithm for converting recorded actions into SeleniumBase code.</p>

<p>🔴 SeleniumBase <code>1.66.7</code> improves Recorder Mode post-processing and automatically adds <code>self.show_file_choosers()</code> if file-upload fields are hidden when calling <code>self.choose_file(selector, file_path)</code>.</p>

--------

<div>To learn more about SeleniumBase, check out the Docs Site:</div>
Expand Down
12 changes: 6 additions & 6 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ theme:
language: en
include_homepage_in_sidebar: true
sticky_navigation: true
# collapse_navigation: false
collapse_navigation: true
# titles_only: false
include_search_page: false
search_index_only: true
Expand All @@ -43,9 +43,10 @@ theme:
- toc.integrate
- navigation.indexes
# - navigation.sections
# - navigation.expand
- navigation.expand
# - navigation.tabs
# - navigation.instant
- navigation.tracking
- navigation.instant
palette:
scheme: default
primary: blue
Expand All @@ -59,7 +60,6 @@ theme:
plugins:
- search:
separator: '[\s]+'
prebuild_index: false
lang: en
- exclude-search:
exclude:
Expand Down Expand Up @@ -107,9 +107,9 @@ nav:
- MasterQA: examples/master_qa/ReadMe.md
- Jenkins on Azure: integrations/azure/jenkins/ReadMe.md
- Jenkins on Google Cloud: integrations/google_cloud/ReadMe.md
- Katalon Recorder: integrations/katalon/ReadMe.md
- Old Recorder / Export: seleniumbase/utilities/selenium_ide/ReadMe.md
- NodeJS Test Runner: https://github.com/seleniumbase/SeleniumBase/tree/master/integrations/node_js
- Katalon Recorder Export: integrations/katalon/ReadMe.md
- Selenium IDE Export: seleniumbase/utilities/selenium_ide/ReadMe.md
- Help Docs:
- Table of Contents: help_docs/ReadMe.md
- JS Package Manager: help_docs/js_package_manager.md
Expand Down
6 changes: 4 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ msedge-selenium-tools==3.141.3
more-itertools==5.0.0;python_version<"3.5"
more-itertools==8.10.0;python_version>="3.5"
cssselect==1.1.0
filelock==3.2.0
filelock==3.2.1;python_version<"3.6"
filelock==3.3.0;python_version>="3.6"
fasteners==0.16;python_version<"3.5"
fasteners==0.16.3;python_version>="3.5"
execnet==1.9.0
Expand Down Expand Up @@ -108,7 +109,8 @@ pdfminer.six==20201018;python_version>="3.5"
# --- Testing Requirements --- #
# ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.)

coverage==5.5
coverage==5.5;python_version<"3.6"
coverage==6.0;python_version>="3.6"
pytest-cov==2.12.1
flake8==3.7.9;python_version<"3.5"
flake8==3.9.2;python_version>="3.5"
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "1.66.6"
__version__ = "1.66.7"
6 changes: 5 additions & 1 deletion seleniumbase/console_scripts/ReadMe.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[<img src="https://seleniumbase.io/cdn/img/super_logo_sb.png" title="SeleniumBase" width="290">](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md)
[<img src="https://seleniumbase.io/cdn/img/sb_logo_10t.png" title="SeleniumBase" width="240">](https://github.com/seleniumbase/SeleniumBase/)

## Console Scripts

Expand Down Expand Up @@ -345,3 +345,7 @@ You can start, restart, or stop the Grid Hub server.
Controls the Selenium Grid node, which serves as a
worker machine for your Selenium Grid Hub server.
You can start, restart, or stop the Grid node.

--------

[<img src="https://seleniumbase.io/cdn/img/super_logo_sb.png" title="SeleniumBase" width="290">](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md)
40 changes: 37 additions & 3 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -3273,7 +3273,7 @@ def __process_recorded_actions(self):
and srt_actions[n-1][0] == "chfil"
):
srt_actions[n-1][0] = "_skip"
srt_actions[n][2] = srt_actions[n-1][1]
srt_actions[n][2] = srt_actions[n-1][1][1]
origins = []
for n in range(len(srt_actions)):
if (
Expand All @@ -3297,6 +3297,18 @@ def __process_recorded_actions(self):
srt_actions[n][0] = "h_clk"
srt_actions[n][1] = srt_actions[n-1][1][0]
srt_actions[n][2] = srt_actions[n-1][1][1]
for n in range(len(srt_actions)):
if srt_actions[n][0] == "chfil" and srt_actions[n][2] in origins:
srt_actions[n][0] = "cho_f"
srt_actions[n][2] = srt_actions[n][1][1]
srt_actions[n][1] = srt_actions[n][1][0]
for n in range(len(srt_actions)):
if (
srt_actions[n][0] == "sh_fc"
and n > 0
and srt_actions[n-1][0] == "sh_fc"
):
srt_actions[n-1][0] = "_skip"
ext_actions = []
ext_actions.append("js_cl")
ext_actions.append("as_el")
Expand All @@ -3312,6 +3324,7 @@ def __process_recorded_actions(self):
ext_actions.append("sw_dc")
ext_actions.append("s_c_f")
ext_actions.append("s_c_d")
ext_actions.append("sh_fc")
for n in range(len(srt_actions)):
if srt_actions[n][0] in ext_actions:
origin = srt_actions[n][2]
Expand Down Expand Up @@ -3521,6 +3534,9 @@ def __process_recorded_actions(self):
else:
sb_actions.append("self.%s('%s')" % (
method, action[1][0]))
elif action[0] == "sh_fc":
cb_method = "show_file_choosers"
sb_actions.append('self.%s()' % cb_method)
elif action[0] == "c_box":
cb_method = "check_if_unchecked"
if action[2] == "no":
Expand All @@ -3546,7 +3562,6 @@ def __process_recorded_actions(self):
if len(sb_actions) > 0:
for action in sb_actions:
data.append(" " + action)
print(" " + action)
else:
data.append(" pass")
data.append("")
Expand Down Expand Up @@ -4120,6 +4135,15 @@ def show_file_choosers(self):
self.execute_script(script)
except Exception:
pass
if self.recorder_mode:
url = self.get_current_url()
if url and len(url) > 0:
if ("http:") in url or ("https:") in url or ("file:") in url:
if self.get_session_storage_item("pause_recorder") == "no":
time_stamp = self.execute_script("return Date.now();")
origin = self.get_origin()
action = ["sh_fc", "", origin, time_stamp]
self.__extra_actions.append(action)

def get_domain_url(self, url):
self.__check_scope()
Expand Down Expand Up @@ -4440,6 +4464,15 @@ def choose_file(
self.__demo_mode_highlight_if_active(selector, by)
if not self.demo_mode and not self.slow_mode:
self.__scroll_to_element(element, selector, by)
else:
choose_file_selector = 'input[type="file"]'
if self.is_element_present(choose_file_selector):
if not self.is_element_visible(choose_file_selector):
self.show_file_choosers()
if self.is_element_visible(selector, by=by):
self.__demo_mode_highlight_if_active(selector, by)
if not self.demo_mode and not self.slow_mode:
self.__scroll_to_element(element, selector, by)
pre_action_url = self.driver.current_url
if self.recorder_mode:
url = self.get_current_url()
Expand All @@ -4448,7 +4481,8 @@ def choose_file(
if self.get_session_storage_item("pause_recorder") == "no":
time_stamp = self.execute_script("return Date.now();")
origin = self.get_origin()
action = ["chfil", file_path, origin, time_stamp]
sele_file_path = [selector, file_path]
action = ["chfil", sele_file_path, origin, time_stamp]
self.__extra_actions.append(action)
if type(abs_path) is int or type(abs_path) is float:
abs_path = str(abs_path)
Expand Down
6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@
'more-itertools==5.0.0;python_version<"3.5"',
'more-itertools==8.10.0;python_version>="3.5"',
"cssselect==1.1.0",
"filelock==3.2.0",
'filelock==3.2.1;python_version<"3.6"',
'filelock==3.3.0;python_version>="3.6"',
'fasteners==0.16;python_version<"3.5"',
'fasteners==0.16.3;python_version>="3.5"',
"execnet==1.9.0",
Expand Down Expand Up @@ -224,7 +225,8 @@
extras_require={
# pip install -e .[coverage]
"coverage": [
"coverage==5.5",
'coverage==5.5;python_version<"3.6"',
'coverage==6.0;python_version>="3.6"',
"pytest-cov==2.12.1",
],
# pip install -e .[flake]
Expand Down