test: add cli tests for bags

This commit is contained in:
Jon Seager 2025-11-27 13:34:56 +00:00
parent d708a0e112
commit 5252cacad0
No known key found for this signature in database
5 changed files with 233 additions and 64 deletions

159
tests/cli/bags_cli.rs Normal file
View file

@ -0,0 +1,159 @@
use crate::helpers::{create_roast, create_roaster, create_token, run_brewlog, server_info};
use serde_json::Value;
#[test]
fn test_add_bag_requires_authentication() {
let _ = server_info();
let output = run_brewlog(&["add-bag", "--roast-id", "123", "--amount", "250.0"], &[]);
assert!(!output.status.success(), "add-bag without auth should fail");
}
#[test]
fn test_add_bag_with_authentication() {
let token = create_token("test-add-bag");
// Setup: Create Roaster & Roast
let roaster_id = create_roaster("Bag Add Roaster", &token);
let roast_id = create_roast(&roaster_id, "Bag Add Roast", &token);
// Test: Add Bag
let output = run_brewlog(
&[
"add-bag",
"--roast-id",
&roast_id,
"--amount",
"250.0",
"--roast-date",
"2023-01-01",
],
&[("BREWLOG_TOKEN", &token)],
);
assert!(output.status.success());
let bag: Value = serde_json::from_slice(&output.stdout).unwrap();
assert_eq!(bag["amount"].as_f64(), Some(250.0));
assert_eq!(bag["roast_date"], "2023-01-01");
assert!(bag["id"].is_i64());
}
#[test]
fn test_update_bag_requires_authentication() {
let _ = server_info();
let output = run_brewlog(&["update-bag", "--id", "123", "--remaining", "100.0"], &[]);
assert!(
!output.status.success(),
"update-bag without auth should fail"
);
}
#[test]
fn test_update_bag_with_authentication() {
let token = create_token("test-update-bag");
// Setup: Create Roaster & Roast & Bag
let roaster_id = create_roaster("Bag Update Roaster", &token);
let roast_id = create_roast(&roaster_id, "Bag Update Roast", &token);
let bag_output = run_brewlog(
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
&[("BREWLOG_TOKEN", &token)],
);
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
let bag_id = bag["id"].as_i64().unwrap().to_string();
// Test: Update Bag
let output = run_brewlog(
&[
"update-bag",
"--id",
&bag_id,
"--remaining",
"150.0",
"--closed",
"true",
],
&[("BREWLOG_TOKEN", &token)],
);
assert!(output.status.success());
let updated_bag: Value = serde_json::from_slice(&output.stdout).unwrap();
assert_eq!(updated_bag["remaining"].as_f64(), Some(150.0));
assert_eq!(updated_bag["closed"].as_bool(), Some(true));
}
#[test]
fn test_list_bags_works_without_authentication() {
let _ = server_info();
// Listing without roast_id might return all or empty, but should succeed (200 OK)
let output = run_brewlog(&["list-bags"], &[]);
assert!(output.status.success());
}
#[test]
fn test_list_bags_shows_added_bag() {
let token = create_token("test-list-bags");
// Setup
let roaster_id = create_roaster("Bag List Roaster", &token);
let roast_id = create_roast(&roaster_id, "Bag List Roast", &token);
let bag_output = run_brewlog(
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
&[("BREWLOG_TOKEN", &token)],
);
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
let bag_id = bag["id"].as_i64().unwrap();
// Test: List Bags (Authenticated)
let output = run_brewlog(
&["list-bags", "--roast-id", &roast_id],
&[("BREWLOG_TOKEN", &token)],
);
assert!(output.status.success());
let bags: Value = serde_json::from_slice(&output.stdout).unwrap();
assert!(bags.is_array());
let bags_array = bags.as_array().unwrap();
assert!(bags_array.iter().any(|b| b["id"].as_i64() == Some(bag_id)));
}
#[test]
fn test_delete_bag_requires_authentication() {
let _ = server_info();
let output = run_brewlog(&["delete-bag", "--id", "123"], &[]);
assert!(!output.status.success());
}
#[test]
fn test_delete_bag_with_authentication() {
let token = create_token("test-delete-bag");
// Setup
let roaster_id = create_roaster("Bag Delete Roaster", &token);
let roast_id = create_roast(&roaster_id, "Bag Delete Roast", &token);
let bag_output = run_brewlog(
&["add-bag", "--roast-id", &roast_id, "--amount", "250.0"],
&[("BREWLOG_TOKEN", &token)],
);
let bag: Value = serde_json::from_slice(&bag_output.stdout).unwrap();
let bag_id = bag["id"].as_i64().unwrap().to_string();
// Test: Delete Bag
let output = run_brewlog(
&["delete-bag", "--id", &bag_id],
&[("BREWLOG_TOKEN", &token)],
);
assert!(output.status.success());
// Verify deletion
let get_output = run_brewlog(&["get-bag", "--id", &bag_id], &[]);
assert!(!get_output.status.success());
}

View file

@ -161,3 +161,64 @@ pub fn run_brewlog(args: &[&str], env: &[(&str, &str)]) -> std::process::Output
cmd.output().expect("Failed to run brewlog command")
}
/// Helper to create a roaster and return its ID
pub fn create_roaster(name: &str, token: &str) -> String {
let output = run_brewlog(
&["add-roaster", "--name", name, "--country", "UK"],
&[("BREWLOG_TOKEN", token)],
);
if !output.status.success() {
panic!(
"Failed to create roaster: {}",
String::from_utf8_lossy(&output.stderr)
);
}
let stdout = String::from_utf8_lossy(&output.stdout);
let roaster: serde_json::Value =
serde_json::from_str(&stdout).expect("Should output valid JSON");
roaster["id"]
.as_i64()
.expect("roaster id should be numeric")
.to_string()
}
/// Helper to create a roast and return its ID
pub fn create_roast(roaster_id: &str, name: &str, token: &str) -> String {
let output = run_brewlog(
&[
"add-roast",
"--roaster-id",
roaster_id,
"--name",
name,
"--origin",
"Kenya",
"--region",
"Nyeri",
"--producer",
"Coop",
"--process",
"Washed",
"--tasting-notes",
"Blackcurrant",
],
&[("BREWLOG_TOKEN", token)],
);
if !output.status.success() {
panic!(
"Failed to create roast: {}",
String::from_utf8_lossy(&output.stderr)
);
}
let stdout = String::from_utf8_lossy(&output.stdout);
let roast: serde_json::Value = serde_json::from_str(&stdout).expect("Should output valid JSON");
roast["id"]
.as_i64()
.expect("roast id should be numeric")
.to_string()
}

View file

@ -1,3 +1,4 @@
pub mod bags_cli;
pub mod helpers;
pub mod roasters_cli;
pub mod roasts_cli;

View file

@ -1,4 +1,4 @@
use crate::helpers::{create_token, run_brewlog, server_info};
use crate::helpers::{create_roaster, create_token, run_brewlog, server_info};
use serde_json::Value;
#[test]
@ -62,28 +62,7 @@ fn test_list_roasters_shows_added_roaster() {
let token = create_token("test-list-roasters");
// Add a roaster
let add_output = run_brewlog(
&[
"add-roaster",
"--name",
"Example Roasters",
"--country",
"USA",
],
&[("BREWLOG_TOKEN", &token)],
);
assert!(
add_output.status.success(),
"Failed to add roaster: {}",
String::from_utf8_lossy(&add_output.stderr)
);
let stdout = String::from_utf8_lossy(&add_output.stdout);
let added_roaster: Value = serde_json::from_str(&stdout).expect("Should output valid JSON");
let roaster_id = added_roaster["id"]
.as_i64()
.expect("roaster id should be numeric");
let roaster_id = create_roaster("Example Roasters", &token);
// List roasters
let list_output = run_brewlog(&["list-roasters"], &[]);
@ -100,7 +79,7 @@ fn test_list_roasters_shows_added_roaster() {
// Find our roaster in the list
let found = roasters_array
.iter()
.any(|r| r["id"].as_i64() == Some(roaster_id));
.any(|r| r["id"].as_i64().unwrap().to_string() == roaster_id);
assert!(found, "Should find the added roaster in the list");
}

View file

@ -1,4 +1,4 @@
use crate::helpers::{create_token, run_brewlog, server_info};
use crate::helpers::{create_roaster, create_token, run_brewlog, server_info};
use serde_json::Value;
#[test]
@ -35,32 +35,14 @@ fn test_add_roast_with_authentication() {
let token = create_token("test-add-roast");
// First create a roaster
let roaster_output = run_brewlog(
&[
"add-roaster",
"--name",
"Test Roasters Add",
"--country",
"UK",
],
&[("BREWLOG_TOKEN", &token)],
);
assert!(roaster_output.status.success());
let roaster_stdout = String::from_utf8_lossy(&roaster_output.stdout);
let roaster: Value = serde_json::from_str(&roaster_stdout).expect("Should output valid JSON");
let roaster_id = roaster["id"]
.as_i64()
.expect("roaster id should be numeric");
let roaster_id_arg = roaster_id.to_string();
let roaster_id = create_roaster("Test Roasters Add", &token);
// Now add a roast
let output = run_brewlog(
&[
"add-roast",
"--roaster-id",
&roaster_id_arg,
&roaster_id,
"--name",
"Ethiopian Yirgacheffe",
"--origin",
@ -87,7 +69,10 @@ fn test_add_roast_with_authentication() {
let roast: Value = serde_json::from_str(&stdout).expect("Should output valid JSON");
assert_eq!(roast["name"], "Ethiopian Yirgacheffe");
assert_eq!(roast["roaster_id"].as_i64(), Some(roaster_id));
assert_eq!(
roast["roaster_id"].as_i64().unwrap().to_string(),
roaster_id
);
assert!(roast["id"].is_i64(), "Should have an ID");
}
@ -113,30 +98,14 @@ fn test_list_roasts_shows_added_roast() {
let token = create_token("test-list-roasts");
// First create a roaster
let roaster_output = run_brewlog(
&[
"add-roaster",
"--name",
"Test Roasters List",
"--country",
"UK",
],
&[("BREWLOG_TOKEN", &token)],
);
let roaster_stdout = String::from_utf8_lossy(&roaster_output.stdout);
let roaster: Value = serde_json::from_str(&roaster_stdout).unwrap();
let roaster_id = roaster["id"]
.as_i64()
.expect("roaster id should be numeric");
let roaster_id_arg = roaster_id.to_string();
let roaster_id = create_roaster("Test Roasters List", &token);
// Add a roast
let add_output = run_brewlog(
&[
"add-roast",
"--roaster-id",
&roaster_id_arg,
&roaster_id,
"--name",
"Colombian Supremo",
"--origin",