Skip to content

Commit 068d893

Browse files
test(redisctl): add async_utils unit tests (#472)
* chore: add coverage artifacts to gitignore * test(redisctl): add unit tests for async_utils pure functions Add comprehensive unit tests for async operation utilities: - Task state detection (completed, failed, cancelled, in-progress) - Task state formatting with visual indicators - Task details parsing from various API response formats - Error handling for nested and alternative field names Coverage: 22 new tests for critical polling/async logic Related to #462
1 parent abe9312 commit 068d893

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

crates/redisctl/src/commands/cloud/async_utils.rs

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,209 @@ fn print_task_details(task: &Value) -> CliResult<()> {
270270

271271
Ok(())
272272
}
273+
274+
#[cfg(test)]
275+
mod tests {
276+
use super::*;
277+
use serde_json::json;
278+
279+
#[test]
280+
fn test_is_terminal_state_completed_variants() {
281+
assert!(is_terminal_state("completed"));
282+
assert!(is_terminal_state("complete"));
283+
assert!(is_terminal_state("succeeded"));
284+
assert!(is_terminal_state("success"));
285+
assert!(is_terminal_state("COMPLETED")); // case insensitive
286+
}
287+
288+
#[test]
289+
fn test_is_terminal_state_failed_variants() {
290+
assert!(is_terminal_state("failed"));
291+
assert!(is_terminal_state("error"));
292+
assert!(is_terminal_state("processing-error"));
293+
assert!(is_terminal_state("ERROR")); // case insensitive
294+
}
295+
296+
#[test]
297+
fn test_is_terminal_state_cancelled() {
298+
assert!(is_terminal_state("cancelled"));
299+
assert!(is_terminal_state("CANCELLED"));
300+
}
301+
302+
#[test]
303+
fn test_is_terminal_state_non_terminal() {
304+
assert!(!is_terminal_state("processing"));
305+
assert!(!is_terminal_state("running"));
306+
assert!(!is_terminal_state("in_progress"));
307+
assert!(!is_terminal_state("pending"));
308+
assert!(!is_terminal_state("unknown"));
309+
assert!(!is_terminal_state(""));
310+
}
311+
312+
#[test]
313+
fn test_get_task_state_from_status() {
314+
let task = json!({"status": "completed"});
315+
assert_eq!(get_task_state(&task), "completed");
316+
}
317+
318+
#[test]
319+
fn test_get_task_state_from_state() {
320+
let task = json!({"state": "processing"});
321+
assert_eq!(get_task_state(&task), "processing");
322+
}
323+
324+
#[test]
325+
fn test_get_task_state_status_priority() {
326+
// status takes priority over state
327+
let task = json!({"status": "completed", "state": "processing"});
328+
assert_eq!(get_task_state(&task), "completed");
329+
}
330+
331+
#[test]
332+
fn test_get_task_state_unknown() {
333+
let task = json!({"foo": "bar"});
334+
assert_eq!(get_task_state(&task), "unknown");
335+
}
336+
337+
#[test]
338+
fn test_get_task_state_empty() {
339+
let task = json!({});
340+
assert_eq!(get_task_state(&task), "unknown");
341+
}
342+
343+
#[test]
344+
fn test_format_task_state_success_variants() {
345+
assert_eq!(format_task_state("completed"), "✓ completed");
346+
assert_eq!(format_task_state("complete"), "✓ complete");
347+
assert_eq!(format_task_state("succeeded"), "✓ succeeded");
348+
assert_eq!(format_task_state("success"), "✓ success");
349+
assert_eq!(format_task_state("COMPLETED"), "✓ COMPLETED");
350+
}
351+
352+
#[test]
353+
fn test_format_task_state_failure_variants() {
354+
assert_eq!(format_task_state("failed"), "✗ failed");
355+
assert_eq!(format_task_state("error"), "✗ error");
356+
assert_eq!(format_task_state("processing-error"), "✗ processing-error");
357+
assert_eq!(format_task_state("ERROR"), "✗ ERROR");
358+
}
359+
360+
#[test]
361+
fn test_format_task_state_cancelled() {
362+
assert_eq!(format_task_state("cancelled"), "⊘ cancelled");
363+
assert_eq!(format_task_state("CANCELLED"), "⊘ CANCELLED");
364+
}
365+
366+
#[test]
367+
fn test_format_task_state_in_progress_variants() {
368+
assert_eq!(format_task_state("processing"), "⟳ processing");
369+
assert_eq!(format_task_state("running"), "⟳ running");
370+
assert_eq!(format_task_state("in_progress"), "⟳ in_progress");
371+
}
372+
373+
#[test]
374+
fn test_format_task_state_unknown() {
375+
assert_eq!(format_task_state("pending"), "pending");
376+
assert_eq!(format_task_state("unknown"), "unknown");
377+
assert_eq!(format_task_state("custom_state"), "custom_state");
378+
}
379+
380+
#[test]
381+
fn test_print_task_details_full() {
382+
let task = json!({
383+
"taskId": "task-123",
384+
"status": "completed",
385+
"description": "Create database",
386+
"progress": 100,
387+
"createdAt": "2025-01-01T00:00:00Z",
388+
"updatedAt": "2025-01-01T00:05:00Z"
389+
});
390+
391+
let result = print_task_details(&task);
392+
assert!(result.is_ok());
393+
}
394+
395+
#[test]
396+
fn test_print_task_details_with_error() {
397+
let task = json!({
398+
"taskId": "task-456",
399+
"status": "failed",
400+
"error": "Database creation failed",
401+
"description": "Create database"
402+
});
403+
404+
let result = print_task_details(&task);
405+
assert!(result.is_ok());
406+
}
407+
408+
#[test]
409+
fn test_print_task_details_with_error_message() {
410+
let task = json!({
411+
"taskId": "task-789",
412+
"status": "failed",
413+
"errorMessage": "Invalid configuration"
414+
});
415+
416+
let result = print_task_details(&task);
417+
assert!(result.is_ok());
418+
}
419+
420+
#[test]
421+
fn test_print_task_details_with_nested_error_object() {
422+
let task = json!({
423+
"taskId": "task-nested",
424+
"status": "failed",
425+
"response": {
426+
"error": {
427+
"type": "ValidationError",
428+
"status": "400",
429+
"description": "Invalid database configuration"
430+
}
431+
}
432+
});
433+
434+
let result = print_task_details(&task);
435+
assert!(result.is_ok());
436+
}
437+
438+
#[test]
439+
fn test_print_task_details_with_nested_error_string() {
440+
let task = json!({
441+
"taskId": "task-string-error",
442+
"status": "failed",
443+
"response": {
444+
"error": "Simple error message"
445+
}
446+
});
447+
448+
let result = print_task_details(&task);
449+
assert!(result.is_ok());
450+
}
451+
452+
#[test]
453+
fn test_print_task_details_minimal() {
454+
let task = json!({"id": "task-minimal"});
455+
let result = print_task_details(&task);
456+
assert!(result.is_ok());
457+
}
458+
459+
#[test]
460+
fn test_print_task_details_alternative_field_names() {
461+
let task = json!({
462+
"id": "task-alt",
463+
"state": "processing",
464+
"created_at": "2025-01-01T00:00:00Z",
465+
"updated_at": "2025-01-01T00:01:00Z"
466+
});
467+
468+
let result = print_task_details(&task);
469+
assert!(result.is_ok());
470+
}
471+
472+
#[test]
473+
fn test_print_task_details_empty() {
474+
let task = json!({});
475+
let result = print_task_details(&task);
476+
assert!(result.is_ok());
477+
}
478+
}

0 commit comments

Comments
 (0)