generated from nhcarrigan/template
feat: add tests and assert coverage (#71)
### Explanation _No response_ ### Issue _No response_ ### Attestations - [ ] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/) - [ ] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). - [ ] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/). ### Dependencies - [ ] I have pinned the dependencies to a specific patch version. ### Style - [ ] I have run the linter and resolved any errors. - [ ] My pull request uses an appropriate title, matching the conventional commit standards. - [ ] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request. ### Tests - [ ] My contribution adds new code, and I have added tests to cover it. - [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes. - [ ] All new and existing tests pass locally with my changes. - [ ] Code coverage remains at or above the configured threshold. ### Documentation _No response_ ### Versioning _No response_ Co-authored-by: Hikari <hikari@nhcarrigan.com> Reviewed-on: #71 Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com> Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit was merged in pull request #71.
This commit is contained in:
@@ -171,6 +171,18 @@ pub async fn reset_default_quick_actions(app: AppHandle) -> Result<(), String> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn create_test_action(id: &str, name: &str, is_default: bool) -> QuickAction {
|
||||
QuickAction {
|
||||
id: id.to_string(),
|
||||
name: name.to_string(),
|
||||
prompt: "Test prompt".to_string(),
|
||||
icon: "star".to_string(),
|
||||
is_default,
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_quick_actions_exist() {
|
||||
let defaults = get_default_quick_actions();
|
||||
@@ -188,4 +200,174 @@ mod tests {
|
||||
assert!(!action.icon.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_quick_actions_count() {
|
||||
let defaults = get_default_quick_actions();
|
||||
// Should have 6 default actions
|
||||
assert_eq!(defaults.len(), 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_quick_actions_have_unique_ids() {
|
||||
let defaults = get_default_quick_actions();
|
||||
let mut ids: Vec<&String> = defaults.iter().map(|a| &a.id).collect();
|
||||
ids.sort();
|
||||
ids.dedup();
|
||||
assert_eq!(ids.len(), defaults.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_quick_actions_ids_start_with_default() {
|
||||
let defaults = get_default_quick_actions();
|
||||
assert!(defaults.iter().all(|a| a.id.starts_with("default-")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quick_action_serialization() {
|
||||
let action = create_test_action("test-1", "Test Action", false);
|
||||
let json = serde_json::to_string(&action).expect("Failed to serialize");
|
||||
let parsed: QuickAction = serde_json::from_str(&json).expect("Failed to deserialize");
|
||||
|
||||
assert_eq!(parsed.id, action.id);
|
||||
assert_eq!(parsed.name, action.name);
|
||||
assert_eq!(parsed.prompt, action.prompt);
|
||||
assert_eq!(parsed.icon, action.icon);
|
||||
assert_eq!(parsed.is_default, action.is_default);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quick_action_clone() {
|
||||
let original = create_test_action("clone-test", "Clone Test", true);
|
||||
let cloned = original.clone();
|
||||
|
||||
assert_eq!(original.id, cloned.id);
|
||||
assert_eq!(original.name, cloned.name);
|
||||
assert_eq!(original.is_default, cloned.is_default);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::useless_vec)]
|
||||
fn test_quick_action_sorting_defaults_first() {
|
||||
let mut actions = vec![
|
||||
create_test_action("custom-z", "Zebra", false),
|
||||
create_test_action("default-a", "Apple", true),
|
||||
create_test_action("custom-a", "Alpha", false),
|
||||
create_test_action("default-z", "Zulu", true),
|
||||
];
|
||||
|
||||
// Sort by: defaults first, then alphabetically by name
|
||||
actions.sort_by(|a, b| {
|
||||
let default_cmp = b.is_default.cmp(&a.is_default);
|
||||
if default_cmp == std::cmp::Ordering::Equal {
|
||||
a.name.cmp(&b.name)
|
||||
} else {
|
||||
default_cmp
|
||||
}
|
||||
});
|
||||
|
||||
// Defaults should come first
|
||||
assert!(actions[0].is_default);
|
||||
assert!(actions[1].is_default);
|
||||
assert!(!actions[2].is_default);
|
||||
assert!(!actions[3].is_default);
|
||||
|
||||
// Within defaults, alphabetically sorted
|
||||
assert_eq!(actions[0].name, "Apple");
|
||||
assert_eq!(actions[1].name, "Zulu");
|
||||
|
||||
// Within non-defaults, alphabetically sorted
|
||||
assert_eq!(actions[2].name, "Alpha");
|
||||
assert_eq!(actions[3].name, "Zebra");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_known_default_actions() {
|
||||
let defaults = get_default_quick_actions();
|
||||
let ids: Vec<&str> = defaults.iter().map(|a| a.id.as_str()).collect();
|
||||
|
||||
assert!(ids.contains(&"default-review-pr"));
|
||||
assert!(ids.contains(&"default-run-tests"));
|
||||
assert!(ids.contains(&"default-explain-file"));
|
||||
assert!(ids.contains(&"default-fix-error"));
|
||||
assert!(ids.contains(&"default-write-tests"));
|
||||
assert!(ids.contains(&"default-refactor"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_action_icons() {
|
||||
let defaults = get_default_quick_actions();
|
||||
let icons: Vec<&str> = defaults.iter().map(|a| a.icon.as_str()).collect();
|
||||
|
||||
assert!(icons.contains(&"git-pull-request"));
|
||||
assert!(icons.contains(&"play"));
|
||||
assert!(icons.contains(&"file-text"));
|
||||
assert!(icons.contains(&"alert-circle"));
|
||||
assert!(icons.contains(&"check-square"));
|
||||
assert!(icons.contains(&"refresh-cw"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quick_action_prompts_not_empty() {
|
||||
let defaults = get_default_quick_actions();
|
||||
for action in defaults {
|
||||
assert!(
|
||||
action.prompt.len() > 10,
|
||||
"Prompt should be meaningful: {}",
|
||||
action.name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quick_action_timestamps() {
|
||||
let action = create_test_action("time-test", "Time Test", false);
|
||||
assert!(action.created_at <= action.updated_at);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_actions_have_same_timestamps() {
|
||||
let defaults = get_default_quick_actions();
|
||||
// All defaults are created at the same instant
|
||||
let first_created = defaults[0].created_at;
|
||||
let first_updated = defaults[0].updated_at;
|
||||
|
||||
for action in &defaults {
|
||||
assert_eq!(action.created_at, first_created);
|
||||
assert_eq!(action.updated_at, first_updated);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_action_retain_non_default() {
|
||||
let mut actions = vec![
|
||||
create_test_action("default-1", "Default 1", true),
|
||||
create_test_action("custom-1", "Custom 1", false),
|
||||
create_test_action("default-2", "Default 2", true),
|
||||
create_test_action("custom-2", "Custom 2", false),
|
||||
];
|
||||
|
||||
// Mimics reset_default_quick_actions behavior (retain non-defaults)
|
||||
actions.retain(|a| !a.is_default);
|
||||
|
||||
assert_eq!(actions.len(), 2);
|
||||
assert!(actions.iter().all(|a| !a.is_default));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::useless_vec)]
|
||||
fn test_action_find_by_id() {
|
||||
let actions = vec![
|
||||
create_test_action("action-1", "First", false),
|
||||
create_test_action("action-2", "Second", false),
|
||||
create_test_action("action-3", "Third", false),
|
||||
];
|
||||
|
||||
let found = actions.iter().find(|a| a.id == "action-2");
|
||||
assert!(found.is_some());
|
||||
assert_eq!(found.unwrap().name, "Second");
|
||||
|
||||
let not_found = actions.iter().find(|a| a.id == "action-999");
|
||||
assert!(not_found.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user