Skip to main content

Runnable Robot Framework cells

<RunnableRobot> runs a real .robot suite in the browser via Pyodide

  • the bundled RF wheel. Same infrastructure as <RunnablePython>, with CodeMirror's RF grammar + libdoc autocomplete + the rebot artifact pipeline pre-wired.
import RunnableRobot from '@/components/rf/RunnableRobot.tsx';

<RunnableRobot
client:visible
fileName="first_test.robot"
caption="Edit the suite then hit Run — log.html is produced just like the CLI."
initialCode={`*** Settings ***
Documentation My very first Robot Framework test

*** Test Cases ***
Say Hello
Log Hello, Robot Framework!
Should Be Equal \${1 + 1} \${2}
`}
/>

What the learner sees:

  • A CodeMirror editor with RF syntax highlighting + autocomplete (~298 keywords across BuiltIn, Collections, String, DateTime, OperatingSystem, Process, XML).
  • Run suite / Reset buttons in a toolbar below the editor.
  • After running:
    • Console output (stdout + stderr).
    • A stats pill: passed / failed / skipped.
    • Show / Download log.html — the detailed trace.
    • Show / Download report.html — the high-level summary.
    • Download output.xml — rebot-input XML for external tooling.

For the deep technical reference (architecture, setup, vendoring), see <RunnableRobot> deep-dive.

Props​

PropTypeRequiredDefaultNotes
initialCodestringyes—The .robot source the learner sees
fileNamestringno"suite.robot"Filename inside the virtual FS — also used as the artifact filename stem
captionstringno—Optional description rendered above the editor
runLabelstringno"Run suite"Override the run button label

Source: apps/docs/src/components/rf/RunnableRobot.tsx.

A complete example​

The lesson 1.4 from rf-training shows a real edit-and-run flow. Drop this into any lesson:

<RunnableRobot
client:visible
fileName="warehouse_smoke.robot"
caption="Two tests in one file. After Run, open log.html to see [Documentation] and [Tags] rendered."
initialCode={`*** Test Cases ***
Warehouse Arrival Is Logged
[Documentation] Smoke test confirming arrival is recorded.
[Tags] warehouse smoke
Log Shift started at Munich DC

Container Weight Is Within Limit
[Documentation] Verifies that containers do not exceed the vessel limit.
[Tags] warehouse weights
VAR \${weight: int} 8200
Should Be True \${weight} < 25000
`}
/>

After the learner clicks Run suite:

  1. Pyodide boots (first run only, ~10–15 s).
  2. The RF wheel installs into the in-worker filesystem (cached after first run).
  3. The .robot file is written to /lernkit_rf_work/.
  4. robot.run_cli([...]) executes the suite.
  5. log.html, report.html, output.xml come back as blob URLs.

Escaping ${variable} in MDX​

RF uses ${} and \${} for variable references. MDX treats {...} as a JSX expression. Two safe patterns:

Pattern 1 — backtick template with escaped $​

<RunnableRobot
initialCode={`*** Test Cases ***
Greet
Log \${weight: int}
`}
/>

The escape is the backslash before $. JavaScript template literals treat \$ as a literal $, so RF's ${weight} survives.

Pattern 2 — string concatenation​

For complex code, store it in a constant and pass it in:

import RunnableRobot from '@/components/rf/RunnableRobot.tsx';

export const ROBOT_CODE = `*** Test Cases ***
Greet
Log \${weight: int}
`;

<RunnableRobot client:visible initialCode={ROBOT_CODE} />

Use whichever is easier to read.

Editor features​

The CodeMirror editor includes:

  • Syntax highlighting for RF (StreamLanguage-based grammar; covers section headers, comments, settings, variables, control-flow keywords, keyword settings, numbers, strings).
  • Autocomplete — Ctrl-Space (or Cmd-Space) opens the popup with ~298 keywords from the vendored libdocs, filtered by the prefix you typed. Each entry shows args + short doc.
  • Bracket matching for {, [, (.
  • Active-line highlighting.
  • Tab → 4 spaces (preserves the 2-space-separator rule by NOT collapsing whitespace).
  • Undo / redo via standard keybindings.

What works in the in-browser runner​

✅ Pure-Python libraries. BuiltIn, Collections, String, DateTime, OperatingSystem, Process, XML — all work.

✅ Standard RF features. Test cases, keywords, settings, variables (typed + untyped), control structures, evaluations.

✅ Artifacts. log.html, report.html, output.xml all generated identically to a CLI run.

✅ Multiple test cases per suite.

❌ Native libraries. SeleniumLibrary and Browser (Playwright) need real OS-level browsers. They don't work in Pyodide; lessons that need them use the server-side rf-mcp runner per ADR 0009.

❌ Custom libraries from disk. The in-browser FS is virtual; learners can't Library ./helpers.py against a file outside the suite. Single-file .robot only.

❌ External services. Pyodide can't open sockets directly. Anything that needs an HTTP server, database, or file system outside the worker won't work.

What the learner can do​

✅ Edit any character of initialCode and re-run.
✅ Add new test cases / keywords.
✅ See the full RF log with keyword traces.
✅ Download artifacts and share them.
✅ Type Robot keywords with autocomplete.
✅ Iterate freely; nothing escapes the worker.

❌ Save changes across page reloads (the editor state is per-mount).

Authoring tips​

  • Keep initialCode short and self-contained. 10–20 lines is the sweet spot. Long suites belong in .robot files inside the package, loaded out-of-band.
  • Highlight the gotchas. ${1 + 1} vs ${1+1} (RF's whitespace rules); typed vs untyped variables; Should Be Equal vs Should Be Equal As Integers.
  • Use <Aside> to call out browser-only limitations. Most RF tutorials assume a CLI; learners shouldn't be surprised when Library Browser fails.
<Aside type="note">
This in-browser runner covers pure-Python Robot Framework libraries —
`BuiltIn`, `Collections`, `String`, `DateTime`, `OperatingSystem`,
`XML`, `Process`. Lessons that need `SeleniumLibrary` or `Browser`
use the server-side rf-mcp runner.
</Aside>
  • Encourage the Show log.html button. It's how learners see the per-keyword trace, which is the most powerful debugging tool RF gives you. Mention it in the caption.

SCORM packaging implications​

The RF runner needs Pyodide AND the RF wheel bundled in the zip. Use:

INCLUDE_PYODIDE_RUNTIME=1 \
node apps/docs/scripts/package-scorm12.mjs

This bundles apps/docs/public/pyodide/ (Pyodide core) + pyodide/wheels/ (RF wheel) + rf-libdocs/ (autocomplete data) into the zip. Adds ~6.3 MB compressed.

Without INCLUDE_PYODIDE_RUNTIME=1, the runner tries to fetch Pyodide from the same origin; that works in dev but fails inside an LMS where the SCO is mounted at an unknown sub-path with no upstream.

Where to go next​