Principle:MarketSquare Robotframework browser Custom Keyword Invocation
Overview
Once JavaScript extension functions have been registered as Robot Framework keywords (see MarketSquare_Robotframework_browser_Extension_Import_and_Registration), they can be invoked from Robot Framework test cases. This principle describes the execution path: how arguments are serialized, transmitted over gRPC, processed on the Node.js side, and how return values and errors propagate back.
Core Concept
Custom keyword invocation is a cross-language remote procedure call (RPC). The Python side acts as the client, and the Node.js Playwright wrapper acts as the server. The transport is gRPC with Protocol Buffers for message serialization. The call flow is:
- Argument preparation -- Python keyword wrapper collects user-supplied arguments and marks reserved parameters with the sentinel
"RESERVED" - JSON serialization -- The argument dictionary is serialized to JSON
- gRPC call -- The serialized payload is sent via
stub.CallExtensionKeyword - Node.js execution -- The server deserializes arguments, injects live Playwright objects for reserved parameters, calls the JavaScript function
- Response streaming -- The server streams back log messages and the final JSON-serialized return value
- Result deserialization -- The Python side parses the JSON response and returns the value to Robot Framework
Argument Serialization
Arguments are packaged into a dictionary structure before serialization:
{
"arguments": [
("param_name", value_or_RESERVED),
...
]
}
Each argument is a tuple of (name, value). For reserved parameter names, the value is the string "RESERVED" rather than the user-supplied value:
| Parameter Type | Name Example | Value in Payload |
|---|---|---|
| User-supplied | selector |
The actual value passed by the test (e.g., "#my-button")
|
| Reserved | page |
"RESERVED"
|
| Reserved | logger |
"RESERVED"
|
| Reserved | playwright |
"RESERVED"
|
| Reserved | context |
"RESERVED"
|
| Reserved | browser |
"RESERVED"
|
The entire dictionary is serialized with json.dumps() and sent as the arguments field of a Request.KeywordCall protobuf message.
Node.js Side Processing
On the Node.js side, the CallExtensionKeyword handler:
- Deserializes the JSON arguments
- For each argument marked
"RESERVED", substitutes the live Playwright object:pagebecomes the current active Pagecontextbecomes the current BrowserContextbrowserbecomes the current Browserloggerbecomes a function that streams log messages back to Pythonplaywrightbecomes the Playwright module instance
- Calls the JavaScript function with the prepared arguments
- Collects the return value
Response Handling
The gRPC call returns a stream of responses. Each response message has two fields:
log-- A log message string (produced when the JS function callslogger())json-- The JSON-serialized return value (only meaningful in the final response)
The Python side iterates through all responses, logging each response.log message. After the stream completes, it examines the final response's json field:
- If
jsonis an empty string (""), the keyword returnsNone - Otherwise, it parses the JSON string with
json.loads()and returns the resulting Python object
Error Propagation
If the JavaScript function throws an error:
- The Node.js gRPC server catches the exception
- The error is transmitted as a gRPC error status
- The Python gRPC client receives the error and raises it as a Robot Framework keyword failure
- The test case reports the failure with the JavaScript error message
Programmatic Access
In addition to the auto-generated keyword wrappers (which are the primary invocation path), the Browser library provides a call_js_keyword method for programmatic access. This allows Python code (e.g., plugins or other library components) to call JavaScript extension functions directly without going through Robot Framework's keyword resolution.
Domains
- Cross_Language_Integration -- The invocation bridges Python and Node.js via gRPC
- RPC -- The mechanism is a remote procedure call over gRPC with JSON payload serialization
Implemented By
Related Topics
- MarketSquare_Robotframework_browser_Call_Js_Keyword -- Implementation details of the
call_js_keywordAPI - MarketSquare_Robotframework_browser_Extension_Import_and_Registration -- How keywords are registered before they can be invoked
- MarketSquare_Robotframework_browser_Create_Lib_Component_From_Jsextension -- The code generation that produces the auto-generated wrappers
- MarketSquare_Robotframework_browser_JavaScript_Module_Authoring -- Rules for writing the JavaScript functions that are invoked