from __future__ import annotations
import html as _html
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "bindings" / "cases" / "full.json"
def doc(title: str, body: str, style: str = "") -> str:
style_tag = f"<style>{style}</style>" if style else ""
return (
f"<!doctype html><html><head><title>{_html.escape(title)}</title>"
f"{style_tag}</head><body>{body}</body></html>"
)
def case(cid, description, html, steps):
return {"id": cid, "description": description, "html": html, "steps": steps}
cases = []
for i in range(30):
title = f"Rustwright Case {i:02d}"
cases.append(case(
f"title-{i:02d}",
"Capture the document title and assert exact + substring equality.",
doc(title, f"<h1>heading {i}</h1>"),
[
{"op": "goto", "useCaseHtml": True},
{"op": "title", "capture": "title"},
{"op": "assertTitle", "equals": title},
{"op": "assertTitle", "contains": f"Case {i:02d}"},
],
))
for i in range(25):
value = f"value-{i:03d}"
body = (
'<p id="message">ready</p>'
'<input id="name">'
'<button id="go" onclick="document.querySelector(\'#message\')'
".textContent=document.querySelector('#name').value\">Go</button>"
)
cases.append(case(
f"form-{i:02d}",
"Read initial text, fill an input, click, and assert the mutated text.",
doc(f"Form {i:02d}", body),
[
{"op": "goto", "useCaseHtml": True, "waitUntil": "load"},
{"op": "textContent", "selector": "#message", "capture": "before"},
{"op": "assertText", "selector": "#message", "equals": "ready"},
{"op": "fill", "selector": "#name", "value": value},
{"op": "click", "selector": "#go"},
{"op": "textContent", "selector": "#message", "capture": "after"},
{"op": "assertText", "selector": "#message", "equals": value},
],
))
for i in range(20):
cases.append(case(
f"eval-{i:02d}",
"Pass a JSON argument, capture a decoded object, assert a primitive result.",
doc(f"Evaluate {i:02d}", ""),
[
{"op": "goto", "useCaseHtml": True},
{
"op": "evaluate",
"expression": "v => ({ n: v.n, doubled: v.n * 2, tag: v.tag, items: [v.n, v.n + 1] })",
"arg": {"n": i, "tag": f"t-{i:02d}"},
"capture": "computed",
},
{"op": "assertEval", "expression": f"{i} + {i}", "equals": i + i},
],
))
for i in range(15):
text = f"lorem {i:02d} ipsum dolor"
cases.append(case(
f"text-{i:02d}",
"Capture element text and assert contains + exact semantics.",
doc(f"Text {i:02d}", f'<article id="content">{text}</article>'),
[
{"op": "goto", "useCaseHtml": True},
{"op": "textContent", "selector": "#content", "capture": "content"},
{"op": "assertText", "selector": "#content", "contains": f"{i:02d}"},
{"op": "assertText", "selector": "#content", "equals": text},
],
))
palette = ["#2457d6", "#0b7d3e", "#8a1f5c", "#b45309", "#334155",
"#7c3aed", "#0e7490", "#be123c", "#15803d", "#a16207"]
for i in range(10):
style = f"body{{margin:0;background:{palette[i]};color:#fff;font:32px sans-serif}}main{{padding:48px}}"
cases.append(case(
f"shot-{i:02d}",
"Record the default PNG screenshot byte length for a deterministic render.",
doc(f"Shot {i:02d}", f"<main>Rustwright shot {i:02d}</main>", style),
[
{"op": "goto", "useCaseHtml": True},
{"op": "screenshot", "capture": "pngBytes"},
{"op": "evaluate", "expression": "document.body.textContent.trim()", "capture": "bodyText"},
{"op": "assertTitle", "equals": f"Shot {i:02d}"},
],
))
manifest = {"version": 1, "cases": cases}
assert len(cases) == 100, len(cases)
ids = [c["id"] for c in cases]
assert len(ids) == len(set(ids)), "duplicate ids"
OUT.write_text(json.dumps(manifest, indent=2) + "\n")
print(f"wrote {OUT} with {len(cases)} cases")