rustcodegraph 1.2.10

Local-first code intelligence graph and CLI for AI agents
Documentation
use super::common::*;

#[test]
fn install_writes_files_detect_already_configured_becomes_true() {
    with_fixture("contract-install", |_| {
        for target in all_targets() {
            for location in supported_locations(target.as_ref()) {
                assert!(
                    !target.detect(location).already_configured,
                    "{} {location:?} should start unconfigured",
                    target.id().as_str()
                );

                let result = target.install(location, install_options(true));
                assert!(
                    !result.files.is_empty(),
                    "{} {location:?} should report files",
                    target.id().as_str()
                );
                for file in &result.files {
                    if file.action != WriteAction::Unchanged && file.action != WriteAction::NotFound
                    {
                        assert!(
                            Path::new(&file.path).exists(),
                            "expected {} to exist",
                            file.path
                        );
                    }
                }
                assert!(
                    target.detect(location).already_configured,
                    "{} {location:?} should become configured",
                    target.id().as_str()
                );
                target.uninstall(location);
            }
        }
    });
}

#[test]
fn re_running_install_is_idempotent_no_actions_other_than_unchanged() {
    with_fixture("contract-idempotent", |_| {
        for target in all_targets() {
            for location in supported_locations(target.as_ref()) {
                target.install(location, install_options(true));
                let second = target.install(location, install_options(true));
                for file in &second.files {
                    assert_eq!(
                        file.action,
                        WriteAction::Unchanged,
                        "{} {location:?} expected unchanged for {}",
                        target.id().as_str(),
                        file.path
                    );
                }
                target.uninstall(location);
            }
        }
    });
}

#[test]
fn install_preserves_a_pre_existing_sibling_mcp_server_where_applicable() {
    with_fixture("contract-sibling", |_| {
        for target in all_targets() {
            for location in supported_locations(target.as_ref()) {
                let paths = target.describe_paths(location);
                let Some(json_path) = paths
                    .iter()
                    .find(|path| path.ends_with(".json") || path.ends_with(".jsonc"))
                else {
                    continue;
                };
                let path = PathBuf::from(json_path);
                if target.id() == TargetId::Opencode {
                    write_json(
                        &path,
                        json!({ "mcp": { "other": { "type": "local", "command": ["x"], "enabled": true } } }),
                    );
                } else {
                    write_json(
                        &path,
                        json!({ "mcpServers": { "other": { "command": "x" } } }),
                    );
                }

                target.install(location, install_options(true));
                let after = read_json(&path);
                if target.id() == TargetId::Opencode {
                    assert!(
                        after.pointer("/mcp/other").is_some(),
                        "opencode sibling missing"
                    );
                    assert!(
                        after.pointer("/mcp/rustcodegraph").is_some(),
                        "opencode rustcodegraph missing"
                    );
                } else {
                    assert!(
                        after.pointer("/mcpServers/other").is_some(),
                        "sibling missing"
                    );
                    assert!(
                        after.pointer("/mcpServers/rustcodegraph").is_some(),
                        "rustcodegraph missing"
                    );
                }
                target.uninstall(location);
            }
        }
    });
}

#[test]
fn uninstall_reverses_install_already_configured_returns_to_false() {
    with_fixture("contract-uninstall", |_| {
        for target in all_targets() {
            for location in supported_locations(target.as_ref()) {
                target.install(location, install_options(true));
                assert!(target.detect(location).already_configured);
                target.uninstall(location);
                assert!(!target.detect(location).already_configured);
            }
        }
    });
}

#[test]
fn print_config_returns_non_empty_output_without_writing_anything() {
    with_fixture("contract-print", |fixture| {
        for target in all_targets() {
            for location in supported_locations(target.as_ref()) {
                let mut before = list_all_files(fixture.home());
                before.extend(list_all_files(fixture.cwd()));
                before.sort();
                let out = target.print_config(location);
                assert!(
                    !out.is_empty(),
                    "{} printConfig returned empty",
                    target.id().as_str()
                );
                let mut after = list_all_files(fixture.home());
                after.extend(list_all_files(fixture.cwd()));
                after.sort();
                assert_eq!(
                    after,
                    before,
                    "{} printConfig wrote files",
                    target.id().as_str()
                );
            }
        }
    });
}