Skip to content

Commit 2c07f2a

Browse files
authored
test: add compact option to plan snapshot tests (#174)
## Summary - Add `compact: bool` field to `[[plan]]` in plan snapshot test config - When enabled, snapshots only show the graph topology (`"relative_path#task_name" → [neighbors]`), omitting execution details like spawn commands, env vars, and cache metadata - Nodes with nested `Expanded` items include an `items` array of sub-graphs - Enable compact mode on 3 existing test cases that only verify graph structure: `nested-tasks`, `pnpm-workspace-packages-optional`, `vpr-shorthand` ## Test plan - [x] `cargo test -p vite_task_plan --test plan_snapshots` passes - [x] `cargo clippy -p vite_task_plan --test plan_snapshots -- -D warnings` passes - [x] Compact snapshots show correct graph structure - [x] Non-compact snapshots unchanged 🤖 Generated with [Claude Code](https://claude.com/claude-code)
1 parent 97e7aac commit 2c07f2a

File tree

7 files changed

+103
-196
lines changed

7 files changed

+103
-196
lines changed

crates/vite_task_plan/tests/plan_snapshots/fixtures/nested-tasks/snapshots.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
[[plan]]
44
name = "nested vp run"
55
args = ["run", "script2"]
6+
compact = true
Lines changed: 8 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,15 @@
11
---
22
source: crates/vite_task_plan/tests/plan_snapshots/main.rs
3-
expression: "&plan_json"
3+
expression: "&compact_plan"
44
input_file: crates/vite_task_plan/tests/plan_snapshots/fixtures/nested-tasks
55
---
6-
[
7-
{
8-
"key": [
9-
"<workspace>/",
10-
"script2"
6+
{
7+
"#script2": {
8+
"items": [
9+
{
10+
"#script1": []
11+
}
1112
],
12-
"node": {
13-
"task_display": {
14-
"package_name": "",
15-
"task_name": "script2",
16-
"package_path": "<workspace>/"
17-
},
18-
"items": [
19-
{
20-
"execution_item_display": {
21-
"task_display": {
22-
"package_name": "",
23-
"task_name": "script2",
24-
"package_path": "<workspace>/"
25-
},
26-
"command": "vp run script1",
27-
"and_item_index": null,
28-
"cwd": "<workspace>/"
29-
},
30-
"kind": {
31-
"Expanded": [
32-
{
33-
"key": [
34-
"<workspace>/",
35-
"script1"
36-
],
37-
"node": {
38-
"task_display": {
39-
"package_name": "",
40-
"task_name": "script1",
41-
"package_path": "<workspace>/"
42-
},
43-
"items": [
44-
{
45-
"execution_item_display": {
46-
"task_display": {
47-
"package_name": "",
48-
"task_name": "script1",
49-
"package_path": "<workspace>/"
50-
},
51-
"command": "echo hello",
52-
"and_item_index": null,
53-
"cwd": "<workspace>/"
54-
},
55-
"kind": {
56-
"Leaf": {
57-
"InProcess": {
58-
"kind": {
59-
"Echo": {
60-
"strings": [
61-
"hello"
62-
],
63-
"trailing_newline": true
64-
}
65-
}
66-
}
67-
}
68-
}
69-
}
70-
]
71-
},
72-
"neighbors": []
73-
}
74-
]
75-
}
76-
}
77-
]
78-
},
7913
"neighbors": []
8014
}
81-
]
15+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[[plan]]
22
name = "allow `packages` in pnpm-workspace.yaml to be optional"
33
args = ["run", "hello"]
4+
compact = true
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,8 @@
11
---
22
source: crates/vite_task_plan/tests/plan_snapshots/main.rs
3-
expression: "&plan_json"
3+
expression: "&compact_plan"
44
input_file: crates/vite_task_plan/tests/plan_snapshots/fixtures/pnpm-workspace-packages-optional
55
---
6-
[
7-
{
8-
"key": [
9-
"<workspace>/",
10-
"hello"
11-
],
12-
"node": {
13-
"task_display": {
14-
"package_name": "additional-envs",
15-
"task_name": "hello",
16-
"package_path": "<workspace>/"
17-
},
18-
"items": [
19-
{
20-
"execution_item_display": {
21-
"task_display": {
22-
"package_name": "additional-envs",
23-
"task_name": "hello",
24-
"package_path": "<workspace>/"
25-
},
26-
"command": "echo hello",
27-
"and_item_index": null,
28-
"cwd": "<workspace>/"
29-
},
30-
"kind": {
31-
"Leaf": {
32-
"InProcess": {
33-
"kind": {
34-
"Echo": {
35-
"strings": [
36-
"hello"
37-
],
38-
"trailing_newline": true
39-
}
40-
}
41-
}
42-
}
43-
}
44-
}
45-
]
46-
},
47-
"neighbors": []
48-
}
49-
]
6+
{
7+
"#hello": []
8+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[[plan]]
22
name = "vpr expands to vp run"
33
args = ["run", "all"]
4+
compact = true
Lines changed: 8 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,15 @@
11
---
22
source: crates/vite_task_plan/tests/plan_snapshots/main.rs
3-
expression: "&plan_json"
3+
expression: "&compact_plan"
44
input_file: crates/vite_task_plan/tests/plan_snapshots/fixtures/vpr-shorthand
55
---
6-
[
7-
{
8-
"key": [
9-
"<workspace>/",
10-
"all"
6+
{
7+
"#all": {
8+
"items": [
9+
{
10+
"#build": []
11+
}
1112
],
12-
"node": {
13-
"task_display": {
14-
"package_name": "",
15-
"task_name": "all",
16-
"package_path": "<workspace>/"
17-
},
18-
"items": [
19-
{
20-
"execution_item_display": {
21-
"task_display": {
22-
"package_name": "",
23-
"task_name": "all",
24-
"package_path": "<workspace>/"
25-
},
26-
"command": "vpr build",
27-
"and_item_index": null,
28-
"cwd": "<workspace>/"
29-
},
30-
"kind": {
31-
"Expanded": [
32-
{
33-
"key": [
34-
"<workspace>/",
35-
"build"
36-
],
37-
"node": {
38-
"task_display": {
39-
"package_name": "",
40-
"task_name": "build",
41-
"package_path": "<workspace>/"
42-
},
43-
"items": [
44-
{
45-
"execution_item_display": {
46-
"task_display": {
47-
"package_name": "",
48-
"task_name": "build",
49-
"package_path": "<workspace>/"
50-
},
51-
"command": "echo building",
52-
"and_item_index": null,
53-
"cwd": "<workspace>/"
54-
},
55-
"kind": {
56-
"Leaf": {
57-
"InProcess": {
58-
"kind": {
59-
"Echo": {
60-
"strings": [
61-
"building"
62-
],
63-
"trailing_newline": true
64-
}
65-
}
66-
}
67-
}
68-
}
69-
}
70-
]
71-
},
72-
"neighbors": []
73-
}
74-
]
75-
}
76-
}
77-
]
78-
},
7913
"neighbors": []
8014
}
81-
]
15+
}

crates/vite_task_plan/tests/plan_snapshots/main.rs

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
mod redact;
22

3-
use std::{ffi::OsStr, sync::Arc};
3+
use std::{
4+
collections::{BTreeMap, BTreeSet},
5+
ffi::OsStr,
6+
sync::Arc,
7+
};
48

59
use clap::Parser;
610
use copy_dir::copy_dir;
711
use cow_utils::CowUtils as _;
812
use redact::redact_snapshot;
913
use rustc_hash::FxHashMap;
14+
use serde::Serialize;
1015
use tokio::runtime::Runtime;
1116
use vite_path::{AbsolutePath, AbsolutePathBuf, RelativePathBuf};
1217
use vite_str::Str;
1318
use vite_task::{Command, Session};
19+
use vite_task_graph::display::TaskDisplay;
20+
use vite_task_plan::{ExecutionGraph, ExecutionItemKind};
1421
use vite_workspace::find_workspace_root;
1522

1623
/// Local parser wrapper for `BuiltInCommand`
@@ -27,6 +34,8 @@ struct Plan {
2734
pub args: Vec<Str>,
2835
#[serde(default)]
2936
pub cwd: RelativePathBuf,
37+
#[serde(default)]
38+
pub compact: bool,
3039
}
3140

3241
#[derive(serde::Deserialize, Default)]
@@ -35,6 +44,68 @@ struct SnapshotsFile {
3544
pub plan_cases: Vec<Plan>,
3645
}
3746

47+
/// Compact plan: maps `"relative_path#task_name"` to either just neighbors (simple)
48+
/// or `{ items, neighbors }` when the node has nested `Expanded` execution items.
49+
#[derive(Serialize)]
50+
#[serde(transparent)]
51+
struct CompactPlan(BTreeMap<Str, CompactNode>);
52+
53+
/// Untagged enum so simple nodes serialize as just an array, and nodes with
54+
/// expanded items serialize as `{ "items": [...], "neighbors": [...] }`.
55+
#[derive(Serialize)]
56+
#[serde(untagged)]
57+
enum CompactNode {
58+
/// No nested `Expanded` items — just the neighbor list
59+
Simple(BTreeSet<Str>),
60+
/// Has nested `Expanded` items
61+
WithItems { items: Vec<CompactPlan>, neighbors: BTreeSet<Str> },
62+
}
63+
64+
impl CompactPlan {
65+
fn from_execution_graph(graph: &ExecutionGraph, workspace_root: &AbsolutePath) -> Self {
66+
use petgraph::visit::EdgeRef as _;
67+
let mut map = BTreeMap::<Str, CompactNode>::new();
68+
for node_idx in graph.node_indices() {
69+
let node = &graph[node_idx];
70+
let key = Self::task_key(&node.task_display, workspace_root);
71+
72+
let neighbors: BTreeSet<Str> = graph
73+
.edges(node_idx)
74+
.map(|edge| Self::task_key(&graph[edge.target()].task_display, workspace_root))
75+
.collect();
76+
77+
let expanded_items: Vec<Self> = node
78+
.items
79+
.iter()
80+
.filter_map(|item| {
81+
if let ExecutionItemKind::Expanded(sub_graph) = &item.kind {
82+
Some(Self::from_execution_graph(sub_graph, workspace_root))
83+
} else {
84+
None
85+
}
86+
})
87+
.collect();
88+
89+
let compact_node = if expanded_items.is_empty() {
90+
CompactNode::Simple(neighbors)
91+
} else {
92+
CompactNode::WithItems { items: expanded_items, neighbors }
93+
};
94+
map.insert(key, compact_node);
95+
}
96+
Self(map)
97+
}
98+
99+
fn task_key(task_display: &TaskDisplay, workspace_root: &AbsolutePath) -> Str {
100+
let relative = task_display
101+
.package_path
102+
.strip_prefix(workspace_root)
103+
.expect("strip_prefix should not produce invalid path data")
104+
.expect("package_path must be under workspace_root");
105+
vite_str::format!("{}#{}", relative, task_display.task_name)
106+
}
107+
}
108+
38109
#[expect(clippy::disallowed_types, reason = "Path required by insta::glob! callback signature")]
39110
fn run_case(
40111
runtime: &Runtime,
@@ -157,6 +228,7 @@ fn run_case_inner(
157228

158229
for plan in cases_file.plan_cases {
159230
let snapshot_name = vite_str::format!("query - {}", plan.name);
231+
let compact = plan.compact;
160232

161233
let cli = match Cli::try_parse_from(
162234
std::iter::once("vp") // dummy program name
@@ -208,8 +280,13 @@ fn run_case_inner(
208280
}
209281
};
210282

211-
let plan_json = redact_snapshot(&plan, workspace_root_str);
212-
insta::assert_json_snapshot!(snapshot_name.as_str(), &plan_json);
283+
if compact {
284+
let compact_plan = CompactPlan::from_execution_graph(&plan, &workspace_root.path);
285+
insta::assert_json_snapshot!(snapshot_name.as_str(), &compact_plan);
286+
} else {
287+
let plan_json = redact_snapshot(&plan, workspace_root_str);
288+
insta::assert_json_snapshot!(snapshot_name.as_str(), &plan_json);
289+
}
213290
}
214291
});
215292
}

0 commit comments

Comments
 (0)