crates/nornir-robotui/.nornir/assets/robot_ui_flow.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 560" font-family="'DejaVu Sans', 'Segoe UI', sans-serif">
<defs>
<linearGradient id="board" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0b1c2e"/>
<stop offset="1" stop-color="#06111d"/>
</linearGradient>
<linearGradient id="drive" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#14384f"/>
<stop offset="1" stop-color="#0e2a3e"/>
</linearGradient>
<linearGradient id="observe" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#173d57"/>
<stop offset="1" stop-color="#0c2438"/>
</linearGradient>
<linearGradient id="emit" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#1d4a3a"/>
<stop offset="1" stop-color="#0c2a20"/>
</linearGradient>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L8,3 L0,6 z" fill="#5fd0c0"/>
</marker>
</defs>
<rect x="0" y="0" width="1180" height="560" fill="url(#board)"/>
<text x="40" y="48" fill="#cfe9e2" font-size="26" font-weight="bold">nornir-robotui — drive → observe → emit</text>
<text x="40" y="76" fill="#7fa8b8" font-size="15">auto-click a real egui app, read back what it renders, and fill the test matrix</text>
<!-- App / Harness -->
<rect x="40" y="120" width="300" height="170" rx="12" fill="url(#drive)" stroke="#2b6a86"/>
<text x="60" y="150" fill="#e6f3ef" font-size="19" font-weight="bold">1 · DRIVE</text>
<text x="60" y="178" fill="#bcdcd4" font-size="14">egui_kittest Harness</text>
<text x="60" y="200" fill="#9fc6bd" font-size="13">RobotSession::click_label /</text>
<text x="60" y="218" fill="#9fc6bd" font-size="13">click_button / type_into /</text>
<text x="60" y="236" fill="#9fc6bd" font-size="13">key / scroll / drag / step</text>
<text x="60" y="262" fill="#7fa8b8" font-size="12">real AccessKit interactions →</text>
<text x="60" y="278" fill="#7fa8b8" font-size="12">the app mutates, frame steps</text>
<!-- Observable -->
<rect x="440" y="120" width="300" height="170" rx="12" fill="url(#observe)" stroke="#2b6a86"/>
<text x="460" y="150" fill="#e6f3ef" font-size="19" font-weight="bold">2 · OBSERVE</text>
<text x="460" y="178" fill="#bcdcd4" font-size="14">Observable::state_json()</text>
<text x="460" y="200" fill="#9fc6bd" font-size="13">the nordisk readable-data LAW —</text>
<text x="460" y="218" fill="#9fc6bd" font-size="13">same blob the viz dumps to</text>
<text x="460" y="236" fill="#9fc6bd" font-size="13">$NORNIR_VIZ_STATE</text>
<text x="460" y="262" fill="#7fa8b8" font-size="12">Assert::State{pointer,expected}</text>
<text x="460" y="278" fill="#7fa8b8" font-size="12">LabelVisible · Drew · Contains</text>
<!-- Matrix rows -->
<rect x="840" y="120" width="300" height="170" rx="12" fill="url(#emit)" stroke="#2f8a63"/>
<text x="860" y="150" fill="#e6f3ef" font-size="19" font-weight="bold">3 · EMIT</text>
<text x="860" y="178" fill="#bcdcd4" font-size="14">nornir-testmatrix rows</text>
<text x="860" y="200" fill="#9fc6bd" font-size="13">one Step → one TestResultRow</text>
<text x="860" y="218" fill="#9fc6bd" font-size="13">suite=<scenario> aspect=robot-ui</text>
<text x="860" y="236" fill="#9fc6bd" font-size="13">pass / fail per cell</text>
<text x="860" y="262" fill="#7fa8b8" font-size="12">→ any TestSink (JsonFile /</text>
<text x="860" y="278" fill="#7fa8b8" font-size="12">Iceberg warehouse)</text>
<!-- arrows between -->
<line x1="340" y1="205" x2="438" y2="205" stroke="#5fd0c0" stroke-width="3" marker-end="url(#arrow)"/>
<line x1="740" y1="205" x2="838" y2="205" stroke="#5fd0c0" stroke-width="3" marker-end="url(#arrow)"/>
<!-- scenario loop -->
<rect x="40" y="350" width="1100" height="150" rx="12" fill="#0c2436" stroke="#214a60"/>
<text x="60" y="382" fill="#e6f3ef" font-size="18" font-weight="bold">RobotSession::run_scenario(&Scenario) — one call drives every step → the matrix fills</text>
<text x="60" y="414" fill="#9fc6bd" font-size="14">for each Step { action, assert, label }: perform(action) → step() → check(assert against state_json) → push TestResultRow</text>
<!-- mini matrix cells -->
<g>
<rect x="60" y="436" width="150" height="42" rx="6" fill="#13402c" stroke="#2f8a63"/>
<text x="135" y="462" fill="#bfe9cf" font-size="13" text-anchor="middle">click DepGraph ✓</text>
<rect x="225" y="436" width="150" height="42" rx="6" fill="#13402c" stroke="#2f8a63"/>
<text x="300" y="462" fill="#bfe9cf" font-size="13" text-anchor="middle">click Release ✓</text>
<rect x="390" y="436" width="150" height="42" rx="6" fill="#13402c" stroke="#2f8a63"/>
<text x="465" y="462" fill="#bfe9cf" font-size="13" text-anchor="middle">click Test → rows ✓</text>
<rect x="555" y="436" width="150" height="42" rx="6" fill="#13402c" stroke="#2f8a63"/>
<text x="630" y="462" fill="#bfe9cf" font-size="13" text-anchor="middle">label visible ✓</text>
<rect x="720" y="436" width="150" height="42" rx="6" fill="#13402c" stroke="#2f8a63"/>
<text x="795" y="462" fill="#bfe9cf" font-size="13" text-anchor="middle">drew widgets ✓</text>
<rect x="885" y="436" width="255" height="42" rx="6" fill="#3a1414" stroke="#8a2f2f"/>
<text x="1012" y="462" fill="#e9bfbf" font-size="13" text-anchor="middle">wrong expectation → red cell ✗</text>
</g>
<text x="40" y="534" fill="#5e7f8f" font-size="12">reusable by: korp · facett-demo · mannequin · nornir's own viz (robot_viz reference test)</text>
</svg>