Principle:MarketSquare Robotframework browser JavaScript Module Authoring
Overview
The robotframework-browser library allows users to extend its keyword set by writing JavaScript modules that export functions. These functions are loaded at library import time and become first-class Robot Framework keywords. The authoring contract is based on the CommonJS module format: each function that should be exposed as a keyword must be explicitly assigned to the exports object of the module.
This principle covers the rules, conventions, and constraints that govern how a JavaScript extension module must be structured so the Browser library can introspect, register, and invoke its functions.
Core Concept
A JavaScript extension module is a .js file written in CommonJS format. Every function attached to exports is discovered by the Browser library's Node.js gRPC server during the InitializeExtension call. The server inspects each exported function's name, parameter list, default values, and optional .rfdoc property, then reports them back to the Python side for dynamic keyword generation.
Module Structure Requirements
CommonJS Export Pattern
All extension modules must use the CommonJS exports object. ES module syntax (import/export) is not supported directly and must be transpiled first (see MarketSquare_Robotframework_browser_ES2015_Module_Transpilation).
The canonical pattern is:
exports.__esModule = true;
exports.myFunctionName = myFunctionName;
Setting exports.__esModule = true signals that the module follows the ES module interop convention, which the Browser library expects.
Function Definitions
Functions can be defined as:
- Named async functions -- the most common form for functions that interact with Playwright objects
- Named synchronous functions -- for simple computations or error-throwing utilities
- Arrow functions -- assigned directly to exports
Both async and synchronous functions are supported. Async functions are awaited on the Node.js side before returning results.
Naming Convention
JavaScript function names written in camelCase are automatically converted to space-separated Robot Framework keyword names:
| JavaScript Function Name | Robot Framework Keyword Name |
|---|---|
myFunkyKeyword |
My Funky Keyword |
createRemoteBrowser |
Create Remote Browser |
withDefaultValue |
With Default Value |
This conversion is performed during keyword registration so that keywords follow Robot Framework naming conventions without requiring manual mapping.
Reserved Parameter Names
Certain parameter names are reserved and are automatically injected by the Node.js runtime when the keyword is called. The user does not supply values for these parameters; they are filled in by the gRPC server with live Playwright objects or utilities:
| Reserved Name | Injected Value |
|---|---|
page |
The currently active Playwright Page object |
context |
The currently active BrowserContext object |
browser |
The currently active Browser object |
logger |
A logging function that forwards messages to Robot Framework's log |
playwright |
The Playwright module instance itself |
When the Python side serializes arguments for a gRPC call, reserved parameter names are replaced with the string "RESERVED". The Node.js side detects this sentinel and substitutes the actual live objects.
Default Value Mapping
JavaScript default values in function signatures are mapped to their Python equivalents when generating the wrapper keyword:
| JavaScript Default | Python Equivalent |
|---|---|
true |
True
|
false |
False
|
null |
None
|
undefined |
None
|
NaN |
float('nan')
|
Infinity |
float('inf')
|
-Infinity |
float('-inf')
|
String and numeric defaults are passed through unchanged.
Forbidden Parameters
The parameter name self is forbidden in JavaScript extension functions. Because the Python wrapper is generated as a bound method on a LibraryComponent instance, self is already the first positional argument. If a JavaScript function declares a parameter named self, the generated Python code will have a syntax conflict, and the library raises a SyntaxError via DataError.
Custom Documentation
Functions may optionally have a .rfdoc property attached. When present, its string value is used as the keyword's documentation in Robot Framework's libdoc output and log:
async function withDefaultValue(a = "default") {
return a.toUpperCase();
}
withDefaultValue.rfdoc = "This function returns the default value if no argument is passed";
If .rfdoc is not set, the keyword will have an empty documentation string.
The args Parameter (Legacy Style)
For backward compatibility, a function may declare a parameter named args. This is mapped to Python's *args (variadic positional arguments). In this legacy style, the caller passes positional arguments which arrive as an array on the JavaScript side:
async function myFunkyKeyword(page, args, logger) {
const h = await page.locator(args[0]);
// ...
}
The newer style uses named parameters directly (e.g., selector, message), which is preferred for clarity.
Error Propagation
If a JavaScript function throws an error (e.g., throw Error("Crash")), the error message is propagated back through the gRPC response and surfaces as a Robot Framework keyword failure.
Domains
- JavaScript -- Module authoring uses CommonJS conventions and Node.js runtime features
- Test_Automation -- The purpose is to create custom test keywords for Robot Framework
Implemented By
Related Topics
- MarketSquare_Robotframework_browser_Js_Module_Exports_Pattern -- Implementation details of the CommonJS export pattern
- MarketSquare_Robotframework_browser_ES2015_Module_Transpilation -- How to use ES2015+ syntax with transpilation
- MarketSquare_Robotframework_browser_Extension_Import_and_Registration -- How modules are loaded and registered
- MarketSquare_Robotframework_browser_Custom_Keyword_Invocation -- How registered keywords are called at runtime