Skip to content

Commit b633045

Browse files
CI: remove suite asserts codes, not sentences (#1089) (#1535)
* Start #1089 child 1: remove suite asserts codes Assisted-by: Claude Code:claude-opus-5-5 * Remove suite asserts codes, not sentences The remove failure-path tests pinned whole English sentences in --json mode and kept private copies of the envelope readers, so a copy edit to a remove message broke them even when the exit code, error code, events and bytes on disk were unchanged. The --json tests now read the envelope through common::envelope and check error codes, events, summary counts and on-disk state. Where a message must name something, they check that token (a purl, a flag, a path). Human-mode tests stay as the render checks, minus lines whose disk state is asserted already. common::envelope gains event_purls, and the file moves into the remove suite as remove_failure_paths.rs. Refs #1089. Assisted-by: Claude Code:claude-opus-5-5 * Share has_event; keep remedy and promise checks Review follow-ups on the remove suite rewrite: - has_event moves into common::envelope next to event_purls, with self-tests (including a non-string purl) and a ratchet entry. - The hosted refusal again checks the `git checkout --` remedy, and the vendor flavor refusal the "manifest was not modified" promise. - The mixed drift-keep human test checks the manifest on disk, since it no longer reads the "Removed 1 patch" line. - The --json preserve-state leg checks for no `Note:` line on stderr instead of the note's wording. - The module doc says which message parts the --json tests still read. Assisted-by: Claude Code:claude-opus-5-5 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9a5929a commit b633045

4 files changed

Lines changed: 151 additions & 141 deletions

File tree

‎crates/socket-patch-cli/tests/cli/envelope_helper_copies.rs‎

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ use std::path::Path;
1010
use serde_json::{json, Value};
1111

1212
use crate::common::envelope::{
13-
all_codes, codes_in, event_codes, event_triples, events, find_event, parse_json_envelope,
13+
all_codes, codes_in, event_codes, event_purls, event_triples, events, find_event, has_event,
14+
parse_json_envelope,
1415
};
1516

1617
/// Files that still define a private envelope reader. Each is changed by an
@@ -40,7 +41,6 @@ const PENDING_PRIVATE_READERS: &[&str] = &[
4041
"vendor_jvm_cli.rs",
4142
"e2e_vex_lockfile/cargo.rs",
4243
"in_process_vendor_bun_takeover/vlt.rs",
43-
"remove/covgap_commands_remove.rs",
4444
"scan/scan_paths_e2e.rs",
4545
"vlt_hosted_common/mod.rs",
4646
"vlt_vendor_common/mod.rs",
@@ -54,6 +54,8 @@ const READER_NAMES: &[&str] = &[
5454
"parse_json_envelope",
5555
"event_codes",
5656
"event_triples",
57+
"event_purls",
58+
"has_event",
5759
"warning_codes",
5860
"codes",
5961
"all_codes",
@@ -138,6 +140,7 @@ fn the_detector_sees_every_former_copy_shape() {
138140
"pub fn codes(env: &Value) -> Vec<String> {",
139141
"fn warning_codes(doc: &Value) -> Vec<&str> {",
140142
"fn event_codes(v: &Value) -> Vec<String> {",
143+
"fn event_purls(v: &serde_json::Value, action: &str) -> Vec<String> {",
141144
] {
142145
assert!(defines_private_reader(copy), "missed: {copy}");
143146
}
@@ -234,6 +237,46 @@ fn event_triples_fill_absent_fields_with_empty_strings() {
234237
);
235238
}
236239

240+
#[test]
241+
fn event_purls_lists_the_string_purls_of_one_action() {
242+
let env = sample();
243+
assert_eq!(event_purls(&env, "vendored"), ["pkg:npm/a@1.0.0"]);
244+
// The `skipped` event has no purl, so it lists nothing.
245+
assert!(event_purls(&env, "skipped").is_empty());
246+
assert!(event_purls(&env, "removed").is_empty());
247+
// A null or numeric purl is not listed as text.
248+
let odd = json!({"events": [
249+
{"action": "removed", "purl": null},
250+
{"action": "removed", "purl": 7},
251+
{"action": "removed", "purl": "pkg:npm/c@1.0.0"},
252+
]});
253+
assert_eq!(event_purls(&odd, "removed"), ["pkg:npm/c@1.0.0"]);
254+
}
255+
256+
#[test]
257+
fn has_event_needs_action_code_and_purl_to_match() {
258+
let env = sample();
259+
assert!(has_event(
260+
&env,
261+
"failed",
262+
"vendor_lock_drift",
263+
"pkg:npm/b@1.0.0"
264+
));
265+
assert!(!has_event(
266+
&env,
267+
"failed",
268+
"vendor_lock_drift",
269+
"pkg:npm/a@1.0.0"
270+
));
271+
assert!(!has_event(
272+
&env,
273+
"skipped",
274+
"vendor_lock_drift",
275+
"pkg:npm/b@1.0.0"
276+
));
277+
assert!(!has_event(&env, "vendored", "", "pkg:npm/a@1.0.0"));
278+
}
279+
237280
#[test]
238281
fn codes_in_reads_any_warnings_array_and_skips_non_strings() {
239282
let env = sample();

‎crates/socket-patch-cli/tests/common/envelope.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,22 @@ pub fn event_triples(envelope: &Value) -> Vec<(String, String, String)> {
6464
.collect()
6565
}
6666

67+
/// Whether some `action` event for `purl` has `errorCode == code`.
68+
pub fn has_event(envelope: &Value, action: &str, code: &str, purl: &str) -> bool {
69+
events(envelope)
70+
.iter()
71+
.any(|e| e["action"] == action && e["errorCode"] == code && e["purl"] == purl)
72+
}
73+
74+
/// The string `purl` of every `action` event, in order.
75+
pub fn event_purls(envelope: &Value, action: &str) -> Vec<String> {
76+
events(envelope)
77+
.iter()
78+
.filter(|e| e["action"] == action)
79+
.filter_map(|e| e["purl"].as_str().map(str::to_string))
80+
.collect()
81+
}
82+
6783
/// The `errorCode` of every event that has one; empty when `events` is
6884
/// missing.
6985
pub fn event_codes(envelope: &Value) -> Vec<String> {

‎crates/socket-patch-cli/tests/remove/main.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ mod vlt_hosted_common;
1313
#[path = "../vlt_hosted_common/vendored.rs"]
1414
mod vlt_vendored;
1515

16-
mod covgap_commands_remove;
1716
mod pypi_name_spellings;
1817
mod remove_duality_invariants;
18+
mod remove_failure_paths;
1919
mod remove_invariants;
2020
mod remove_network;

0 commit comments

Comments
 (0)