use std::path::Path;
use std::process::Command;
fn bin() -> Command {
let mut cmd = Command::new(env!("CARGO_BIN_EXE_i-self"));
cmd.env("RUST_LOG", "error");
cmd
}
fn write(path: &Path, content: &str) {
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
std::fs::write(path, content).unwrap();
}
#[test]
fn share_ls_finds_seeded_goose_session() {
let tmp = tempfile::tempdir().unwrap();
write(
&tmp.path().join("test-session.jsonl"),
r#"{"role":"user","created":1715000000,"content":[{"type":"text","text":"refactor auth"}]}
{"role":"assistant","content":[{"type":"text","text":"on it"}]}
"#,
);
let out = bin()
.args(["share", "ls", "--provider", "goose"])
.env("ISELF_GOOSE_DIR", tmp.path())
.env("ISELF_CODEX_DIR", tmp.path().join("__empty__"))
.env("ISELF_CONTINUE_DIR", tmp.path().join("__empty__"))
.env("ISELF_OPENCODE_DIR", tmp.path().join("__empty__"))
.env("HOME", tmp.path()) .output()
.expect("spawn");
assert!(out.status.success(), "stderr: {}", String::from_utf8_lossy(&out.stderr));
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(stdout.contains("test-session"), "got: {}", stdout);
assert!(stdout.contains("[goose"), "should label provider: {}", stdout);
assert!(stdout.contains("refactor auth"), "should show title hint: {}", stdout);
}
#[test]
fn share_export_to_json_then_import_to_aider_round_trips() {
let src_dir = tempfile::tempdir().unwrap();
let dst_dir = tempfile::tempdir().unwrap();
let work_dir = tempfile::tempdir().unwrap();
let aider_project = work_dir.path().join("aider-target");
std::fs::create_dir_all(&aider_project).unwrap();
write(
&src_dir.path().join("src-session.jsonl"),
r#"{"role":"user","created":1715000000,"content":[{"type":"text","text":"first user turn"}]}
{"role":"assistant","content":[{"type":"text","text":"first assistant reply"}]}
"#,
);
let exported = work_dir.path().join("exported.json");
let export_out = bin()
.args([
"share",
"export",
"src-session",
"--format",
"json",
"--output",
exported.to_str().unwrap(),
])
.env("ISELF_GOOSE_DIR", src_dir.path())
.env("HOME", dst_dir.path()) .output()
.expect("spawn export");
assert!(
export_out.status.success(),
"export failed: {}",
String::from_utf8_lossy(&export_out.stderr)
);
assert!(exported.exists(), "export should have written {:?}", exported);
let json = std::fs::read_to_string(&exported).unwrap();
assert!(json.contains("first user turn"));
assert!(json.contains("first assistant reply"));
let import_out = bin()
.args([
"share",
"import",
exported.to_str().unwrap(),
"--target",
"aider",
"--project",
aider_project.to_str().unwrap(),
])
.output()
.expect("spawn import");
assert!(
import_out.status.success(),
"import failed: {}",
String::from_utf8_lossy(&import_out.stderr)
);
let history = aider_project.join(".aider.chat.history.md");
assert!(history.exists(), "aider history should have been created");
let body = std::fs::read_to_string(&history).unwrap();
assert!(body.contains("[i-self import]"), "provenance line missing");
assert!(body.contains("> first user turn"), "user turn missing");
assert!(body.contains("first assistant reply"), "assistant reply missing");
}
#[test]
fn share_import_unknown_target_fails_cleanly() {
let tmp = tempfile::tempdir().unwrap();
let session = tmp.path().join("session.json");
std::fs::write(
&session,
r#"{"provider":"x","id":"y","project_path":null,"started_at":null,"messages":[]}"#,
)
.unwrap();
let out = bin()
.args([
"share",
"import",
session.to_str().unwrap(),
"--target",
"definitely-not-a-real-target",
])
.output()
.expect("spawn");
assert!(!out.status.success(), "expected failure for bad target");
let stderr = String::from_utf8_lossy(&out.stderr);
let stdout = String::from_utf8_lossy(&out.stdout);
let combined = format!("{}{}", stderr, stdout);
assert!(combined.contains("unknown target"), "expected helpful error, got: {}", combined);
}
#[test]
fn share_export_to_html_produces_self_contained_file() {
let src_dir = tempfile::tempdir().unwrap();
let work_dir = tempfile::tempdir().unwrap();
write(
&src_dir.path().join("html-test.jsonl"),
r#"{"role":"user","content":"Hello <world>"}
{"role":"assistant","content":"```rust\nfn main() {}\n```"}
"#,
);
let out_path = work_dir.path().join("session.html");
let out = bin()
.args([
"share",
"export",
"html-test",
"--format",
"html",
"--output",
out_path.to_str().unwrap(),
])
.env("ISELF_GOOSE_DIR", src_dir.path())
.env("HOME", work_dir.path())
.output()
.expect("spawn");
assert!(out.status.success(), "stderr: {}", String::from_utf8_lossy(&out.stderr));
let html = std::fs::read_to_string(&out_path).unwrap();
assert!(html.starts_with("<!DOCTYPE html>"));
assert!(html.contains("<style>"));
assert!(!html.contains("<script"));
assert!(!html.contains("Hello <world>"));
assert!(html.contains("<world>"));
assert!(html.contains("data-lang=\"rust\""));
}
#[test]
fn vuln_check_known_safe_package_returns_zero_vulns() {
if std::env::var("ISELF_RUN_NETWORK_TESTS").is_err() {
eprintln!("skipping network-touching integration test (set ISELF_RUN_NETWORK_TESTS=1)");
return;
}
let out = bin()
.args(["vuln", "check", "serde", "1.0.200", "--ecosystem", "cargo"])
.output()
.expect("spawn");
assert!(out.status.success(), "stderr: {}", String::from_utf8_lossy(&out.stderr));
}