User scenarios in the real UI, headless: scenario::Harness draws the app frame by frame into an egui context and drives it with control-channel input (toolbar starts, clicks on world/sketch/origin-plane/axis points, keys, typing, drags) and checks the model; tests/scenarios/*.json: box with fillets, shell and hole; revolve on XZ; sketch on a face and cut; mirror; delete and undo. Control: ui.at, ui.dialogInput. Fixes found by them: a shape started on an existing point (the origin, a corner) is tied to it; the Dimension tool's value is edited in place with the value selected, so typing replaces it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
62dbf60eb2
commit
d5b8aa0375
12 files changed
+802
-6
No files matched your search
@@ -0,0 +1,25 @@
|
||||
//! User scenarios in the real UI, headless (see `solvecraft_ui_egui::scenario`). Each JSON file
|
||||
//! under `tests/scenarios/` is one workflow done with clicks, keys and drags.
|
||||
|
||||
use solvecraft_ui_egui::scenario::Harness;
|
||||
|
||||
fn run(name: &str) {
|
||||
let path = format!("{}/tests/scenarios/{name}.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let text = std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("{path}: {e}"));
|
||||
let steps: serde_json::Value = serde_json::from_str(&text).unwrap_or_else(|e| panic!("{path}: {e}"));
|
||||
let mut h = Harness::new();
|
||||
if let Err(e) = h.run(&steps) {
|
||||
panic!("{name}: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! scenarios {
|
||||
($($name:ident),* $(,)?) => {
|
||||
$(#[test]
|
||||
fn $name() {
|
||||
run(stringify!($name));
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
scenarios!(s01_box_fillet_hole_shell, s02_revolve_on_xz, s03_sketch_on_face_cut, s04_mirror_body, s05_delete_and_undo);
|
||||
@@ -0,0 +1,206 @@
|
||||
[
|
||||
{
|
||||
"start": "SketchCreate"
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"plane": "XY"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"sketching": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"start": "ShapeRectangleTwoPoint"
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"sketch": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"sketch": [
|
||||
40,
|
||||
30
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "Escape"
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"dof": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"start": "SketchDimension"
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"sketch": [
|
||||
20,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "50"
|
||||
},
|
||||
{
|
||||
"key": "Enter"
|
||||
},
|
||||
{
|
||||
"key": "Escape"
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"dialog": null,
|
||||
"param": {
|
||||
"d1": 50
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"shot": "s01_sketch"
|
||||
},
|
||||
{
|
||||
"call": "ui.view",
|
||||
"params": {
|
||||
"view": "iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"start": "SketchStop"
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"sketching": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"start": "Extrude"
|
||||
},
|
||||
{
|
||||
"text": "20"
|
||||
},
|
||||
{
|
||||
"key": "Enter"
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 1,
|
||||
"volume": 30000,
|
||||
"dialog": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"shot": "s01_extrude"
|
||||
},
|
||||
{
|
||||
"start": "FusionFilletEdgesCommand"
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"world": [
|
||||
50,
|
||||
15,
|
||||
20
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"world": [
|
||||
0,
|
||||
15,
|
||||
20
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "3"
|
||||
},
|
||||
{
|
||||
"key": "Enter"
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 1,
|
||||
"errors": 0,
|
||||
"dialog": null,
|
||||
"volume": [
|
||||
29884.1,
|
||||
1e-05
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"shot": "s01_fillet"
|
||||
},
|
||||
{
|
||||
"start": "FusionShellBodyCommand"
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"world": [
|
||||
25,
|
||||
0,
|
||||
10
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "2"
|
||||
},
|
||||
{
|
||||
"key": "Enter"
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 1,
|
||||
"errors": 0,
|
||||
"dialog": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"shot": "s01_shell"
|
||||
},
|
||||
{
|
||||
"start": "FusionHoleCommand"
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"world": [
|
||||
25,
|
||||
15,
|
||||
20
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "8"
|
||||
},
|
||||
{
|
||||
"key": "Enter"
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 1,
|
||||
"errors": 0,
|
||||
"dialog": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"debug": 1
|
||||
},
|
||||
{
|
||||
"shot": "s01_hole"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{"start": "SketchCreate"},
|
||||
{"click": {"plane": "XZ"}},
|
||||
{"expect": {"sketching": true}},
|
||||
{"start": "ShapeRectangleTwoPoint"},
|
||||
{"click": {"sketch": [10, 0]}},
|
||||
{"click": {"sketch": [20, 30]}},
|
||||
{"key": "Escape"},
|
||||
{"shot": "s02_sketch"},
|
||||
{"start": "SketchStop"},
|
||||
{"call": "ui.view", "params": {"view": "iso"}},
|
||||
{"start": "Revolve"},
|
||||
{"click": {"axis": "Z"}},
|
||||
{"debug": 1},
|
||||
{"key": "Enter"},
|
||||
{"expect": {"bodies": 1, "errors": 0, "dialog": null, "volume": [28274.33, 1e-3]}},
|
||||
{"shot": "s02_revolve"}
|
||||
]
|
||||
@@ -0,0 +1,30 @@
|
||||
[
|
||||
{"start": "SketchCreate"},
|
||||
{"click": {"plane": "XY"}},
|
||||
{"start": "ShapeRectangleTwoPoint"},
|
||||
{"click": {"sketch": [0, 0]}},
|
||||
{"click": {"sketch": [40, 30]}},
|
||||
{"key": "Escape"},
|
||||
{"start": "SketchStop"},
|
||||
{"call": "ui.view", "params": {"view": "iso"}},
|
||||
{"start": "Extrude"},
|
||||
{"text": "20"},
|
||||
{"key": "Enter"},
|
||||
{"expect": {"bodies": 1, "volume": 24000}},
|
||||
{"start": "SketchCreate"},
|
||||
{"click": {"world": [20, 15, 20]}},
|
||||
{"expect": {"sketching": true}},
|
||||
{"start": "CircleCenterRadius"},
|
||||
{"click": {"sketch": [20, 15]}},
|
||||
{"click": {"sketch": [25, 15]}},
|
||||
{"key": "Escape"},
|
||||
{"shot": "s03_sketch_on_face"},
|
||||
{"start": "SketchStop"},
|
||||
{"start": "Extrude"},
|
||||
{"click": {"world": [20, 15, 20]}},
|
||||
{"debug": 1},
|
||||
{"text": "-10"},
|
||||
{"key": "Enter"},
|
||||
{"expect": {"bodies": 1, "errors": 0, "dialog": null, "volume": [23214.6, 1e-4]}},
|
||||
{"shot": "s03_cut"}
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{"start": "SketchCreate"},
|
||||
{"click": {"plane": "XY"}},
|
||||
{"start": "CircleCenterRadius"},
|
||||
{"click": {"sketch": [20, 10]}},
|
||||
{"click": {"sketch": [25, 10]}},
|
||||
{"key": "Escape"},
|
||||
{"start": "SketchStop"},
|
||||
{"call": "ui.view", "params": {"view": "iso"}},
|
||||
{"start": "Extrude"},
|
||||
{"text": "10"},
|
||||
{"key": "Enter"},
|
||||
{"expect": {"bodies": 1}},
|
||||
{"start": "MirrorCommand"},
|
||||
{"click": {"world": [20, 10, 10]}},
|
||||
{"call": "ui.dialogInput", "params": {"index": 1}},
|
||||
{"click": {"plane": "YZ"}},
|
||||
{"debug": 1},
|
||||
{"key": "Enter"},
|
||||
{"expect": {"bodies": 2, "errors": 0, "dialog": null, "volume": [1570.8, 1e-3]}},
|
||||
{"shot": "s04_mirror"}
|
||||
]
|
||||
@@ -0,0 +1,131 @@
|
||||
[
|
||||
{
|
||||
"start": "SketchCreate"
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"plane": "XY"
|
||||
}
|
||||
},
|
||||
{
|
||||
"start": "ShapeRectangleTwoPoint"
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"sketch": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"sketch": [
|
||||
30,
|
||||
20
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "Escape"
|
||||
},
|
||||
{
|
||||
"start": "SketchStop"
|
||||
},
|
||||
{
|
||||
"call": "ui.view",
|
||||
"params": {
|
||||
"view": "iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"start": "Extrude"
|
||||
},
|
||||
{
|
||||
"text": "10"
|
||||
},
|
||||
{
|
||||
"key": "Enter"
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 1,
|
||||
"volume": 6000
|
||||
}
|
||||
},
|
||||
{
|
||||
"click": {
|
||||
"world": [
|
||||
15,
|
||||
10,
|
||||
10
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"selection": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"selection": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"call": "ui.menu",
|
||||
"params": {
|
||||
"x": 100,
|
||||
"y": 260,
|
||||
"target": {
|
||||
"type": "body",
|
||||
"name": "Body1"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"call": "ui.menuPick",
|
||||
"params": {
|
||||
"item": "Delete"
|
||||
}
|
||||
},
|
||||
{
|
||||
"debug": 1
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "Z",
|
||||
"cmd": true
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 1,
|
||||
"volume": 6000
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "Y",
|
||||
"cmd": true
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "Z",
|
||||
"cmd": true
|
||||
},
|
||||
{
|
||||
"expect": {
|
||||
"bodies": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"shot": "s05_undone"
|
||||
}
|
||||
]
|
||||
Reference in new issue
Block a user