Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
bdbea7d
minor fixes
Jan 16, 2026
223f573
Add tests to achieve 90% coverage for wonopcode-tools
Jan 16, 2026
21a9bdc
Add tests to wonopcode-core: message, hook, share, permission - cover…
Jan 16, 2026
0feb545
Add tests to wonopcode-acp session - coverage 35.16%
Jan 16, 2026
aecad95
Add error tests to wonopcode-lsp and wonopcode-mcp
Jan 16, 2026
a543d9f
Add protocol tests to wonopcode-mcp - coverage now 48.05%
Jan 16, 2026
68901b7
Add tests to wonopcode-core - coverage now 82.96%
Jan 16, 2026
4bdc5ab
Add tests to wonopcode-mcp - coverage now 56.07%
Jan 16, 2026
edbe462
Add tests to wonopcode-core: session, prompt, revert - coverage now 8…
Jan 16, 2026
f2a126e
Add tests to wonopcode-mcp: client, callback - coverage now 63.00%
Jan 16, 2026
3c19d1a
Add instance tests to wonopcode-core - coverage now 89.10%
Jan 16, 2026
f91ba98
Add config tests to wonopcode-core - coverage now 90.42%
Jan 16, 2026
1854b5c
Add tests to wonopcode-mcp - coverage now 83.72%
Jan 16, 2026
d6915bf
Add more tests to wonopcode-mcp oauth.rs - coverage now 85.08%
Jan 16, 2026
b73c38d
Add permission tests to wonopcode-core - coverage now 90.48%
Jan 17, 2026
f64311f
Add tests to wonopcode-discover and wonopcode-server
Jan 17, 2026
2617a42
Add more tests to wonopcode-server - improve coverage
Jan 17, 2026
2868324
refactor
Jan 17, 2026
5ac00fc
Add tests for wonopcode-acp and wonopcode-tui-core
Jan 17, 2026
ca2eb2a
Add tests to wonopcode-tui-widgets - coverage now 43%
Jan 17, 2026
231ea45
Add more tests to wonopcode-tui-widgets - coverage now 52%
Jan 17, 2026
990fc65
Add autocomplete tests to wonopcode-tui-widgets - coverage now 55%
Jan 17, 2026
c1848c2
Add tests to wonopcode-tui-messages - coverage now 25%
Jan 17, 2026
186b04d
Update COVERAGE_PLAN.md with current progress - 55.87% total coverage
Jan 17, 2026
b3c8a69
Add --sort option to covstats command
Jan 17, 2026
f5b4135
Adding support for phases
Jan 17, 2026
8671ff0
finishing tests etc
Jan 17, 2026
4816cdf
removing garbage
Jan 17, 2026
341b58d
removing more slop
Jan 17, 2026
2e84715
fixing tests
Jan 17, 2026
e7ff535
fix: tests
Jan 17, 2026
9a457b9
fixing the coverage workflow
Jan 17, 2026
33744d2
fix: tests
Jan 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:

- name: Generate coverage summary
run: |
cargo llvm-cov report --all-features --workspace \
cargo llvm-cov report \
--ignore-filename-regex '(tests/|test\.rs|mock\.rs)' \
> coverage-summary.txt
echo "## Coverage Summary" >> $GITHUB_STEP_SUMMARY
Expand All @@ -62,7 +62,7 @@ jobs:
- name: Check coverage threshold
run: |
# Extract total line coverage percentage
COVERAGE=$(cargo llvm-cov report --all-features --workspace \
COVERAGE=$(cargo llvm-cov report \
--ignore-filename-regex '(tests/|test\.rs|mock\.rs)' 2>/dev/null \
| grep -E '^TOTAL' | awk '{print $NF}' | tr -d '%')

Expand Down
71 changes: 71 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ members = [
"crates/wonopcode-protocol",
"crates/wonopcode-discover",
"crates/wonopcode-test-utils",
# TUI sub-crates
"crates/wonopcode-tui-core",
"crates/wonopcode-tui-render",
"crates/wonopcode-tui-widgets",
"crates/wonopcode-tui-dialog",
"crates/wonopcode-tui-messages",
]

[workspace.package]
Expand Down Expand Up @@ -50,6 +56,13 @@ wonopcode-protocol = { path = "crates/wonopcode-protocol" }
wonopcode-discover = { path = "crates/wonopcode-discover" }
wonopcode-test-utils = { path = "crates/wonopcode-test-utils" }

# TUI sub-crates
wonopcode-tui-core = { path = "crates/wonopcode-tui-core" }
wonopcode-tui-render = { path = "crates/wonopcode-tui-render" }
wonopcode-tui-widgets = { path = "crates/wonopcode-tui-widgets" }
wonopcode-tui-dialog = { path = "crates/wonopcode-tui-dialog" }
wonopcode-tui-messages = { path = "crates/wonopcode-tui-messages" }

# Async runtime
tokio = { version = "1", features = ["full"] }
futures = "0.3"
Expand Down
111 changes: 111 additions & 0 deletions crates/wonopcode-acp/src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,3 +760,114 @@ pub async fn serve(config: AgentConfig) {
let (agent, incoming_rx) = Agent::new(config);
agent.run(incoming_rx).await;
}

#[cfg(test)]
mod tests {
use super::*;

// === AgentConfig tests ===

#[test]
fn test_agent_config_default() {
let config = AgentConfig::default();
assert_eq!(config.name, "Wonopcode");
assert!(!config.version.is_empty());
assert!(config.default_model.is_none());
}

#[test]
fn test_agent_config_custom() {
let config = AgentConfig {
name: "Custom Agent".to_string(),
version: "1.0.0".to_string(),
default_model: ModelRef::parse("anthropic/claude-sonnet-4-5"),
};
assert_eq!(config.name, "Custom Agent");
assert_eq!(config.version, "1.0.0");
assert!(config.default_model.is_some());
}

#[test]
fn test_agent_config_clone() {
let config = AgentConfig {
name: "Test".to_string(),
version: "1.0.0".to_string(),
default_model: None,
};
let cloned = config;
assert_eq!(cloned.name, "Test");
assert_eq!(cloned.version, "1.0.0");
}

#[test]
fn test_agent_config_debug() {
let config = AgentConfig::default();
let debug = format!("{:?}", config);
assert!(debug.contains("AgentConfig"));
assert!(debug.contains("Wonopcode"));
}

// === capitalize_provider tests ===

#[test]
fn test_capitalize_provider_lowercase() {
assert_eq!(capitalize_provider("anthropic"), "Anthropic");
assert_eq!(capitalize_provider("openai"), "Openai");
assert_eq!(capitalize_provider("google"), "Google");
}

#[test]
fn test_capitalize_provider_already_capitalized() {
assert_eq!(capitalize_provider("Anthropic"), "Anthropic");
}

#[test]
fn test_capitalize_provider_empty() {
assert_eq!(capitalize_provider(""), "");
}

#[test]
fn test_capitalize_provider_single_char() {
assert_eq!(capitalize_provider("a"), "A");
assert_eq!(capitalize_provider("Z"), "Z");
}

#[test]
fn test_capitalize_provider_with_numbers() {
assert_eq!(capitalize_provider("gpt4"), "Gpt4");
}

// === ModelRef tests ===

#[test]
fn test_model_ref_as_string() {
let model = ModelRef::parse("anthropic/claude-sonnet-4-5").unwrap();
assert_eq!(model.as_string(), "anthropic/claude-sonnet-4-5");
}

#[test]
fn test_model_ref_parse_valid() {
let model = ModelRef::parse("openai/gpt-4o");
assert!(model.is_some());
let model = model.unwrap();
assert_eq!(model.provider_id, "openai");
assert_eq!(model.model_id, "gpt-4o");
}

#[test]
fn test_model_ref_parse_no_slash() {
let model = ModelRef::parse("claude-sonnet-4-5");
assert!(model.is_none());
}

#[test]
fn test_model_ref_parse_empty_parts() {
// Note: ModelRef::parse doesn't check for empty parts after split
// This documents the actual behavior
let result = ModelRef::parse("/model");
assert!(result.is_some()); // Actually returns Some with empty provider

let result = ModelRef::parse("provider/");
assert!(result.is_some()); // Actually returns Some with empty model
}
}
Loading