#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::needless_raw_string_hashes,
clippy::duration_suboptimal_units,
clippy::branches_sharing_code,
clippy::used_underscore_binding,
clippy::single_char_pattern,
clippy::ignore_without_reason,
clippy::cloned_ref_to_slice_refs,
clippy::doc_overindented_list_items,
clippy::match_wildcard_for_single_variants,
clippy::ignored_unit_patterns,
clippy::needless_collect,
clippy::unnecessary_map_or,
clippy::manual_flatten,
clippy::manual_strip,
clippy::future_not_send,
clippy::unnested_or_patterns,
clippy::no_effect_underscore_binding,
clippy::literal_string_with_formatting_args
)]
#![cfg(feature = "integration")]
use assert_cmd::Command;
use predicates::prelude::*;
use serde_json::Value;
use std::fs::{self, File};
use std::io::Write;
use std::path::{Path, PathBuf};
use tempfile::TempDir;
fn ggen() -> Command {
Command::cargo_bin("ggen").expect("Failed to find ggen binary")
}
fn create_test_pack_metadata(pack_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
let metadata = r#"{
"id": "test-pack",
"name": "Test Pack",
"version": "1.0.0",
"description": "A test pack for E2E testing",
"category": "test",
"packages": [],
"templates": [],
"trust_tier": "trusted",
"signature": null
}"#;
fs::create_dir_all(pack_dir)?;
let metadata_path = pack_dir.join("metadata.json");
let mut file = File::create(metadata_path)?;
file.write_all(metadata.as_bytes())?;
Ok(())
}
fn create_test_lockfile(lockfile_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
let lockfile_content = r#"{
"version": "6.0.1",
"packs": {
"surface-mcp": {
"version": "1.0.0",
"source": {
"type": "Registry",
"url": "https://registry.ggen.io"
},
"integrity": null,
"installed_at": "2024-01-01T00:00:00Z",
"dependencies": []
}
},
"updated_at": "2024-01-01T00:00:00Z",
"ggen_version": "6.0.1"
}"#;
if let Some(parent) = lockfile_path.parent() {
fs::create_dir_all(parent)?;
}
let mut file = File::create(lockfile_path)?;
file.write_all(lockfile_content.as_bytes())?;
Ok(())
}
fn create_test_receipt(receipt_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
let receipt_content = r#"{
"operation_id": "test-op-123",
"operation_type": "pack_install",
"timestamp": "2024-01-01T00:00:00Z",
"input_hashes": ["abc123"],
"output_hashes": ["def456"],
"signature": "test_signature"
}"#;
if let Some(parent) = receipt_path.parent() {
fs::create_dir_all(parent)?;
}
let mut file = File::create(receipt_path)?;
file.write_all(receipt_content.as_bytes())?;
Ok(())
}
fn parse_json(output: &str) -> Result<Value, Box<dyn std::error::Error>> {
Ok(serde_json::from_str(output)?)
}
fn verify_lockfile_structure(lockfile_path: &Path) -> Result<bool, Box<dyn std::error::Error>> {
if !lockfile_path.exists() {
return Ok(false);
}
let content = fs::read_to_string(lockfile_path)?;
let json: Value = serde_json::from_str(&content)?;
Ok(json.get("packs").is_some()
&& json.get("updated_at").is_some()
&& json.get("ggen_version").is_some())
}
fn count_lockfile_packs(lockfile_path: &Path) -> Result<usize, Box<dyn std::error::Error>> {
let content = fs::read_to_string(lockfile_path)?;
let json: Value = serde_json::from_str(&content)?;
if let Some(packs) = json.get("packs") {
if let Some(obj) = packs.as_object() {
return Ok(obj.len());
}
}
Ok(0)
}
#[test]
fn test_pack_install_creates_lockfile() {
println!("🔍 E2E Test: Pack installation creates lockfile");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
assert!(
lockfile_path.exists(),
"Lockfile should be created at {}",
lockfile_path.display()
);
assert!(
verify_lockfile_structure(&lockfile_path).unwrap(),
"Lockfile should have valid structure"
);
println!("✅ Test PASSED: Lockfile created successfully");
}
#[test]
fn test_pack_install_tracks_packs() {
println!("🔍 E2E Test: Pack installation tracks packs in lockfile");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
let pack_count = count_lockfile_packs(&lockfile_path).unwrap();
assert_eq!(
pack_count, 1,
"Lockfile should contain exactly 1 pack, found {}",
pack_count
);
let content = fs::read_to_string(&lockfile_path).unwrap();
let json: Value = serde_json::from_str(&content).unwrap();
assert!(
json["packs"].get("surface-mcp").is_some(),
"Lockfile should contain surface-mcp pack"
);
println!("✅ Test PASSED: Pack tracked in lockfile");
}
#[test]
fn test_pack_install_returns_valid_json() {
println!("🔍 E2E Test: Pack installation returns valid JSON");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert!(json.get("pack_id").is_some(), "Should have pack_id field");
assert!(json.get("status").is_some(), "Should have status field");
assert_eq!(
json["pack_id"], "surface-mcp",
"Should report correct pack_id"
);
println!("✅ Test PASSED: Valid JSON output");
}
#[test]
fn test_pack_install_fails_on_unknown_pack() {
println!("🔍 E2E Test: Pack installation fails gracefully for unknown pack");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("pack")
.arg("add")
.arg("unknown-pack-xyz")
.current_dir(&temp_dir)
.assert();
result.success();
println!("✅ Test PASSED: Graceful error handling");
}
#[test]
fn test_pack_list_shows_installed_packs() {
println!("🔍 E2E Test: Pack list shows available packs");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("pack")
.arg("list")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert!(json.get("packs").is_some(), "Should have packs field");
assert!(json.get("total").is_some(), "Should have total field");
assert!(json["packs"].is_array(), "packs should be an array");
println!("✅ Test PASSED: Pack list works");
}
#[test]
#[ignore = "Live `pack` noun has NO `validate` verb (only `policy validate` exists, crates/ggen-cli/src/cmds/policy.rs). Intent (validate a pack by id) is impossible on the current CLI; noun migrated packs->pack but verb has no live target."]
fn test_pack_validate_checks_pack() {
println!("🔍 E2E Test: Pack validation works");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("pack")
.arg("validate")
.arg("--pack_id")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert_eq!(
json["pack_id"], "surface-mcp",
"Should validate correct pack"
);
assert!(
json.get("is_valid").is_some(),
"Should have validation status"
);
println!("✅ Test PASSED: Pack validation works");
}
#[test]
#[ignore = "No `capability` noun exists on the live CLI (not registered in crates/ggen-cli/src/cmds/mod.rs). Intent (enable capability -> atomic packs) is impossible on the current CLI."]
fn test_capability_enable_expands_to_atomic_packs() {
println!("🔍 E2E Test: Capability enable expands to atomic packs");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("capability")
.arg("enable")
.arg("mcp")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert_eq!(json["capability"], "mcp", "Should enable mcp capability");
assert!(
json.get("atomic_packs").is_some(),
"Should list atomic packs"
);
assert!(
json["atomic_packs"].is_array(),
"atomic_packs should be array"
);
let atomic_packs = json["atomic_packs"].as_array().unwrap();
assert!(
!atomic_packs.is_empty(),
"atomic_packs should contain at least one pack"
);
println!("✅ Test PASSED: Capability expanded to atomic packs");
}
#[test]
#[ignore = "No `capability` noun exists on the live CLI (crates/ggen-cli/src/cmds/mod.rs). Intent (capability enable --projection) is impossible on the current CLI."]
fn test_capability_enable_with_projection() {
println!("🔍 E2E Test: Capability enable with projection parameter");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("capability")
.arg("enable")
.arg("mcp")
.arg("--projection")
.arg("rust")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert_eq!(
json["projection"],
serde_json::json!("rust"),
"Should have projection set to rust"
);
let atomic_packs = json["atomic_packs"].as_array().unwrap();
let has_projection_pack = atomic_packs
.iter()
.any(|pack| pack.as_str().unwrap().contains("projection"));
assert!(
has_projection_pack,
"atomic_packs should include projection pack"
);
println!("✅ Test PASSED: Projection parameter works");
}
#[test]
#[ignore = "No `capability` noun exists on the live CLI (crates/ggen-cli/src/cmds/mod.rs). Intent (capability enable updates lockfile) is impossible on the current CLI."]
fn test_capability_enable_updates_lockfile() {
println!("🔍 E2E Test: Capability enable updates lockfile");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
create_test_lockfile(&lockfile_path).unwrap();
ggen()
.arg("capability")
.arg("enable")
.arg("mcp")
.current_dir(&temp_dir)
.assert()
.success();
assert!(
lockfile_path.exists(),
"Lockfile should exist after capability enable"
);
assert!(
verify_lockfile_structure(&lockfile_path).unwrap(),
"Lockfile should remain valid"
);
println!("✅ Test PASSED: Lockfile updated after capability enable");
}
#[test]
#[ignore = "No `capability` noun exists on the live CLI (crates/ggen-cli/src/cmds/mod.rs). Intent (capability list) is impossible on the current CLI."]
fn test_capability_list_shows_capabilities() {
println!("🔍 E2E Test: Capability list works");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("capability")
.arg("list")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert!(
json.get("capabilities").is_some(),
"Should have capabilities"
);
assert!(json.get("total").is_some(), "Should have total");
assert!(
json["capabilities"].is_array(),
"capabilities should be array"
);
println!("✅ Test PASSED: Capability list works");
}
#[test]
#[ignore = "No `capability` noun exists on the live CLI (crates/ggen-cli/src/cmds/mod.rs). Intent (capability inspect) is impossible on the current CLI."]
fn test_capability_inspect_shows_details() {
println!("🔍 E2E Test: Capability inspect shows details");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("capability")
.arg("inspect")
.arg("mcp")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert_eq!(
json["capability"], "mcp",
"Should inspect correct capability"
);
assert!(
json.get("atomic_packs").is_some(),
"Should list atomic packs"
);
println!("✅ Test PASSED: Capability inspect works");
}
#[test]
fn test_lockfile_created_after_pack_install() {
println!("🔍 E2E Test: Lockfile created after pack install");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
assert!(
lockfile_path.exists(),
"Lockfile should be created at {}",
lockfile_path.display()
);
assert!(
temp_dir.path().join(".ggen").exists(),
".ggen directory should exist"
);
println!("✅ Test PASSED: Lockfile created");
}
#[test]
#[ignore = "Depends on the non-existent `capability list` noun (crates/ggen-cli/src/cmds/mod.rs). `packs list` was migrated to `pack list`, but the capability step cannot run on the current CLI."]
fn test_lockfile_persists_across_commands() {
println!("🔍 E2E Test: Lockfile persists across commands");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
create_test_lockfile(&lockfile_path).unwrap();
ggen()
.arg("pack")
.arg("list")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("capability")
.arg("list")
.current_dir(&temp_dir)
.assert()
.success();
assert!(
lockfile_path.exists(),
"Lockfile should persist across commands"
);
println!("✅ Test PASSED: Lockfile persists");
}
#[test]
fn test_lockfile_format_is_valid() {
println!("🔍 E2E Test: Lockfile format is valid JSON");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
let content = fs::read_to_string(&lockfile_path).expect("Failed to read lockfile");
let json: Value = parse_json(&content).expect("Lockfile should be valid JSON");
assert!(json.get("version").is_some(), "Should have version");
assert!(json.get("packs").is_some(), "Should have packs");
assert!(json["packs"].is_object(), "packs should be object");
assert!(json.get("updated_at").is_some(), "Should have updated_at");
assert!(
json.get("ggen_version").is_some(),
"Should have ggen_version"
);
println!("✅ Test PASSED: Lockfile format valid");
}
#[test]
fn test_lockfile_tracks_multiple_packs() {
println!("🔍 E2E Test: Lockfile tracks multiple packs");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("pack")
.arg("add")
.arg("projection-rust")
.current_dir(&temp_dir)
.assert()
.success();
let pack_count = count_lockfile_packs(&lockfile_path).unwrap();
assert_eq!(
pack_count, 2,
"Lockfile should contain 2 packs, found {}",
pack_count
);
println!("✅ Test PASSED: Multiple packs tracked");
}
#[test]
fn test_lockfile_reproducibility() {
println!("🔍 E2E Test: Lockfile ensures reproducibility");
let temp_dir1 = TempDir::new().unwrap();
let temp_dir2 = TempDir::new().unwrap();
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir1)
.assert()
.success();
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir2)
.assert()
.success();
let lockfile1 = temp_dir1.path().join(".ggen/packs.lock");
let lockfile2 = temp_dir2.path().join(".ggen/packs.lock");
assert!(lockfile1.exists() && lockfile2.exists());
let content1 = fs::read_to_string(&lockfile1).unwrap();
let content2 = fs::read_to_string(&lockfile2).unwrap();
let json1: Value = parse_json(&content1).unwrap();
let json2: Value = parse_json(&content2).unwrap();
assert!(
json1["packs"].get("surface-mcp").is_some(),
"First lockfile should contain surface-mcp"
);
assert!(
json2["packs"].get("surface-mcp").is_some(),
"Second lockfile should contain surface-mcp"
);
println!("✅ Test PASSED: Lockfile ensures reproducibility");
}
#[test]
fn test_receipt_generated_after_pack_install() {
println!("🔍 E2E Test: Receipt generated after pack install");
let temp_dir = TempDir::new().unwrap();
let receipts_dir = temp_dir.path().join(".ggen/receipts");
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
assert!(
receipts_dir.exists(),
"Receipts directory should exist at {}",
receipts_dir.display()
);
let receipt_files: Vec<_> = fs::read_dir(&receipts_dir)
.unwrap()
.filter_map(|entry| entry.ok())
.filter(|entry| {
entry
.path()
.extension()
.map(|ext| ext == "json")
.unwrap_or(false)
})
.collect();
assert!(
!receipt_files.is_empty(),
"At least one receipt file should exist"
);
println!("✅ Test PASSED: Receipt generated");
}
#[test]
fn test_receipt_verify_works() {
println!("🔍 E2E Test: Receipt verification works");
let temp_dir = TempDir::new().unwrap();
let receipt_path = temp_dir.path().join("receipt.json");
create_test_receipt(&receipt_path).unwrap();
ggen()
.arg("receipt")
.arg("verify")
.arg("--receipt_file")
.arg(receipt_path.to_str().unwrap())
.current_dir(&temp_dir)
.assert()
.success();
println!("✅ Test PASSED: Receipt verify command works");
}
#[test]
fn test_receipt_info_shows_details() {
println!("🔍 E2E Test: Receipt info shows details");
let temp_dir = TempDir::new().unwrap();
let receipt_path = temp_dir.path().join("receipt.json");
create_test_receipt(&receipt_path).unwrap();
let result = ggen()
.arg("receipt")
.arg("info")
.arg("--receipt_file")
.arg(receipt_path.to_str().unwrap())
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert!(
json.get("operation_id").is_some(),
"Should have operation_id"
);
assert!(json.get("timestamp").is_some(), "Should have timestamp");
println!("✅ Test PASSED: Receipt info works");
}
#[test]
fn test_receipt_format_is_valid() {
println!("🔍 E2E Test: Receipt format is valid JSON");
let temp_dir = TempDir::new().unwrap();
let receipts_dir = temp_dir.path().join(".ggen/receipts");
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
let receipt_files: Vec<_> = fs::read_dir(&receipts_dir)
.unwrap()
.filter_map(|entry| entry.ok())
.filter(|entry| {
entry
.path()
.extension()
.map(|ext| ext == "json")
.unwrap_or(false)
})
.collect();
assert!(!receipt_files.is_empty(), "Should have receipt files");
let receipt_path = receipt_files[0].path();
let content = fs::read_to_string(&receipt_path).expect("Failed to read receipt");
let json: Value = parse_json(&content).expect("Receipt should be valid JSON");
assert!(
json.get("operation_id").is_some(),
"Should have operation_id"
);
assert!(json.get("timestamp").is_some(), "Should have timestamp");
assert!(
json.get("input_hashes").is_some(),
"Should have input_hashes"
);
assert!(
json.get("output_hashes").is_some(),
"Should have output_hashes"
);
println!("✅ Test PASSED: Receipt format valid");
}
#[test]
fn test_receipt_chain_verification() {
println!("🔍 E2E Test: Receipt chain verification works");
let temp_dir = TempDir::new().unwrap();
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("pack")
.arg("add")
.arg("projection-rust")
.current_dir(&temp_dir)
.assert()
.success();
let receipts_dir = temp_dir.path().join(".ggen/receipts");
let receipt_count = fs::read_dir(&receipts_dir)
.unwrap()
.filter_map(|entry| entry.ok())
.filter(|entry| {
entry
.path()
.extension()
.map(|ext| ext == "json")
.unwrap_or(false)
})
.count();
assert!(
receipt_count >= 2,
"Should have at least 2 receipts, found {}",
receipt_count
);
println!("✅ Test PASSED: Receipt chain created");
}
#[test]
fn test_policy_validate_checks_lockfile() {
println!("🔍 E2E Test: Policy validation checks lockfile");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
create_test_lockfile(&lockfile_path).unwrap();
let result = ggen()
.arg("policy")
.arg("validate")
.arg("--profile")
.arg("enterprise-strict")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert!(json.get("profile_id").is_some(), "Should have profile_id");
assert!(json.get("passed").is_some(), "Should have passed status");
println!("✅ Test PASSED: Policy validation works");
}
#[test]
fn test_policy_list_shows_profiles() {
println!("🔍 E2E Test: Policy list shows available profiles");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("policy")
.arg("list")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert!(json.get("profiles").is_some(), "Should have profiles");
assert!(json.get("total").is_some(), "Should have total");
assert!(json["profiles"].is_array(), "profiles should be array");
println!("✅ Test PASSED: Policy list works");
}
#[test]
fn test_policy_show_displays_profile_details() {
println!("🔍 E2E Test: Policy show displays profile details");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("policy")
.arg("show")
.arg("--profile_id")
.arg("enterprise-strict")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert_eq!(
json["profile_id"], "enterprise-strict",
"Should show correct profile"
);
assert!(json.get("policies").is_some(), "Should have policies");
println!("✅ Test PASSED: Policy show works");
}
#[test]
fn test_policy_validation_without_lockfile_fails_gracefully() {
println!("🔍 E2E Test: Policy validation handles missing lockfile gracefully");
let temp_dir = TempDir::new().unwrap();
let result = ggen()
.arg("policy")
.arg("validate")
.arg("--profile")
.arg("enterprise-strict")
.current_dir(&temp_dir)
.assert();
result.success();
println!("✅ Test PASSED: Graceful error handling");
}
#[test]
fn test_policy_enforces_trust_requirements() {
println!("🔍 E2E Test: Policy enforces trust requirements");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
create_test_lockfile(&lockfile_path).unwrap();
let result = ggen()
.arg("policy")
.arg("validate")
.arg("--profile")
.arg("enterprise-strict")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).expect("Output should be valid JSON");
assert!(
json.get("passed").is_some(),
"Should have validation result"
);
println!("✅ Test PASSED: Trust requirements enforced");
}
#[test]
#[ignore = "Depends on the removed `packs validate` verb (no live `pack validate`; only `policy validate`). `packs install`->`pack add` and `packs list`->`pack list` were migrated, but the validate step cannot pass on the current CLI."]
fn test_full_workflow_install_to_receipt() {
println!("🔍 E2E Test: Full workflow from install to receipt");
let temp_dir = TempDir::new().unwrap();
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
assert!(
temp_dir.path().join(".ggen").exists(),
".ggen directory should exist"
);
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
assert!(lockfile_path.exists(), "Lockfile should exist");
let receipts_dir = temp_dir.path().join(".ggen/receipts");
assert!(receipts_dir.exists(), "Receipts directory should exist");
ggen()
.arg("pack")
.arg("list")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("pack")
.arg("validate")
.arg("--pack_id")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
println!("✅ Test PASSED: Full workflow completed");
}
#[test]
#[ignore = "Depends on the non-existent `capability enable` noun (crates/ggen-cli/src/cmds/mod.rs). The policy step is live, but the capability step cannot run on the current CLI."]
fn test_full_workflow_capability_to_policy() {
println!("🔍 E2E Test: Capability enable → policy validate workflow");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
create_test_lockfile(&lockfile_path).unwrap();
ggen()
.arg("capability")
.arg("enable")
.arg("mcp")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("policy")
.arg("validate")
.arg("--profile")
.arg("enterprise-strict")
.current_dir(&temp_dir)
.assert()
.success();
assert!(
lockfile_path.exists(),
"Lockfile should persist through workflow"
);
println!("✅ Test PASSED: Capability to policy workflow");
}
#[test]
fn test_full_workflow_with_receipt_verification() {
println!("🔍 E2E Test: Workflow with receipt verification");
let temp_dir = TempDir::new().unwrap();
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
let receipts_dir = temp_dir.path().join(".ggen/receipts");
let receipt_files: Vec<_> = fs::read_dir(&receipts_dir)
.unwrap()
.filter_map(|entry| entry.ok())
.filter(|entry| {
entry
.path()
.extension()
.map(|ext| ext == "json")
.unwrap_or(false)
})
.collect();
assert!(!receipt_files.is_empty(), "Should have receipt files");
let receipt_path = receipt_files[0].path();
ggen()
.arg("receipt")
.arg("info")
.arg("--receipt_file")
.arg(receipt_path.to_str().unwrap())
.current_dir(&temp_dir)
.assert()
.success();
println!("✅ Test PASSED: Receipt verification workflow");
}
#[test]
#[ignore = "Depends on the non-existent `capability enable` noun (crates/ggen-cli/src/cmds/mod.rs). `packs list`->`pack list` was migrated, but the capability step cannot run on the current CLI."]
fn test_concurrent_operations_with_lockfile() {
println!("🔍 E2E Test: Lockfile handles multiple operations");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
create_test_lockfile(&lockfile_path).unwrap();
ggen()
.arg("pack")
.arg("list")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("capability")
.arg("enable")
.arg("mcp")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("policy")
.arg("validate")
.arg("--profile")
.arg("enterprise-strict")
.current_dir(&temp_dir)
.assert()
.success();
assert!(
lockfile_path.exists(),
"Lockfile should persist through multiple operations"
);
println!("✅ Test PASSED: Concurrent operations handled");
}
#[test]
fn test_workflow_error_handling() {
println!("🔍 E2E Test: Graceful error handling");
let temp_dir = TempDir::new().unwrap();
ggen()
.arg("pack")
.arg("show")
.arg("--pack_id")
.arg("nonexistent-pack-xyz")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("receipt")
.arg("verify")
.arg("--receipt_file")
.arg("nonexistent-receipt.json")
.current_dir(&temp_dir)
.assert()
.success();
println!("✅ Test PASSED: Graceful error handling");
}
#[test]
fn test_full_workflow_multiple_packs() {
println!("🔍 E2E Test: Install multiple packs with full workflow");
let temp_dir = TempDir::new().unwrap();
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
ggen()
.arg("pack")
.arg("add")
.arg("projection-rust")
.current_dir(&temp_dir)
.assert()
.success();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
let pack_count = count_lockfile_packs(&lockfile_path).unwrap();
assert_eq!(pack_count, 2, "Should have 2 packs in lockfile");
let receipts_dir = temp_dir.path().join(".ggen/receipts");
let receipt_count = fs::read_dir(&receipts_dir)
.unwrap()
.filter_map(|entry| entry.ok())
.filter(|entry| {
entry
.path()
.extension()
.map(|ext| ext == "json")
.unwrap_or(false)
})
.count();
assert!(
receipt_count >= 2,
"Should have at least 2 receipts, found {}",
receipt_count
);
let result = ggen()
.arg("pack")
.arg("list")
.current_dir(&temp_dir)
.assert()
.success();
let output = String::from_utf8_lossy(&result.get_output().stdout);
let json = parse_json(&output).unwrap();
assert!(json["packs"].as_array().unwrap().len() >= 2);
println!("✅ Test PASSED: Multiple packs workflow");
}
#[test]
#[ignore = "Depends on the non-existent `capability enable` noun (crates/ggen-cli/src/cmds/mod.rs). `packs install`->`pack add` was migrated, but the capability step cannot run on the current CLI."]
fn test_workflow_state_consistency() {
println!("🔍 E2E Test: State consistency across workflow");
let temp_dir = TempDir::new().unwrap();
let lockfile_path = temp_dir.path().join(".ggen/packs.lock");
ggen()
.arg("pack")
.arg("add")
.arg("surface-mcp")
.current_dir(&temp_dir)
.assert()
.success();
let content1 = fs::read_to_string(&lockfile_path).unwrap();
let json1: Value = parse_json(&content1).unwrap();
let pack_count1 = json1["packs"].as_object().unwrap().len();
ggen()
.arg("capability")
.arg("enable")
.arg("mcp")
.current_dir(&temp_dir)
.assert()
.success();
let content2 = fs::read_to_string(&lockfile_path).unwrap();
let json2: Value = parse_json(&content2).unwrap();
let pack_count2 = json2["packs"].as_object().unwrap().len();
assert!(pack_count2 >= pack_count1, "Lockfile should be updated");
println!("✅ Test PASSED: State consistency maintained");
}