Skip to main content

2.1 Python Plugin API

Python plugin API allows extending Browser library directly, by adding new keywords or replacing existing keywords. Plugin API is provided by PythonLibCore and is similar which is found from SeleniumLibrary

Python plugin API differs from JavaScript Plugin. Main difference is that JavaScript plugin allows only write code in NodeJS side. Python plugin API allows use both Python and JavaScript when creating keywords. Example with Python Plugin API it is possible use AssertionEngine.

2.1.1 Python only plugin

The simplest way to use Python plugin API is to create new keywords only in Python side. Example when there is this Python class:

import json

from robot.api import logger
from robot.api.deco import keyword

from Browser.base.librarycomponent import LibraryComponent
from Browser.generated.playwright_pb2 import Request


class SimplePythonPlugin(LibraryComponent):

@keyword
def new_plugin_cookie_keyword_with_grpc(self) -> dict:
"""Uses grpc to directly call node side function."""
with self.playwright.grpc_channel() as stub:
response = stub.GetCookies(Request().Empty())
cookies = json.loads(response.json)
logger.debug(json.dumps(cookies, indent=4))
assert len(cookies) == 1, "Too many cookies."
return {"name": cookies[0]["name"], "value": cookies[0]["value"]}

@keyword
def other_plugin_cookie_keyword_with_public_api(self) -> dict:
"""Use Browser public API to create new keyword"""
cookies = self.library.get_cookies()
logger.debug(json.dumps(cookies, indent=4))
assert len(cookies) == 1, "Too many cookies."
return {"name": cookies[0]["name"], "value": cookies[0]["value"]}

and this test:

*** Settings ***
Library Browser
... enable_playwright_debug=${True}
... plugins=${CURDIR}/SimplePythonPlugin.py
... auto_closing_level=SUITE

*** Test Cases ***
Simple Plugin Example With GRPC
[Setup] New Page https://github.com/MarketSquare/robotframework-browser
${URL} = Get Url
Set Suite Variable ${URL}
Add Cookie
... Foo22
... Bar22
... url=${URL}
... expires=3 155 760 000,195223
${cookies} = New Plugin Cookie Keyword With Grpc
Should Be Equal ${cookies}[name] Foo22
Should Be Equal ${cookies}[value] Bar22

Simple Plugin Example With Public API
Add Cookie
... Foo22
... Bar22
... url=${URL}
... expires=3 155 760 000,195223
${cookies} = Other Plugin Cookie Keyword With Public Api
Should Be Equal ${cookies}[name] Foo22
Should Be Equal ${cookies}[value] Bar22

And run the test with command:

robot --outputdir output --loglevel debug 2.2.Python_Plugin-API/simple/

Then look log.html file from the output folder. It is possible to use multiple plugins same time, but it is user responsibility make sure that they do not collide.

2.1.2 Resolving Selectors / Presenter Mode

Selector prefix is something that has to be handled by the keywords itself. First step should be to resolve the selector:

    @keyword
def disable_element(self, selector):
"""Disables an element."""
selector = self.resolve_selector(selector) # prefixes the selector with the set prefix
self.library.evaluate_javascript(selector=selector, "e => e.disabled = true")

Presenter mode works similar and resolves as well:

    @keyword
def blur(self, selector):
"""Calls blur on the element."""
selector = self.presenter_mode(selector, self.strict_mode) #highlights the element and waits and resolves the selector
self.call_js_keyword("blur", selector=selector)

2.1.3 Python plugin with NodeJS implementation

Load JS plugin

class PythonPlugin(LibraryComponent):
def __init__(self, library: Browser):
super().__init__(library)
self.initialize_js_extension(Path(__file__).parent.resolve() / "JSPlugin.js")

### Use it with self.call_js_keyword

    @keyword
def my_mouse_wheel(self, x: int, y: int):
"""This keyword calls a custom javascript keyword from the file JSPlugin.js."""
return self.call_js_keyword("myMouseWheel", x=x, y=y)

All arguments must be named and arguments must be JSON serializable.

Loading examples...