This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Repository files navigation

PyWebRunner

A supercharged Python wrapper for Selenium

Build StatusPyPI version

Documentation

Full documentation can be located here: https://intuitivewebsolutions.github.io/PyWebRunner

Uses

You could use WebRunner to scrape a website, automate web tasks, or anything else you could imagine. It is easy to initialize and use. It's also compatible with BrowserStack using the command_executor and remote_capabilities examples on that page.

(Please note that you will need a subscription, username, and API key to make it work.)

Installing

pip install PyWebRunner

Basic Examples

# Import WebRunner if you aren't going to assert anything.# WebTester is a sub-class of WebRunnerfromPyWebRunnerimportWebRunner# Running headless FireFox is the default.wr=WebRunner() # Defaults to xvfb=True, driver=FireFox# If xvfb is not installed, it will be bypassed automatically.# Start the browser instance.wr.start()
# Navigate to a page.wr.go('https://www.google.com/')
# Fill in a text field.wr.set_value('#lst-ib', 'PyWebRunner')
wr.send_key('#lst-ib', 'ENTER')
# Click the link based on a (gross) CSS selector.wr.click('#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a')
# Wait for the page to load.wr.wait_for_presence('div.document')
# Are we there yet?wr.is_text_on_page('A helpful wrapper for Selenium') # True# Take a screenshot!wr.screenshot('/tmp/screenshot1.png')
# Stop the browser instance.wr.stop()

YAML Scripts

PyWebRunner supports running YAML scripts and includes the webrunner command.

Let's say we made a YAML script for the above example and we called it script.yml

- go: https://www.google.com/
- set_value:
- "#lst-ib"
- PyWebRunner
- send_key:
- "#lst-ib"
- "ENTER"
- click: "#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a"
- wait_for_presence: div.document
- assert_text_on_page: A helpful wrapper for Selenium
- screenshot: /tmp/screenshot1.png

We can run it like so:

webrunner script.yml

...and it will behave identically to the Python-based example above.

Advanced YAML Features

YAML supports the use of the fake-factory library (if it is installed) as well as evals and python function calls. Though the YAML is not intended as a complete replacement for Python scripts, this does enable some pretty flexible scripts to run.

You might be asking yourself, what's the purpose of parsing YAML like this if you can just write Python and have access to all these things by default?

The answer is that I wanted a way to write purely data-driven, front-end tests. The benefits could be summarized as:

  • It makes it possible to write a single loader script that grabs all the YAML files in a folder and runs them one at a time (or in parallel).
  • The tests themselves could be served up from a single, remote web-server.
  • Tests could be written by non-programmers with minimal training and effort.
  • GUI tools can easily be created to write tests/automated tasks without needing any programming knowledge.

Consider the following example of registering an account:

# Go to the page.
- go: https://somesite/page.html# Click the register link.
- click: "#register"# Wait for the registration form.
- wait_for_presence: "#email"# Set the email field to a freshly-generated fake email address:
- set_value:
- "#email"
- (( fake-email ))# Create a fake password string.
- set_value:
- "#password"
- (( fake-password ))# Reference the fake password we already generated.
- set_value:
- "#password-verify"
- (( vars|password ))# Click the register button.
- click: "#register"# Wait for the redirect and the confirmation div.
- wait_for_presence: "#confirmation-div"# Assert that the registration was successful.
- assert_text_in_page: Your registration was successful!

FakeData

This example makes use of the fake-factory/faker library to generate a fake email address as well as a password. Any data that is created using the (( )) syntax is automatically assigned to a variable list for reference later.

InstallingFaker

To install prior to September 15th, 2016: pip install fake-factory

To install after September 15th, 2016: pip install faker

fake-factory / faker need only be installed for the YAML to support (( fake-* )) tags.

* can be any of the methods on the faker class. This list is extensive and is under active development. For more information, go to the fake-factory website:

https://faker.readthedocs.io/en/latest/

((special))

Items enclosed in double parentheses (( )) will be parsed in this special way upon the execution of the script.

Examples

- include: basic_setup.yml
- import: random.randint
- set_value:
- "#someinput"
- (( randint|1,2 ))

The previous example will import random.randint and use it to generate a value of either 1 or 2 and insert it into the #someinput element.


- import: random.choice
- set_value:
- "#someinput"
- (( choice|['frog','cat','bird'] ))

As you can see, the choice function doesn't take positional arguments like the randint function does. It needs a list of options.


What happens when we run a function more than once and we need to reference the second or third output?

- import: random.choice
- set_value:
- "#someinput-a"
- (( choice|['frog','cat','bird'] )) # bird
- set_value:
- "#someinput-b"
- (( choice|['frog','cat','bird'] )) # cat
- set_value:
- "#someinput-c"
- (( choice|['frog','cat','bird'] )) # cat (again)
- assert_value_of_element:
- "#someinput-a"
- (( vars|choice )) # The "choice" array. Defaults to index 0.
- assert_value_of_element:
- "#someinput-b"
- (( vars|choice|1 )) # The "choice" array index 1.
- assert_value_of_element:
- "#someinput-c"
- (( vars|choice|2 )) # The "choice" array index 2.

OK, how about values on the page itself? Is there any way to obtain and reference them from inside a YAML WebRunner script?

- value_of: "#my-input-element"# Set the value.
- set_value:
- "#someinput-a"
- (( vars|value_of|0 )) # Use the value at index 0.
- text_of: "#my-div-element"# Set the text to a variable.
- set_value:
- "#someinput-b"
- (( vars|text_of|0 )) # Use the text value at index 0.

BrowserStack example:

This library also has first-class support for BrowserStack. Using it is not much different than the examples above.

fromPyWebRunnerimportWebRunner# Change any of these values to valid ones.desired= {
'browser': 'Edge',
'browser_version': '13.0',
'os': 'Windows',
'os_version': '10',
'resolution': '1440x900'
}
# Make sure you plug in your own USERNAME and API_KEY values here.wr=WebRunner(desired_capabilities=desired,
command_executor='http://USERNAME:API_KEY@hub.browserstack.com:80/wd/hub',
driver='Remote')
wr.start()
wr.go('http://google.com')
# ... Etc.

Testing

WebTester

WebTester inherits WebRunner so it has all the same methods that WebRunner has but it adds some additional methods that are useful for testing.

Testing Asserts

  • assert_alert_not_present
  • assert_alert_present
  • assert_checked
  • assert_element_contains_text
  • assert_element_has_class
  • assert_element_not_has_class
  • assert_exists
  • assert_found
  • assert_not_checked
  • assert_not_found
  • assert_not_visible
  • assert_text_in_element
  • assert_text_in_elements
  • assert_text_in_page
  • assert_text_not_in_page
  • assert_url
  • assert_value_of_element
  • assert_visible

About

A helpful wrapper for Selenium

Resources

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Repository files navigation

PyWebRunner

A supercharged Python wrapper for Selenium

Build StatusPyPI version

Documentation

Full documentation can be located here: https://intuitivewebsolutions.github.io/PyWebRunner

Uses

You could use WebRunner to scrape a website, automate web tasks, or anything else you could imagine. It is easy to initialize and use. It's also compatible with BrowserStack using the command_executor and remote_capabilities examples on that page.

(Please note that you will need a subscription, username, and API key to make it work.)

Installing

pip install PyWebRunner

Basic Examples

# Import WebRunner if you aren't going to assert anything.# WebTester is a sub-class of WebRunnerfromPyWebRunnerimportWebRunner# Running headless FireFox is the default.wr=WebRunner() # Defaults to xvfb=True, driver=FireFox# If xvfb is not installed, it will be bypassed automatically.# Start the browser instance.wr.start()
# Navigate to a page.wr.go('https://www.google.com/')
# Fill in a text field.wr.set_value('#lst-ib', 'PyWebRunner')
wr.send_key('#lst-ib', 'ENTER')
# Click the link based on a (gross) CSS selector.wr.click('#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a')
# Wait for the page to load.wr.wait_for_presence('div.document')
# Are we there yet?wr.is_text_on_page('A helpful wrapper for Selenium') # True# Take a screenshot!wr.screenshot('/tmp/screenshot1.png')
# Stop the browser instance.wr.stop()

YAML Scripts

PyWebRunner supports running YAML scripts and includes the webrunner command.

Let's say we made a YAML script for the above example and we called it script.yml

- go: https://www.google.com/
- set_value:
- "#lst-ib"
- PyWebRunner
- send_key:
- "#lst-ib"
- "ENTER"
- click: "#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a"
- wait_for_presence: div.document
- assert_text_on_page: A helpful wrapper for Selenium
- screenshot: /tmp/screenshot1.png

We can run it like so:

webrunner script.yml

...and it will behave identically to the Python-based example above.

Advanced YAML Features

YAML supports the use of the fake-factory library (if it is installed) as well as evals and python function calls. Though the YAML is not intended as a complete replacement for Python scripts, this does enable some pretty flexible scripts to run.

You might be asking yourself, what's the purpose of parsing YAML like this if you can just write Python and have access to all these things by default?

The answer is that I wanted a way to write purely data-driven, front-end tests. The benefits could be summarized as:

  • It makes it possible to write a single loader script that grabs all the YAML files in a folder and runs them one at a time (or in parallel).
  • The tests themselves could be served up from a single, remote web-server.
  • Tests could be written by non-programmers with minimal training and effort.
  • GUI tools can easily be created to write tests/automated tasks without needing any programming knowledge.

Consider the following example of registering an account:

# Go to the page.
- go: https://somesite/page.html# Click the register link.
- click: "#register"# Wait for the registration form.
- wait_for_presence: "#email"# Set the email field to a freshly-generated fake email address:
- set_value:
- "#email"
- (( fake-email ))# Create a fake password string.
- set_value:
- "#password"
- (( fake-password ))# Reference the fake password we already generated.
- set_value:
- "#password-verify"
- (( vars|password ))# Click the register button.
- click: "#register"# Wait for the redirect and the confirmation div.
- wait_for_presence: "#confirmation-div"# Assert that the registration was successful.
- assert_text_in_page: Your registration was successful!

FakeData

This example makes use of the fake-factory/faker library to generate a fake email address as well as a password. Any data that is created using the (( )) syntax is automatically assigned to a variable list for reference later.

InstallingFaker

To install prior to September 15th, 2016: pip install fake-factory

To install after September 15th, 2016: pip install faker

fake-factory / faker need only be installed for the YAML to support (( fake-* )) tags.

* can be any of the methods on the faker class. This list is extensive and is under active development. For more information, go to the fake-factory website:

https://faker.readthedocs.io/en/latest/

((special))

Items enclosed in double parentheses (( )) will be parsed in this special way upon the execution of the script.

Examples

- include: basic_setup.yml
- import: random.randint
- set_value:
- "#someinput"
- (( randint|1,2 ))

The previous example will import random.randint and use it to generate a value of either 1 or 2 and insert it into the #someinput element.


- import: random.choice
- set_value:
- "#someinput"
- (( choice|['frog','cat','bird'] ))

As you can see, the choice function doesn't take positional arguments like the randint function does. It needs a list of options.


What happens when we run a function more than once and we need to reference the second or third output?

- import: random.choice
- set_value:
- "#someinput-a"
- (( choice|['frog','cat','bird'] )) # bird
- set_value:
- "#someinput-b"
- (( choice|['frog','cat','bird'] )) # cat
- set_value:
- "#someinput-c"
- (( choice|['frog','cat','bird'] )) # cat (again)
- assert_value_of_element:
- "#someinput-a"
- (( vars|choice )) # The "choice" array. Defaults to index 0.
- assert_value_of_element:
- "#someinput-b"
- (( vars|choice|1 )) # The "choice" array index 1.
- assert_value_of_element:
- "#someinput-c"
- (( vars|choice|2 )) # The "choice" array index 2.

OK, how about values on the page itself? Is there any way to obtain and reference them from inside a YAML WebRunner script?

- value_of: "#my-input-element"# Set the value.
- set_value:
- "#someinput-a"
- (( vars|value_of|0 )) # Use the value at index 0.
- text_of: "#my-div-element"# Set the text to a variable.
- set_value:
- "#someinput-b"
- (( vars|text_of|0 )) # Use the text value at index 0.

BrowserStack example:

This library also has first-class support for BrowserStack. Using it is not much different than the examples above.

fromPyWebRunnerimportWebRunner# Change any of these values to valid ones.desired= {
'browser': 'Edge',
'browser_version': '13.0',
'os': 'Windows',
'os_version': '10',
'resolution': '1440x900'
}
# Make sure you plug in your own USERNAME and API_KEY values here.wr=WebRunner(desired_capabilities=desired,
command_executor='http://USERNAME:API_KEY@hub.browserstack.com:80/wd/hub',
driver='Remote')
wr.start()
wr.go('http://google.com')
# ... Etc.

Testing

WebTester

WebTester inherits WebRunner so it has all the same methods that WebRunner has but it adds some additional methods that are useful for testing.

Testing Asserts

  • assert_alert_not_present
  • assert_alert_present
  • assert_checked
  • assert_element_contains_text
  • assert_element_has_class
  • assert_element_not_has_class
  • assert_exists
  • assert_found
  • assert_not_checked
  • assert_not_found
  • assert_not_visible
  • assert_text_in_element
  • assert_text_in_elements
  • assert_text_in_page
  • assert_text_not_in_page
  • assert_url
  • assert_value_of_element
  • assert_visible

About

A helpful wrapper for Selenium

Resources

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Repository files navigation

PyWebRunner

A supercharged Python wrapper for Selenium

Build StatusPyPI version

Documentation

Full documentation can be located here: https://intuitivewebsolutions.github.io/PyWebRunner

Uses

You could use WebRunner to scrape a website, automate web tasks, or anything else you could imagine. It is easy to initialize and use. It's also compatible with BrowserStack using the command_executor and remote_capabilities examples on that page.

(Please note that you will need a subscription, username, and API key to make it work.)

Installing

pip install PyWebRunner

Basic Examples

# Import WebRunner if you aren't going to assert anything.# WebTester is a sub-class of WebRunnerfromPyWebRunnerimportWebRunner# Running headless FireFox is the default.wr=WebRunner() # Defaults to xvfb=True, driver=FireFox# If xvfb is not installed, it will be bypassed automatically.# Start the browser instance.wr.start()
# Navigate to a page.wr.go('https://www.google.com/')
# Fill in a text field.wr.set_value('#lst-ib', 'PyWebRunner')
wr.send_key('#lst-ib', 'ENTER')
# Click the link based on a (gross) CSS selector.wr.click('#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a')
# Wait for the page to load.wr.wait_for_presence('div.document')
# Are we there yet?wr.is_text_on_page('A helpful wrapper for Selenium') # True# Take a screenshot!wr.screenshot('/tmp/screenshot1.png')
# Stop the browser instance.wr.stop()

YAML Scripts

PyWebRunner supports running YAML scripts and includes the webrunner command.

Let's say we made a YAML script for the above example and we called it script.yml

- go: https://www.google.com/
- set_value:
- "#lst-ib"
- PyWebRunner
- send_key:
- "#lst-ib"
- "ENTER"
- click: "#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a"
- wait_for_presence: div.document
- assert_text_on_page: A helpful wrapper for Selenium
- screenshot: /tmp/screenshot1.png

We can run it like so:

webrunner script.yml

...and it will behave identically to the Python-based example above.

Advanced YAML Features

YAML supports the use of the fake-factory library (if it is installed) as well as evals and python function calls. Though the YAML is not intended as a complete replacement for Python scripts, this does enable some pretty flexible scripts to run.

You might be asking yourself, what's the purpose of parsing YAML like this if you can just write Python and have access to all these things by default?

The answer is that I wanted a way to write purely data-driven, front-end tests. The benefits could be summarized as:

  • It makes it possible to write a single loader script that grabs all the YAML files in a folder and runs them one at a time (or in parallel).
  • The tests themselves could be served up from a single, remote web-server.
  • Tests could be written by non-programmers with minimal training and effort.
  • GUI tools can easily be created to write tests/automated tasks without needing any programming knowledge.

Consider the following example of registering an account:

# Go to the page.
- go: https://somesite/page.html# Click the register link.
- click: "#register"# Wait for the registration form.
- wait_for_presence: "#email"# Set the email field to a freshly-generated fake email address:
- set_value:
- "#email"
- (( fake-email ))# Create a fake password string.
- set_value:
- "#password"
- (( fake-password ))# Reference the fake password we already generated.
- set_value:
- "#password-verify"
- (( vars|password ))# Click the register button.
- click: "#register"# Wait for the redirect and the confirmation div.
- wait_for_presence: "#confirmation-div"# Assert that the registration was successful.
- assert_text_in_page: Your registration was successful!

FakeData

This example makes use of the fake-factory/faker library to generate a fake email address as well as a password. Any data that is created using the (( )) syntax is automatically assigned to a variable list for reference later.

InstallingFaker

To install prior to September 15th, 2016: pip install fake-factory

To install after September 15th, 2016: pip install faker

fake-factory / faker need only be installed for the YAML to support (( fake-* )) tags.

* can be any of the methods on the faker class. This list is extensive and is under active development. For more information, go to the fake-factory website:

https://faker.readthedocs.io/en/latest/

((special))

Items enclosed in double parentheses (( )) will be parsed in this special way upon the execution of the script.

Examples

- include: basic_setup.yml
- import: random.randint
- set_value:
- "#someinput"
- (( randint|1,2 ))

The previous example will import random.randint and use it to generate a value of either 1 or 2 and insert it into the #someinput element.


- import: random.choice
- set_value:
- "#someinput"
- (( choice|['frog','cat','bird'] ))

As you can see, the choice function doesn't take positional arguments like the randint function does. It needs a list of options.


What happens when we run a function more than once and we need to reference the second or third output?

- import: random.choice
- set_value:
- "#someinput-a"
- (( choice|['frog','cat','bird'] )) # bird
- set_value:
- "#someinput-b"
- (( choice|['frog','cat','bird'] )) # cat
- set_value:
- "#someinput-c"
- (( choice|['frog','cat','bird'] )) # cat (again)
- assert_value_of_element:
- "#someinput-a"
- (( vars|choice )) # The "choice" array. Defaults to index 0.
- assert_value_of_element:
- "#someinput-b"
- (( vars|choice|1 )) # The "choice" array index 1.
- assert_value_of_element:
- "#someinput-c"
- (( vars|choice|2 )) # The "choice" array index 2.

OK, how about values on the page itself? Is there any way to obtain and reference them from inside a YAML WebRunner script?

- value_of: "#my-input-element"# Set the value.
- set_value:
- "#someinput-a"
- (( vars|value_of|0 )) # Use the value at index 0.
- text_of: "#my-div-element"# Set the text to a variable.
- set_value:
- "#someinput-b"
- (( vars|text_of|0 )) # Use the text value at index 0.

BrowserStack example:

This library also has first-class support for BrowserStack. Using it is not much different than the examples above.

fromPyWebRunnerimportWebRunner# Change any of these values to valid ones.desired= {
'browser': 'Edge',
'browser_version': '13.0',
'os': 'Windows',
'os_version': '10',
'resolution': '1440x900'
}
# Make sure you plug in your own USERNAME and API_KEY values here.wr=WebRunner(desired_capabilities=desired,
command_executor='http://USERNAME:API_KEY@hub.browserstack.com:80/wd/hub',
driver='Remote')
wr.start()
wr.go('http://google.com')
# ... Etc.

Testing

WebTester

WebTester inherits WebRunner so it has all the same methods that WebRunner has but it adds some additional methods that are useful for testing.

Testing Asserts

  • assert_alert_not_present
  • assert_alert_present
  • assert_checked
  • assert_element_contains_text
  • assert_element_has_class
  • assert_element_not_has_class
  • assert_exists
  • assert_found
  • assert_not_checked
  • assert_not_found
  • assert_not_visible
  • assert_text_in_element
  • assert_text_in_elements
  • assert_text_in_page
  • assert_text_not_in_page
  • assert_url
  • assert_value_of_element
  • assert_visible

About

A helpful wrapper for Selenium

Resources

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Repository files navigation

PyWebRunner

A supercharged Python wrapper for Selenium

Build StatusPyPI version

Documentation

Full documentation can be located here: https://intuitivewebsolutions.github.io/PyWebRunner

Uses

You could use WebRunner to scrape a website, automate web tasks, or anything else you could imagine. It is easy to initialize and use. It's also compatible with BrowserStack using the command_executor and remote_capabilities examples on that page.

(Please note that you will need a subscription, username, and API key to make it work.)

Installing

pip install PyWebRunner

Basic Examples

# Import WebRunner if you aren't going to assert anything.# WebTester is a sub-class of WebRunnerfromPyWebRunnerimportWebRunner# Running headless FireFox is the default.wr=WebRunner() # Defaults to xvfb=True, driver=FireFox# If xvfb is not installed, it will be bypassed automatically.# Start the browser instance.wr.start()
# Navigate to a page.wr.go('https://www.google.com/')
# Fill in a text field.wr.set_value('#lst-ib', 'PyWebRunner')
wr.send_key('#lst-ib', 'ENTER')
# Click the link based on a (gross) CSS selector.wr.click('#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a')
# Wait for the page to load.wr.wait_for_presence('div.document')
# Are we there yet?wr.is_text_on_page('A helpful wrapper for Selenium') # True# Take a screenshot!wr.screenshot('/tmp/screenshot1.png')
# Stop the browser instance.wr.stop()

YAML Scripts

PyWebRunner supports running YAML scripts and includes the webrunner command.

Let's say we made a YAML script for the above example and we called it script.yml

- go: https://www.google.com/
- set_value:
- "#lst-ib"
- PyWebRunner
- send_key:
- "#lst-ib"
- "ENTER"
- click: "#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a"
- wait_for_presence: div.document
- assert_text_on_page: A helpful wrapper for Selenium
- screenshot: /tmp/screenshot1.png

We can run it like so:

webrunner script.yml

...and it will behave identically to the Python-based example above.

Advanced YAML Features

YAML supports the use of the fake-factory library (if it is installed) as well as evals and python function calls. Though the YAML is not intended as a complete replacement for Python scripts, this does enable some pretty flexible scripts to run.

You might be asking yourself, what's the purpose of parsing YAML like this if you can just write Python and have access to all these things by default?

The answer is that I wanted a way to write purely data-driven, front-end tests. The benefits could be summarized as:

  • It makes it possible to write a single loader script that grabs all the YAML files in a folder and runs them one at a time (or in parallel).
  • The tests themselves could be served up from a single, remote web-server.
  • Tests could be written by non-programmers with minimal training and effort.
  • GUI tools can easily be created to write tests/automated tasks without needing any programming knowledge.

Consider the following example of registering an account:

# Go to the page.
- go: https://somesite/page.html# Click the register link.
- click: "#register"# Wait for the registration form.
- wait_for_presence: "#email"# Set the email field to a freshly-generated fake email address:
- set_value:
- "#email"
- (( fake-email ))# Create a fake password string.
- set_value:
- "#password"
- (( fake-password ))# Reference the fake password we already generated.
- set_value:
- "#password-verify"
- (( vars|password ))# Click the register button.
- click: "#register"# Wait for the redirect and the confirmation div.
- wait_for_presence: "#confirmation-div"# Assert that the registration was successful.
- assert_text_in_page: Your registration was successful!

FakeData

This example makes use of the fake-factory/faker library to generate a fake email address as well as a password. Any data that is created using the (( )) syntax is automatically assigned to a variable list for reference later.

InstallingFaker

To install prior to September 15th, 2016: pip install fake-factory

To install after September 15th, 2016: pip install faker

fake-factory / faker need only be installed for the YAML to support (( fake-* )) tags.

* can be any of the methods on the faker class. This list is extensive and is under active development. For more information, go to the fake-factory website:

https://faker.readthedocs.io/en/latest/

((special))

Items enclosed in double parentheses (( )) will be parsed in this special way upon the execution of the script.

Examples

- include: basic_setup.yml
- import: random.randint
- set_value:
- "#someinput"
- (( randint|1,2 ))

The previous example will import random.randint and use it to generate a value of either 1 or 2 and insert it into the #someinput element.


- import: random.choice
- set_value:
- "#someinput"
- (( choice|['frog','cat','bird'] ))

As you can see, the choice function doesn't take positional arguments like the randint function does. It needs a list of options.


What happens when we run a function more than once and we need to reference the second or third output?

- import: random.choice
- set_value:
- "#someinput-a"
- (( choice|['frog','cat','bird'] )) # bird
- set_value:
- "#someinput-b"
- (( choice|['frog','cat','bird'] )) # cat
- set_value:
- "#someinput-c"
- (( choice|['frog','cat','bird'] )) # cat (again)
- assert_value_of_element:
- "#someinput-a"
- (( vars|choice )) # The "choice" array. Defaults to index 0.
- assert_value_of_element:
- "#someinput-b"
- (( vars|choice|1 )) # The "choice" array index 1.
- assert_value_of_element:
- "#someinput-c"
- (( vars|choice|2 )) # The "choice" array index 2.

OK, how about values on the page itself? Is there any way to obtain and reference them from inside a YAML WebRunner script?

- value_of: "#my-input-element"# Set the value.
- set_value:
- "#someinput-a"
- (( vars|value_of|0 )) # Use the value at index 0.
- text_of: "#my-div-element"# Set the text to a variable.
- set_value:
- "#someinput-b"
- (( vars|text_of|0 )) # Use the text value at index 0.

BrowserStack example:

This library also has first-class support for BrowserStack. Using it is not much different than the examples above.

fromPyWebRunnerimportWebRunner# Change any of these values to valid ones.desired= {
'browser': 'Edge',
'browser_version': '13.0',
'os': 'Windows',
'os_version': '10',
'resolution': '1440x900'
}
# Make sure you plug in your own USERNAME and API_KEY values here.wr=WebRunner(desired_capabilities=desired,
command_executor='http://USERNAME:API_KEY@hub.browserstack.com:80/wd/hub',
driver='Remote')
wr.start()
wr.go('http://google.com')
# ... Etc.

Testing

WebTester

WebTester inherits WebRunner so it has all the same methods that WebRunner has but it adds some additional methods that are useful for testing.

Testing Asserts

  • assert_alert_not_present
  • assert_alert_present
  • assert_checked
  • assert_element_contains_text
  • assert_element_has_class
  • assert_element_not_has_class
  • assert_exists
  • assert_found
  • assert_not_checked
  • assert_not_found
  • assert_not_visible
  • assert_text_in_element
  • assert_text_in_elements
  • assert_text_in_page
  • assert_text_not_in_page
  • assert_url
  • assert_value_of_element
  • assert_visible

About

A helpful wrapper for Selenium

Resources

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Repository files navigation

PyWebRunner

A supercharged Python wrapper for Selenium

Build StatusPyPI version

Documentation

Full documentation can be located here: https://intuitivewebsolutions.github.io/PyWebRunner

Uses

You could use WebRunner to scrape a website, automate web tasks, or anything else you could imagine. It is easy to initialize and use. It's also compatible with BrowserStack using the command_executor and remote_capabilities examples on that page.

(Please note that you will need a subscription, username, and API key to make it work.)

Installing

pip install PyWebRunner

Basic Examples

# Import WebRunner if you aren't going to assert anything.# WebTester is a sub-class of WebRunnerfromPyWebRunnerimportWebRunner# Running headless FireFox is the default.wr=WebRunner() # Defaults to xvfb=True, driver=FireFox# If xvfb is not installed, it will be bypassed automatically.# Start the browser instance.wr.start()
# Navigate to a page.wr.go('https://www.google.com/')
# Fill in a text field.wr.set_value('#lst-ib', 'PyWebRunner')
wr.send_key('#lst-ib', 'ENTER')
# Click the link based on a (gross) CSS selector.wr.click('#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a')
# Wait for the page to load.wr.wait_for_presence('div.document')
# Are we there yet?wr.is_text_on_page('A helpful wrapper for Selenium') # True# Take a screenshot!wr.screenshot('/tmp/screenshot1.png')
# Stop the browser instance.wr.stop()

YAML Scripts

PyWebRunner supports running YAML scripts and includes the webrunner command.

Let's say we made a YAML script for the above example and we called it script.yml

- go: https://www.google.com/
- set_value:
- "#lst-ib"
- PyWebRunner
- send_key:
- "#lst-ib"
- "ENTER"
- click: "#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a"
- wait_for_presence: div.document
- assert_text_on_page: A helpful wrapper for Selenium
- screenshot: /tmp/screenshot1.png

We can run it like so:

webrunner script.yml

...and it will behave identically to the Python-based example above.

Advanced YAML Features

YAML supports the use of the fake-factory library (if it is installed) as well as evals and python function calls. Though the YAML is not intended as a complete replacement for Python scripts, this does enable some pretty flexible scripts to run.

You might be asking yourself, what's the purpose of parsing YAML like this if you can just write Python and have access to all these things by default?

The answer is that I wanted a way to write purely data-driven, front-end tests. The benefits could be summarized as:

  • It makes it possible to write a single loader script that grabs all the YAML files in a folder and runs them one at a time (or in parallel).
  • The tests themselves could be served up from a single, remote web-server.
  • Tests could be written by non-programmers with minimal training and effort.
  • GUI tools can easily be created to write tests/automated tasks without needing any programming knowledge.

Consider the following example of registering an account:

# Go to the page.
- go: https://somesite/page.html# Click the register link.
- click: "#register"# Wait for the registration form.
- wait_for_presence: "#email"# Set the email field to a freshly-generated fake email address:
- set_value:
- "#email"
- (( fake-email ))# Create a fake password string.
- set_value:
- "#password"
- (( fake-password ))# Reference the fake password we already generated.
- set_value:
- "#password-verify"
- (( vars|password ))# Click the register button.
- click: "#register"# Wait for the redirect and the confirmation div.
- wait_for_presence: "#confirmation-div"# Assert that the registration was successful.
- assert_text_in_page: Your registration was successful!

FakeData

This example makes use of the fake-factory/faker library to generate a fake email address as well as a password. Any data that is created using the (( )) syntax is automatically assigned to a variable list for reference later.

InstallingFaker

To install prior to September 15th, 2016: pip install fake-factory

To install after September 15th, 2016: pip install faker

fake-factory / faker need only be installed for the YAML to support (( fake-* )) tags.

* can be any of the methods on the faker class. This list is extensive and is under active development. For more information, go to the fake-factory website:

https://faker.readthedocs.io/en/latest/

((special))

Items enclosed in double parentheses (( )) will be parsed in this special way upon the execution of the script.

Examples

- include: basic_setup.yml
- import: random.randint
- set_value:
- "#someinput"
- (( randint|1,2 ))

The previous example will import random.randint and use it to generate a value of either 1 or 2 and insert it into the #someinput element.


- import: random.choice
- set_value:
- "#someinput"
- (( choice|['frog','cat','bird'] ))

As you can see, the choice function doesn't take positional arguments like the randint function does. It needs a list of options.


What happens when we run a function more than once and we need to reference the second or third output?

- import: random.choice
- set_value:
- "#someinput-a"
- (( choice|['frog','cat','bird'] )) # bird
- set_value:
- "#someinput-b"
- (( choice|['frog','cat','bird'] )) # cat
- set_value:
- "#someinput-c"
- (( choice|['frog','cat','bird'] )) # cat (again)
- assert_value_of_element:
- "#someinput-a"
- (( vars|choice )) # The "choice" array. Defaults to index 0.
- assert_value_of_element:
- "#someinput-b"
- (( vars|choice|1 )) # The "choice" array index 1.
- assert_value_of_element:
- "#someinput-c"
- (( vars|choice|2 )) # The "choice" array index 2.

OK, how about values on the page itself? Is there any way to obtain and reference them from inside a YAML WebRunner script?

- value_of: "#my-input-element"# Set the value.
- set_value:
- "#someinput-a"
- (( vars|value_of|0 )) # Use the value at index 0.
- text_of: "#my-div-element"# Set the text to a variable.
- set_value:
- "#someinput-b"
- (( vars|text_of|0 )) # Use the text value at index 0.

BrowserStack example:

This library also has first-class support for BrowserStack. Using it is not much different than the examples above.

fromPyWebRunnerimportWebRunner# Change any of these values to valid ones.desired= {
'browser': 'Edge',
'browser_version': '13.0',
'os': 'Windows',
'os_version': '10',
'resolution': '1440x900'
}
# Make sure you plug in your own USERNAME and API_KEY values here.wr=WebRunner(desired_capabilities=desired,
command_executor='http://USERNAME:API_KEY@hub.browserstack.com:80/wd/hub',
driver='Remote')
wr.start()
wr.go('http://google.com')
# ... Etc.

Testing

WebTester

WebTester inherits WebRunner so it has all the same methods that WebRunner has but it adds some additional methods that are useful for testing.

Testing Asserts

  • assert_alert_not_present
  • assert_alert_present
  • assert_checked
  • assert_element_contains_text
  • assert_element_has_class
  • assert_element_not_has_class
  • assert_exists
  • assert_found
  • assert_not_checked
  • assert_not_found
  • assert_not_visible
  • assert_text_in_element
  • assert_text_in_elements
  • assert_text_in_page
  • assert_text_not_in_page
  • assert_url
  • assert_value_of_element
  • assert_visible

About

A helpful wrapper for Selenium

Resources

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Repository files navigation

PyWebRunner

A supercharged Python wrapper for Selenium

Build StatusPyPI version

Documentation

Full documentation can be located here: https://intuitivewebsolutions.github.io/PyWebRunner

Uses

You could use WebRunner to scrape a website, automate web tasks, or anything else you could imagine. It is easy to initialize and use. It's also compatible with BrowserStack using the command_executor and remote_capabilities examples on that page.

(Please note that you will need a subscription, username, and API key to make it work.)

Installing

pip install PyWebRunner

Basic Examples

# Import WebRunner if you aren't going to assert anything.# WebTester is a sub-class of WebRunnerfromPyWebRunnerimportWebRunner# Running headless FireFox is the default.wr=WebRunner() # Defaults to xvfb=True, driver=FireFox# If xvfb is not installed, it will be bypassed automatically.# Start the browser instance.wr.start()
# Navigate to a page.wr.go('https://www.google.com/')
# Fill in a text field.wr.set_value('#lst-ib', 'PyWebRunner')
wr.send_key('#lst-ib', 'ENTER')
# Click the link based on a (gross) CSS selector.wr.click('#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a')
# Wait for the page to load.wr.wait_for_presence('div.document')
# Are we there yet?wr.is_text_on_page('A helpful wrapper for Selenium') # True# Take a screenshot!wr.screenshot('/tmp/screenshot1.png')
# Stop the browser instance.wr.stop()

YAML Scripts

PyWebRunner supports running YAML scripts and includes the webrunner command.

Let's say we made a YAML script for the above example and we called it script.yml

- go: https://www.google.com/
- set_value:
- "#lst-ib"
- PyWebRunner
- send_key:
- "#lst-ib"
- "ENTER"
- click: "#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a"
- wait_for_presence: div.document
- assert_text_on_page: A helpful wrapper for Selenium
- screenshot: /tmp/screenshot1.png

We can run it like so:

webrunner script.yml

...and it will behave identically to the Python-based example above.

Advanced YAML Features

YAML supports the use of the fake-factory library (if it is installed) as well as evals and python function calls. Though the YAML is not intended as a complete replacement for Python scripts, this does enable some pretty flexible scripts to run.

You might be asking yourself, what's the purpose of parsing YAML like this if you can just write Python and have access to all these things by default?

The answer is that I wanted a way to write purely data-driven, front-end tests. The benefits could be summarized as:

  • It makes it possible to write a single loader script that grabs all the YAML files in a folder and runs them one at a time (or in parallel).
  • The tests themselves could be served up from a single, remote web-server.
  • Tests could be written by non-programmers with minimal training and effort.
  • GUI tools can easily be created to write tests/automated tasks without needing any programming knowledge.

Consider the following example of registering an account:

# Go to the page.
- go: https://somesite/page.html# Click the register link.
- click: "#register"# Wait for the registration form.
- wait_for_presence: "#email"# Set the email field to a freshly-generated fake email address:
- set_value:
- "#email"
- (( fake-email ))# Create a fake password string.
- set_value:
- "#password"
- (( fake-password ))# Reference the fake password we already generated.
- set_value:
- "#password-verify"
- (( vars|password ))# Click the register button.
- click: "#register"# Wait for the redirect and the confirmation div.
- wait_for_presence: "#confirmation-div"# Assert that the registration was successful.
- assert_text_in_page: Your registration was successful!

FakeData

This example makes use of the fake-factory/faker library to generate a fake email address as well as a password. Any data that is created using the (( )) syntax is automatically assigned to a variable list for reference later.

InstallingFaker

To install prior to September 15th, 2016: pip install fake-factory

To install after September 15th, 2016: pip install faker

fake-factory / faker need only be installed for the YAML to support (( fake-* )) tags.

* can be any of the methods on the faker class. This list is extensive and is under active development. For more information, go to the fake-factory website:

https://faker.readthedocs.io/en/latest/

((special))

Items enclosed in double parentheses (( )) will be parsed in this special way upon the execution of the script.

Examples

- include: basic_setup.yml
- import: random.randint
- set_value:
- "#someinput"
- (( randint|1,2 ))

The previous example will import random.randint and use it to generate a value of either 1 or 2 and insert it into the #someinput element.


- import: random.choice
- set_value:
- "#someinput"
- (( choice|['frog','cat','bird'] ))

As you can see, the choice function doesn't take positional arguments like the randint function does. It needs a list of options.


What happens when we run a function more than once and we need to reference the second or third output?

- import: random.choice
- set_value:
- "#someinput-a"
- (( choice|['frog','cat','bird'] )) # bird
- set_value:
- "#someinput-b"
- (( choice|['frog','cat','bird'] )) # cat
- set_value:
- "#someinput-c"
- (( choice|['frog','cat','bird'] )) # cat (again)
- assert_value_of_element:
- "#someinput-a"
- (( vars|choice )) # The "choice" array. Defaults to index 0.
- assert_value_of_element:
- "#someinput-b"
- (( vars|choice|1 )) # The "choice" array index 1.
- assert_value_of_element:
- "#someinput-c"
- (( vars|choice|2 )) # The "choice" array index 2.

OK, how about values on the page itself? Is there any way to obtain and reference them from inside a YAML WebRunner script?

- value_of: "#my-input-element"# Set the value.
- set_value:
- "#someinput-a"
- (( vars|value_of|0 )) # Use the value at index 0.
- text_of: "#my-div-element"# Set the text to a variable.
- set_value:
- "#someinput-b"
- (( vars|text_of|0 )) # Use the text value at index 0.

BrowserStack example:

This library also has first-class support for BrowserStack. Using it is not much different than the examples above.

fromPyWebRunnerimportWebRunner# Change any of these values to valid ones.desired= {
'browser': 'Edge',
'browser_version': '13.0',
'os': 'Windows',
'os_version': '10',
'resolution': '1440x900'
}
# Make sure you plug in your own USERNAME and API_KEY values here.wr=WebRunner(desired_capabilities=desired,
command_executor='http://USERNAME:API_KEY@hub.browserstack.com:80/wd/hub',
driver='Remote')
wr.start()
wr.go('http://google.com')
# ... Etc.

Testing

WebTester

WebTester inherits WebRunner so it has all the same methods that WebRunner has but it adds some additional methods that are useful for testing.

Testing Asserts

  • assert_alert_not_present
  • assert_alert_present
  • assert_checked
  • assert_element_contains_text
  • assert_element_has_class
  • assert_element_not_has_class
  • assert_exists
  • assert_found
  • assert_not_checked
  • assert_not_found
  • assert_not_visible
  • assert_text_in_element
  • assert_text_in_elements
  • assert_text_in_page
  • assert_text_not_in_page
  • assert_url
  • assert_value_of_element
  • assert_visible

About

A helpful wrapper for Selenium

Resources

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Repository files navigation

PyWebRunner

A supercharged Python wrapper for Selenium

Build StatusPyPI version

Documentation

Full documentation can be located here: https://intuitivewebsolutions.github.io/PyWebRunner

Uses

You could use WebRunner to scrape a website, automate web tasks, or anything else you could imagine. It is easy to initialize and use. It's also compatible with BrowserStack using the command_executor and remote_capabilities examples on that page.

(Please note that you will need a subscription, username, and API key to make it work.)

Installing

pip install PyWebRunner

Basic Examples

# Import WebRunner if you aren't going to assert anything.# WebTester is a sub-class of WebRunnerfromPyWebRunnerimportWebRunner# Running headless FireFox is the default.wr=WebRunner() # Defaults to xvfb=True, driver=FireFox# If xvfb is not installed, it will be bypassed automatically.# Start the browser instance.wr.start()
# Navigate to a page.wr.go('https://www.google.com/')
# Fill in a text field.wr.set_value('#lst-ib', 'PyWebRunner')
wr.send_key('#lst-ib', 'ENTER')
# Click the link based on a (gross) CSS selector.wr.click('#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a')
# Wait for the page to load.wr.wait_for_presence('div.document')
# Are we there yet?wr.is_text_on_page('A helpful wrapper for Selenium') # True# Take a screenshot!wr.screenshot('/tmp/screenshot1.png')
# Stop the browser instance.wr.stop()

YAML Scripts

PyWebRunner supports running YAML scripts and includes the webrunner command.

Let's say we made a YAML script for the above example and we called it script.yml

- go: https://www.google.com/
- set_value:
- "#lst-ib"
- PyWebRunner
- send_key:
- "#lst-ib"
- "ENTER"
- click: "#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a"
- wait_for_presence: div.document
- assert_text_on_page: A helpful wrapper for Selenium
- screenshot: /tmp/screenshot1.png

We can run it like so:

webrunner script.yml

...and it will behave identically to the Python-based example above.

Advanced YAML Features

YAML supports the use of the fake-factory library (if it is installed) as well as evals and python function calls. Though the YAML is not intended as a complete replacement for Python scripts, this does enable some pretty flexible scripts to run.

You might be asking yourself, what's the purpose of parsing YAML like this if you can just write Python and have access to all these things by default?

The answer is that I wanted a way to write purely data-driven, front-end tests. The benefits could be summarized as:

  • It makes it possible to write a single loader script that grabs all the YAML files in a folder and runs them one at a time (or in parallel).
  • The tests themselves could be served up from a single, remote web-server.
  • Tests could be written by non-programmers with minimal training and effort.
  • GUI tools can easily be created to write tests/automated tasks without needing any programming knowledge.

Consider the following example of registering an account:

# Go to the page.
- go: https://somesite/page.html# Click the register link.
- click: "#register"# Wait for the registration form.
- wait_for_presence: "#email"# Set the email field to a freshly-generated fake email address:
- set_value:
- "#email"
- (( fake-email ))# Create a fake password string.
- set_value:
- "#password"
- (( fake-password ))# Reference the fake password we already generated.
- set_value:
- "#password-verify"
- (( vars|password ))# Click the register button.
- click: "#register"# Wait for the redirect and the confirmation div.
- wait_for_presence: "#confirmation-div"# Assert that the registration was successful.
- assert_text_in_page: Your registration was successful!

FakeData

This example makes use of the fake-factory/faker library to generate a fake email address as well as a password. Any data that is created using the (( )) syntax is automatically assigned to a variable list for reference later.

InstallingFaker

To install prior to September 15th, 2016: pip install fake-factory

To install after September 15th, 2016: pip install faker

fake-factory / faker need only be installed for the YAML to support (( fake-* )) tags.

* can be any of the methods on the faker class. This list is extensive and is under active development. For more information, go to the fake-factory website:

https://faker.readthedocs.io/en/latest/

((special))

Items enclosed in double parentheses (( )) will be parsed in this special way upon the execution of the script.

Examples

- include: basic_setup.yml
- import: random.randint
- set_value:
- "#someinput"
- (( randint|1,2 ))

The previous example will import random.randint and use it to generate a value of either 1 or 2 and insert it into the #someinput element.


- import: random.choice
- set_value:
- "#someinput"
- (( choice|['frog','cat','bird'] ))

As you can see, the choice function doesn't take positional arguments like the randint function does. It needs a list of options.


What happens when we run a function more than once and we need to reference the second or third output?

- import: random.choice
- set_value:
- "#someinput-a"
- (( choice|['frog','cat','bird'] )) # bird
- set_value:
- "#someinput-b"
- (( choice|['frog','cat','bird'] )) # cat
- set_value:
- "#someinput-c"
- (( choice|['frog','cat','bird'] )) # cat (again)
- assert_value_of_element:
- "#someinput-a"
- (( vars|choice )) # The "choice" array. Defaults to index 0.
- assert_value_of_element:
- "#someinput-b"
- (( vars|choice|1 )) # The "choice" array index 1.
- assert_value_of_element:
- "#someinput-c"
- (( vars|choice|2 )) # The "choice" array index 2.

OK, how about values on the page itself? Is there any way to obtain and reference them from inside a YAML WebRunner script?

- value_of: "#my-input-element"# Set the value.
- set_value:
- "#someinput-a"
- (( vars|value_of|0 )) # Use the value at index 0.
- text_of: "#my-div-element"# Set the text to a variable.
- set_value:
- "#someinput-b"
- (( vars|text_of|0 )) # Use the text value at index 0.

BrowserStack example:

This library also has first-class support for BrowserStack. Using it is not much different than the examples above.

fromPyWebRunnerimportWebRunner# Change any of these values to valid ones.desired= {
'browser': 'Edge',
'browser_version': '13.0',
'os': 'Windows',
'os_version': '10',
'resolution': '1440x900'
}
# Make sure you plug in your own USERNAME and API_KEY values here.wr=WebRunner(desired_capabilities=desired,
command_executor='http://USERNAME:API_KEY@hub.browserstack.com:80/wd/hub',
driver='Remote')
wr.start()
wr.go('http://google.com')
# ... Etc.

Testing

WebTester

WebTester inherits WebRunner so it has all the same methods that WebRunner has but it adds some additional methods that are useful for testing.

Testing Asserts

  • assert_alert_not_present
  • assert_alert_present
  • assert_checked
  • assert_element_contains_text
  • assert_element_has_class
  • assert_element_not_has_class
  • assert_exists
  • assert_found
  • assert_not_checked
  • assert_not_found
  • assert_not_visible
  • assert_text_in_element
  • assert_text_in_elements
  • assert_text_in_page
  • assert_text_not_in_page
  • assert_url
  • assert_value_of_element
  • assert_visible

About

A helpful wrapper for Selenium

Resources

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Repository files navigation

PyWebRunner

A supercharged Python wrapper for Selenium

Build StatusPyPI version

Documentation

Full documentation can be located here: https://intuitivewebsolutions.github.io/PyWebRunner

Uses

You could use WebRunner to scrape a website, automate web tasks, or anything else you could imagine. It is easy to initialize and use. It's also compatible with BrowserStack using the command_executor and remote_capabilities examples on that page.

(Please note that you will need a subscription, username, and API key to make it work.)

Installing

pip install PyWebRunner

Basic Examples

# Import WebRunner if you aren't going to assert anything.# WebTester is a sub-class of WebRunnerfromPyWebRunnerimportWebRunner# Running headless FireFox is the default.wr=WebRunner() # Defaults to xvfb=True, driver=FireFox# If xvfb is not installed, it will be bypassed automatically.# Start the browser instance.wr.start()
# Navigate to a page.wr.go('https://www.google.com/')
# Fill in a text field.wr.set_value('#lst-ib', 'PyWebRunner')
wr.send_key('#lst-ib', 'ENTER')
# Click the link based on a (gross) CSS selector.wr.click('#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a')
# Wait for the page to load.wr.wait_for_presence('div.document')
# Are we there yet?wr.is_text_on_page('A helpful wrapper for Selenium') # True# Take a screenshot!wr.screenshot('/tmp/screenshot1.png')
# Stop the browser instance.wr.stop()

YAML Scripts

PyWebRunner supports running YAML scripts and includes the webrunner command.

Let's say we made a YAML script for the above example and we called it script.yml

- go: https://www.google.com/
- set_value:
- "#lst-ib"
- PyWebRunner
- send_key:
- "#lst-ib"
- "ENTER"
- click: "#rso > div:nth-child(1) > div:nth-child(1) > div > h3 > a"
- wait_for_presence: div.document
- assert_text_on_page: A helpful wrapper for Selenium
- screenshot: /tmp/screenshot1.png

We can run it like so:

webrunner script.yml

...and it will behave identically to the Python-based example above.

Advanced YAML Features

YAML supports the use of the fake-factory library (if it is installed) as well as evals and python function calls. Though the YAML is not intended as a complete replacement for Python scripts, this does enable some pretty flexible scripts to run.

You might be asking yourself, what's the purpose of parsing YAML like this if you can just write Python and have access to all these things by default?

The answer is that I wanted a way to write purely data-driven, front-end tests. The benefits could be summarized as:

  • It makes it possible to write a single loader script that grabs all the YAML files in a folder and runs them one at a time (or in parallel).
  • The tests themselves could be served up from a single, remote web-server.
  • Tests could be written by non-programmers with minimal training and effort.
  • GUI tools can easily be created to write tests/automated tasks without needing any programming knowledge.

Consider the following example of registering an account:

# Go to the page.
- go: https://somesite/page.html# Click the register link.
- click: "#register"# Wait for the registration form.
- wait_for_presence: "#email"# Set the email field to a freshly-generated fake email address:
- set_value:
- "#email"
- (( fake-email ))# Create a fake password string.
- set_value:
- "#password"
- (( fake-password ))# Reference the fake password we already generated.
- set_value:
- "#password-verify"
- (( vars|password ))# Click the register button.
- click: "#register"# Wait for the redirect and the confirmation div.
- wait_for_presence: "#confirmation-div"# Assert that the registration was successful.
- assert_text_in_page: Your registration was successful!

FakeData

This example makes use of the fake-factory/faker library to generate a fake email address as well as a password. Any data that is created using the (( )) syntax is automatically assigned to a variable list for reference later.

InstallingFaker

To install prior to September 15th, 2016: pip install fake-factory

To install after September 15th, 2016: pip install faker

fake-factory / faker need only be installed for the YAML to support (( fake-* )) tags.

* can be any of the methods on the faker class. This list is extensive and is under active development. For more information, go to the fake-factory website:

https://faker.readthedocs.io/en/latest/

((special))

Items enclosed in double parentheses (( )) will be parsed in this special way upon the execution of the script.

Examples

- include: basic_setup.yml
- import: random.randint
- set_value:
- "#someinput"
- (( randint|1,2 ))

The previous example will import random.randint and use it to generate a value of either 1 or 2 and insert it into the #someinput element.


- import: random.choice
- set_value:
- "#someinput"
- (( choice|['frog','cat','bird'] ))

As you can see, the choice function doesn't take positional arguments like the randint function does. It needs a list of options.


What happens when we run a function more than once and we need to reference the second or third output?

- import: random.choice
- set_value:
- "#someinput-a"
- (( choice|['frog','cat','bird'] )) # bird
- set_value:
- "#someinput-b"
- (( choice|['frog','cat','bird'] )) # cat
- set_value:
- "#someinput-c"
- (( choice|['frog','cat','bird'] )) # cat (again)
- assert_value_of_element:
- "#someinput-a"
- (( vars|choice )) # The "choice" array. Defaults to index 0.
- assert_value_of_element:
- "#someinput-b"
- (( vars|choice|1 )) # The "choice" array index 1.
- assert_value_of_element:
- "#someinput-c"
- (( vars|choice|2 )) # The "choice" array index 2.

OK, how about values on the page itself? Is there any way to obtain and reference them from inside a YAML WebRunner script?

- value_of: "#my-input-element"# Set the value.
- set_value:
- "#someinput-a"
- (( vars|value_of|0 )) # Use the value at index 0.
- text_of: "#my-div-element"# Set the text to a variable.
- set_value:
- "#someinput-b"
- (( vars|text_of|0 )) # Use the text value at index 0.

BrowserStack example:

This library also has first-class support for BrowserStack. Using it is not much different than the examples above.

fromPyWebRunnerimportWebRunner# Change any of these values to valid ones.desired= {
'browser': 'Edge',
'browser_version': '13.0',
'os': 'Windows',
'os_version': '10',
'resolution': '1440x900'
}
# Make sure you plug in your own USERNAME and API_KEY values here.wr=WebRunner(desired_capabilities=desired,
command_executor='http://USERNAME:API_KEY@hub.browserstack.com:80/wd/hub',
driver='Remote')
wr.start()
wr.go('http://google.com')
# ... Etc.

Testing

WebTester

WebTester inherits WebRunner so it has all the same methods that WebRunner has but it adds some additional methods that are useful for testing.

Testing Asserts

  • assert_alert_not_present
  • assert_alert_present
  • assert_checked
  • assert_element_contains_text
  • assert_element_has_class
  • assert_element_not_has_class
  • assert_exists
  • assert_found
  • assert_not_checked
  • assert_not_found
  • assert_not_visible
  • assert_text_in_element
  • assert_text_in_elements
  • assert_text_in_page
  • assert_text_not_in_page
  • assert_url
  • assert_value_of_element
  • assert_visible

About

A helpful wrapper for Selenium

Resources

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages