Skip to content

Screenshots and traces are written into site-packages when keywords are called from Python outside a Robot Framework run #5151

Description

@aaltat

When keywords are called directly from Python, without a Robot Framework run, outputdir is the relative string "." (Browser/browser.py:455). Artefacts whose paths are handed to the Node side as relative strings are then resolved against the Node process's working directory, which is the wrapper directory — so they land inside the installed package instead of the user's working directory.

Under a robot run this cannot happen: outputdir comes from ${OUTPUTDIR} and is absolute. Verified.

Reproduce

from Browser import Browser

browser = Browser()
browser.new_browser("webkit", headless=True)
browser.new_page("https://robotframework-browser.org")
print(browser.take_screenshot())
browser.close_browser("ALL")

Observed:

browser/screenshot/robotframework-browser-screenshot-1.png     <- returned path
  • The returned path is relative and does not exist relative to the caller's working directory.
  • An empty ./browser/screenshot/ is created in the caller's working directory by the Python side.
  • The actual PNG is written to <site-packages>/Browser/wrapper/browser/screenshot/robotframework-browser-screenshot-1.png.

The rule

Anything Python resolves to an absolute path before sending it over gRPC is fine. Anything sent as a relative string is resolved by Node against Browser/wrapper.

Affected

Artefact Source
Screenshots returned path is relative and wrong
tracing=True trace zip Browser/keywords/playwright_state.py:874-877 — no .resolve()
Trace temp/<uuid>/ working files Browser/keywords/playwright_state.py:911
Save Storage State Browser/keywords/playwright_state.py:1720-1722 — from source, not run
Node V8 coverage output Browser/playwright.py:96 — from source, not run

Not affected

Artefact Why
playwright-log.txt opened by Python itself, Browser/playwright.py:234-235
Video explicitly resolved, Browser/keywords/playwright_state.py:948-960

An explicit tracing=Path("x.zip") is also fine — lines 878-880 do resolve it. Only the tracing=True path is affected.

Cause

Browser/browser.py:455 sets _output_dir = ".", and Browser/browser.py:795-798 returns it unchanged when there is no execution context. The Node process is started with cwd=self._browser_wrapper_dir (Browser/playwright.py:280, passed to Popen at :104).

Possible fix

Making the default absolute at construction time was probed in-process (Browser._output_dir = str(Path.cwd()) before constructing). It fixes the screenshot path, the trace zip and the trace temp directory, makes the returned paths absolute, and moves nothing to a new wrong place. It does not fix recordHar, which never passes through outputdir at all — filed separately.

Environment

Browser 20.3.0, Robot Framework 7.4.1, Python 3.14.7, macOS, webkit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions