Skip to content

Commit

Permalink
Update keywords document v0.3 (#8)
Browse files Browse the repository at this point in the history
* setup_document  added documents

* setup_documents add new doc for waiting keyword #1

* setup_document add document for waiting keyword #2

* Update quck start doc

* Clanup doc

Co-authored-by: Penploy <penploy.s@gmail.com>
  • Loading branch information
atthaboon and penploy authored Jun 27, 2020
1 parent 64a0b3f commit 5f0d5a3
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 42 deletions.
4 changes: 3 additions & 1 deletion Examples/quick-start.robot
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Example login form submit
Maximize Browser Window
Input text id:username_field demo
Input text id:password_field mode
Click Element id:login_button
Run Async Keywords
... Click Element id:login_button AND
... Wait For Response Url http://127.0.0.1:7272/welcome.html
Wait Until Page Contains Login succeeded
# Logout and wait for homepage loaded
Run Async Keywords
Expand Down
3 changes: 0 additions & 3 deletions PuppeteerLibrary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ class PuppeteerLibrary(DynamicCore):
| link | Exact text a link has. | ``link:Home page`` |
| partial link | Partial link text | ``partial link:Home`` |
== Asynchronous Handler ==
Core functionality for
"""

ROBOT_LIBRARY_SCOPE = 'GLOBAL'
Expand Down
12 changes: 10 additions & 2 deletions PuppeteerLibrary/keywords/browsermanagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def open_browser(self, url, browser="chrome", alias=None, options=None):
Example:
| &{options} = | create dictionary | headless=${False} |
| Open browser | https://www.w3schools.com/html/html_forms.asp | options=${options} |
| &{options} = | create dictionary | headless=${False} |
| `Open browser` | https://www.w3schools.com/html/html_forms.asp | options=${options} |
"""
async def open_browser_async():
Expand Down Expand Up @@ -104,6 +104,14 @@ async def reload_page_async():

@keyword
def wait_for_new_window_open(self, timeout=5):
"""
Waits until new page or tab opens.
Example:
| Run Async Keywords | Click Element | id:view_conditions | AND |
| ... | `Wait For New Window Open` | | |
"""
async def wait_for_new_page_open_async():
pages = await self.ctx.get_browser().pages()
await pages[-1].title() # workaround for force pages re-cache
Expand Down
60 changes: 48 additions & 12 deletions PuppeteerLibrary/keywords/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,61 @@ def __init__(self, ctx):
self.async_func = ElementKeywordsAsync(self.ctx)

@keyword
def click_element(self, selenium_locator):
return self.loop.run_until_complete(self.async_func.click_element_async(selenium_locator))
def click_element(self, locator):
"""Clicks element identified by ``locator``.
Example:
| `Click Element` | id:register |
"""
return self.loop.run_until_complete(self.async_func.click_element_async(locator))

@keyword
def click_link(self, selenium_locator):
return self.loop.run_until_complete(self.async_func.click_link_async(selenium_locator))
def click_link(self, locator):
"""Clicks link identified by ``locator``.
Example:
| `Click Link` | id:view_more |
"""
return self.loop.run_until_complete(self.async_func.click_link_async(locator))

@keyword
def click_button(self, selenium_locator):
self.loop.run_until_complete(self.async_func.click_button_async(selenium_locator))
def click_button(self, locator):
"""Clicks button identified by ``locator``.
Example:
| `Click Button` | id:submit |
"""
self.loop.run_until_complete(self.async_func.click_button_async(locator))

@keyword
def click_image(self, selenium_locator):
self.loop.run_until_complete(self.async_func.click_image_async(selenium_locator))
def click_image(self, locator):
"""Clicks image identified by ``locator``.
Example:
| `Click Image` | id:cat_image |
"""
self.loop.run_until_complete(self.async_func.click_image_async(locator))

@keyword
def get_text(self, selenium_locator):
return self.loop.run_until_complete(self.async_func.get_text_async(selenium_locator))
def get_text(self, locator):
"""Returns text value of element identified by ``locator``.
Example:
| ${text} | `Get Text` | id:username |
"""
return self.loop.run_until_complete(self.async_func.get_text_async(locator))

@keyword
def get_value(self, selenium_locator):
return self.loop.run_until_complete(self.async_func.get_text_async(selenium_locator))
def get_value(self, locator):
"""Returns specific attribute value of element identified by ``locator``.
Example:
| ${value} | `Get Value` | id:comment |
"""
return self.loop.run_until_complete(self.async_func.get_text_async(locator))
24 changes: 20 additions & 4 deletions PuppeteerLibrary/keywords/formelement.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,26 @@ def __init__(self, ctx):
self.async_func = FormElementKeywordsAsync(self.ctx)

@keyword
def input_text(self, selenium_locator, text, clear=True):
self.loop.run_until_complete(self.async_func.input_text_async(selenium_locator, text, clear))
def input_text(self, locator, text, clear=True):
"""Types the given text into text field identified by ``locator``.
If clear is true, the input element will be cleared before the text is typed into the element.
On the other hand clear is false, the previous text will not be cleared from the element.
Examples:
| `Input Text` | id:name | John Doe | |
| `Input Text` | id:username | john | True |
"""
self.loop.run_until_complete(self.async_func.input_text_async(locator, text, clear))

@keyword
def clear_element_text(self, selenium_locator):
self.loop.run_until_complete(self.async_func.clear_element_text_async(selenium_locator))
def clear_element_text(self, locator):
"""Clears value of text field identified by ``locator``.
Example:
| `Clear Element Text` | id:name |
"""
self.loop.run_until_complete(self.async_func.clear_element_text_async(locator))

10 changes: 9 additions & 1 deletion PuppeteerLibrary/keywords/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ class UtilityKeywords(LibraryComponent):
@keyword
def run_async_keywords(self, *keywords):
# Ensure that script load async keywords before run async keywords function
"""Executes all the given keywords in a asynchronous and wait until all keyword is completed
Example:
| Open browser | ${HOME_PAGE_URL} | options=${options} | |
| `Run Async Keywords` | Click Element | id:login_button | AND |
| ... | Wait for response url | ${HOME_PAGE_URL}/home.html | |
"""
self.ctx.load_async_keywords()
run_keyword = _RunKeyword()
"""Executes all the given keywords in a asynchronous and wait until all keyword complete"""
self.loop.run_until_complete( self._run_async_keywords(run_keyword._split_run_keywords(list(keywords))) )

async def _run_async_keywords(self, iterable):
Expand Down
141 changes: 128 additions & 13 deletions PuppeteerLibrary/keywords/waiting.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,54 +11,169 @@ def __init__(self, ctx):

@keyword
def wait_for_request_url(self, url, method='GET', timeout=None):
"""Wait for request url"""
"""
Wait until web application sent request to ``url``.
The ``url`` is request url.
The ``method`` is HTTP Request Methods:
- GET (default)
- POST
- PUT
- HEAD
- DELETE
- PATCH
Example:
| Open browser | ${HOME_PAGE_URL} | options=${options} | |
| Input Text | id:username | foo | |
| Input Text | id:password | bar | |
| Run Async Keywords | Click Element | id:login_button | AND |
| ... | `Wait For Request Url` | ${URL_API}/login | POST |
"""
return self.loop.run_until_complete(self.async_func.wait_for_request_url_async(url, method , timeout))

@keyword
def wait_for_response_url(self, url, status=200, timeout=None):
"""Wait for response url"""
"""
Wait until web application received response from ``url``.
The ``url`` is response url.
The ``status`` is HTTP Status Codes:
- 200 (default)
- 201
- 204
- 400
- 401
- 404
- 500
Reference:[https://restfulapi.net/http-status-codes/|https://restfulapi.net/http-status-codes/]
Example:
| Open browser | ${HOME_PAGE_URL} | options=${options} | |
| Input Text | id:username | foo | |
| Input Text | id:password | bar | |
| Run Async Keywords | Click Element | id:login_button | AND |
| ... | `Wait For Response Url` | ${URL_API}/login | 200 |
"""
return self.loop.run_until_complete(self.async_func.wait_for_response_url_async(url, status, timeout))

@keyword
def wait_for_function(self, page_function):
"""Wait for page trigger function"""
"""
Waits until web application executes java script function.
The ``page_function`` is java script function.
"""
return self.loop.run_until_complete(self.async_func.wait_for_function_async(page_function))

@keyword
def wait_for_navigation(self):
"""Wait for navigation from any redirect"""
"""
Waits until web page navigates to new url or reloads.
Example:
| Open browser | ${HOME_PAGE_URL} | options=${options} | |
| Input Text | id:username | foo | |
| Input Text | id:password | bar | |
| Run Async Keywords | Click Element | id:login_button | AND |
| ... | `Wait For Navigation` | | |
"""
return self.loop.run_until_complete(self.async_func.wait_for_navigation_async())

@keyword
def wait_until_page_contains_element(self, locator, timeout=None):
"""Wait until page contains element within specific timeout"""
"""
Waits until ``locator`` element appears on current page.
Example:
| Open browser | ${HOME_PAGE_URL} | options=${options} |
| `Wait Until Page Contains Element` | id:username | |
"""
return self.loop.run_until_complete(self.async_func.wait_for_selenium_selector(locator, timeout))

@keyword
def wait_until_element_is_hidden(self, locator, timeout=None):
"""
Waits until ``locator`` element is hide or removed from web page.
Example:
| Run Async Keywords | Click Element | id:login_button | AND |
| ... | Wait For Navigation | | |
| `Wait Until Element Is Hidden` | id:login_button | | |
"""
return self.loop.run_until_complete(self.async_func.wait_until_element_is_hidden_async(locator, timeout))

@keyword
def wait_until_element_is_visible(self, locator, timeout=None):
"""
Waits until ``locator`` element is displayed on web page.
Example:
| Run Async Keywords | Click Element | id:login_button | AND |
| ... | Wait For Navigation | | |
| `Wait Until Element Is Visible` | id:welcome | | |
"""
return self.loop.run_until_complete(self.async_func.wait_until_element_is_visible_async(locator, timeout))

@keyword
def wait_until_page_contains(self, text, timeout=None):
"""Waits until ``text`` appears on the current page"""
"""
Waits until ``text`` appears on current page.
Example:
| Run Async Keywords | Click Element | id:login_button | AND |
| ... | Wait For Navigation | | |
| `Wait Until Page Contains` | Invalid user name or password | | |
"""
return self.loop.run_until_complete(self.async_func.wait_until_page_contains_async(text, timeout))

@keyword
def wait_until_page_does_not_contains(self, text, timeout=None):
"""Waits until ``text`` appears on the current page"""
"""
Waits until ``text`` disappears on current page.
Example:
| Run Async Keywords | Click Element | id:login_button | AND |
| ... | Wait For Navigation | | |
| `Wait Until Page Does Not Contains` | Please input your user name | | |
"""
return self.loop.run_until_complete(self.async_func.wait_until_page_does_not_contains_async(text, timeout))

@keyword
def wait_until_element_contains(self, selenium_locator, text, timeout=None):
"""Waits until the ``element`` contains ``text``."""
return self.loop.run_until_complete(self.async_func.wait_until_element_contains_async(selenium_locator, text, timeout))
def wait_until_element_contains(self, locator, text, timeout=None):
"""
Waits until ``locator`` element contains ``text``.
Example:
| Open browser | ${HOME_PAGE_URL} | options=${options} |
| `Wait Until Element Contains` | css:#container p | Please input your user name |
"""
return self.loop.run_until_complete(self.async_func.wait_until_element_contains_async(locator, text, timeout))

@keyword
def wait_until_element_does_not_contains(self, selenium_locator, text, timeout=None):
"""Waits until the ``element`` does not contains ``text``."""
return self.loop.run_until_complete(self.async_func.wait_until_element_does_not_contains_async(selenium_locator, text, timeout))
def wait_until_element_does_not_contains(self, locator, text, timeout=None):
"""
Waits until ``locator`` element does not contains ``text``.
Example:
| Run Async Keywords | Click Element | id:login_button | AND |
| ... | Wait For Navigation | | |
| `Wait Until Element Does Not Contains` | css:#container p | Please input your user name | |
"""
return self.loop.run_until_complete(self.async_func.wait_until_element_does_not_contains_async(locator, text, timeout))

11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# robotframework-puppeteer
Puppeteer with robotframework. This project connect between robotframework and puppeteer using [pyppeteer](https://github.com/pyppeteer/pyppeteer).
Robot Framework Puppeteer Library powered by [Pyppeteer](https://github.com/pyppeteer/pyppeteer).
Improve automated web testing with native functionality from [Puppeteer](https://github.com/puppeteer/puppeteer) by Google.

We aim for provide keyword similar to robotframework-seleniumlibrary and add core puppeteer functionality that will improve test experiences
We aim to provide keywords similar to robotframework-seleniumlibrary and add core puppeteer functionality that will improve test experiences.
Example:
- _Handle HTTP Request_
- _Handle HTTP Response_
- _Intercepter Http_
- _Intercepter javascript function_

Example: _Handle HTTP Request_, _Handle HTTP Response_ or _Intercepter http request & response_

Keyword documentation
---------------------
Expand Down
6 changes: 4 additions & 2 deletions contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ or slack with the owners of this repository before making a change.
Please note we have a code of conduct, please follow it in all your interactions with the project.

## Pull Request Process
In progress
In progress ...

## Code of Conduct
In progress
In progress ...

## Release steps
Please follow the release steps for ensure that all release will be in the same standard and pattern.

In progress ...

### Step for regenerate keywords documents
Command for Generate document

Expand Down
Loading

0 comments on commit 5f0d5a3

Please sign in to comment.