diff --git a/templates/pages/edit_bag.html b/templates/pages/edit_bag.html index ddb43e9..d21a39e 100644 --- a/templates/pages/edit_bag.html +++ b/templates/pages/edit_bag.html @@ -15,7 +15,7 @@ data-signals:_submit-error="''" data-signals:_roast-date="'{{ roast_date }}'" data-signals:_amount="{{ amount }}" - data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/bags/{{ id }}')" + data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/bags/{{ id }}', {contentType: 'form'})" data-on:datastar-fetch="if (!$_submitting) return; if (evt.detail.type === 'finished') { $_submitting = false; sessionStorage.setItem('toast', 'Bag updated'); window.location.href = evt.detail.response.headers.get('location') || '/bags/{{ id }}' } else if (evt.detail.type === 'error') { $_submitting = false; $_submitError = 'Failed to save changes.' }" diff --git a/templates/pages/edit_brew.html b/templates/pages/edit_brew.html index 3186979..d2dbed8 100644 --- a/templates/pages/edit_brew.html +++ b/templates/pages/edit_brew.html @@ -19,8 +19,13 @@ data-signals:_water-volume="{{ water_volume }}" data-signals:_water-temp="{{ water_temp }}" data-signals:_brew-time="{{ brew_time }}" - data-signals:_quick-notes="'{{ quick_notes }}'" - data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/brews/{{ id }}')" + data-signals:_qn-good="{% if quick_notes.contains("good") %}true{% else %}false{% endif %}" + data-signals:_qn-too-fast="{% if quick_notes.contains("too-fast") %}true{% else %}false{% endif %}" + data-signals:_qn-too-slow="{% if quick_notes.contains("too-slow") %}true{% else %}false{% endif %}" + data-signals:_qn-too-hot="{% if quick_notes.contains("too-hot") %}true{% else %}false{% endif %}" + data-signals:_qn-under-extracted="{% if quick_notes.contains("under-extracted") %}true{% else %}false{% endif %}" + data-signals:_qn-over-extracted="{% if quick_notes.contains("over-extracted") %}true{% else %}false{% endif %}" + data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/brews/{{ id }}', {contentType: 'form'})" data-on:datastar-fetch="if (!$_submitting) return; if (evt.detail.type === 'finished') { $_submitting = false; sessionStorage.setItem('toast', 'Brew updated'); window.location.href = evt.detail.response.headers.get('location') || '/brews/{{ id }}' } else if (evt.detail.type === 'error') { $_submitting = false; $_submitError = 'Failed to save changes.' }" @@ -301,19 +306,55 @@

Quick Notes

-
+ {{ img::deferred_upload("edit-brew-image", "Brew Image") }} diff --git a/templates/pages/edit_cafe.html b/templates/pages/edit_cafe.html index 6112002..6e43c7a 100644 --- a/templates/pages/edit_cafe.html +++ b/templates/pages/edit_cafe.html @@ -20,7 +20,7 @@ data-signals:_latitude="{{ latitude }}" data-signals:_longitude="{{ longitude }}" data-signals:_website="'{{ website }}'" - data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/cafes/{{ id }}')" + data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/cafes/{{ id }}', {contentType: 'form'})" data-on:datastar-fetch="if (!$_submitting) return; if (evt.detail.type === 'finished') { $_submitting = false; sessionStorage.setItem('toast', 'Cafe updated'); window.location.href = evt.detail.response.headers.get('location') || '/cafes/{{ id }}' } else if (evt.detail.type === 'error') { $_submitting = false; $_submitError = 'Failed to save changes.' }" diff --git a/templates/pages/edit_cup.html b/templates/pages/edit_cup.html index aacf872..e92c829 100644 --- a/templates/pages/edit_cup.html +++ b/templates/pages/edit_cup.html @@ -14,7 +14,7 @@ class="flex flex-col gap-4" data-signals:_submitting="false" data-signals:_submit-error="''" - data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/cups/{{ id }}')" + data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/cups/{{ id }}', {contentType: 'form'})" data-on:datastar-fetch="if (!$_submitting) return; if (evt.detail.type === 'finished') { $_submitting = false; sessionStorage.setItem('toast', 'Cup updated'); window.location.href = evt.detail.response.headers.get('location') || '/cups/{{ id }}' } else if (evt.detail.type === 'error') { $_submitting = false; $_submitError = 'Failed to save changes.' }" diff --git a/templates/pages/edit_gear.html b/templates/pages/edit_gear.html index 2ff71ee..6db4047 100644 --- a/templates/pages/edit_gear.html +++ b/templates/pages/edit_gear.html @@ -16,7 +16,7 @@ data-signals:_submit-error="''" data-signals:_make="'{{ make }}'" data-signals:_model="'{{ model }}'" - data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/gear/{{ id }}')" + data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/gear/{{ id }}', {contentType: 'form'})" data-on:datastar-fetch="if (!$_submitting) return; if (evt.detail.type === 'finished') { $_submitting = false; sessionStorage.setItem('toast', 'Gear updated'); window.location.href = evt.detail.response.headers.get('location') || '/gear/{{ id }}' } else if (evt.detail.type === 'error') { $_submitting = false; $_submitError = 'Failed to save changes.' }" diff --git a/templates/pages/edit_roast.html b/templates/pages/edit_roast.html index 1eabd74..2234f34 100644 --- a/templates/pages/edit_roast.html +++ b/templates/pages/edit_roast.html @@ -20,7 +20,7 @@ data-signals:_producer="'{{ producer }}'" data-signals:_process="'{{ process }}'" data-signals:_tasting-notes="'{{ tasting_notes }}'" - data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/roasts/{{ id }}')" + data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/roasts/{{ id }}', {contentType: 'form'})" data-on:datastar-fetch="if (!$_submitting) return; if (evt.detail.type === 'finished') { $_submitting = false; sessionStorage.setItem('toast', 'Roast updated'); window.location.href = evt.detail.response.headers.get('location') || '/roasts/{{ id }}' } else if (evt.detail.type === 'error') { $_submitting = false; $_submitError = 'Failed to save changes.' }" diff --git a/templates/pages/edit_roaster.html b/templates/pages/edit_roaster.html index a99d7ba..6ca7b3f 100644 --- a/templates/pages/edit_roaster.html +++ b/templates/pages/edit_roaster.html @@ -18,7 +18,7 @@ data-signals:_country="'{{ country }}'" data-signals:_city="'{{ city }}'" data-signals:_homepage="'{{ homepage }}'" - data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/roasters/{{ id }}')" + data-on:submit="$_submitting = true; $_submitError = ''; @put('/api/v1/roasters/{{ id }}', {contentType: 'form'})" data-on:datastar-fetch="if (!$_submitting) return; if (evt.detail.type === 'finished') { $_submitting = false; sessionStorage.setItem('toast', 'Roaster updated'); window.location.href = evt.detail.response.headers.get('location') || '/roasters/{{ id }}' } else if (evt.detail.type === 'error') { $_submitting = false; $_submitError = 'Failed to save changes.' }" diff --git a/tests/cli/brews_cli.rs b/tests/cli/brews_cli.rs index fabb10a..fe66e44 100644 --- a/tests/cli/brews_cli.rs +++ b/tests/cli/brews_cli.rs @@ -1,6 +1,7 @@ use crate::helpers::{ - create_bag, create_gear, create_roast, create_roaster, create_token, run_brewlog, + create_bag, create_brew, create_gear, create_roast, create_roaster, create_token, run_brewlog, }; +use crate::test_macros::define_cli_auth_test; #[test] fn brew_add_creates_brew_via_api() { @@ -235,3 +236,45 @@ fn brew_delete_removes_brew() { "brew get should fail after deletion" ); } + +define_cli_auth_test!( + test_update_brew_requires_authentication, + &["brew", "update", "--id", "123", "--coffee-weight", "16.0"] +); + +#[test] +fn test_update_brew_with_authentication() { + let token = create_token("test-update-brew"); + let roaster_id = create_roaster("Update Brew Roaster", &token); + let roast_id = create_roast(&roaster_id, "Update Brew Roast", &token); + let bag_id = create_bag(&roast_id, &token); + let grinder_id = create_gear("grinder", "Weber", "Key", &token); + let brewer_id = create_gear("brewer", "Origami", "Air", &token); + let brew_id = create_brew(&bag_id, &grinder_id, &brewer_id, &token); + + let output = run_brewlog( + &[ + "brew", + "update", + "--id", + &brew_id, + "--coffee-weight", + "16.0", + "--water-temp", + "94.0", + ], + &[("BREWLOG_TOKEN", &token)], + ); + + assert!( + output.status.success(), + "brew update should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); + + let stdout = String::from_utf8_lossy(&output.stdout); + let brew: serde_json::Value = serde_json::from_str(&stdout).expect("Should output valid JSON"); + + assert_eq!(brew["coffee_weight"], 16.0); + assert_eq!(brew["water_temp"], 94.0); +} diff --git a/tests/cli/cups_cli.rs b/tests/cli/cups_cli.rs new file mode 100644 index 0000000..96af9fb --- /dev/null +++ b/tests/cli/cups_cli.rs @@ -0,0 +1,36 @@ +use crate::helpers::{ + create_cafe, create_cup, create_roast, create_roaster, create_token, run_brewlog, +}; +use crate::test_macros::define_cli_auth_test; + +define_cli_auth_test!( + test_update_cup_requires_authentication, + &["cup", "update", "--id", "123", "--roast-id", "1"] +); + +#[test] +fn test_update_cup_with_authentication() { + let token = create_token("test-update-cup"); + let roaster_id = create_roaster("Update Cup Roaster", &token); + let roast_id = create_roast(&roaster_id, "Update Cup Roast", &token); + let cafe_id = create_cafe("Update Cup Cafe", "London", "UK", "51.5", "-0.1", &token); + let cup_id = create_cup(&roast_id, &cafe_id, &token); + + // Create a second roast to update the cup to + let roast_id_2 = create_roast(&roaster_id, "Update Cup Roast 2", &token); + + let output = run_brewlog( + &["cup", "update", "--id", &cup_id, "--roast-id", &roast_id_2], + &[("BREWLOG_TOKEN", &token)], + ); + + assert!( + output.status.success(), + "cup update should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); + + let stdout = String::from_utf8_lossy(&output.stdout); + let cup: serde_json::Value = serde_json::from_str(&stdout).expect("Should output valid JSON"); + assert!(cup["id"].is_i64(), "cup should have an id"); +} diff --git a/tests/cli/helpers.rs b/tests/cli/helpers.rs index 0e935b4..6ebaf2c 100644 --- a/tests/cli/helpers.rs +++ b/tests/cli/helpers.rs @@ -316,3 +316,28 @@ pub fn create_gear(category: &str, make: &str, model: &str, token: &str) -> Stri "gear", ) } + +pub fn create_brew(bag_id: &str, grinder_id: &str, brewer_id: &str, token: &str) -> String { + create_entity_cli( + &[ + "brew", + "add", + "--bag-id", + bag_id, + "--grinder-id", + grinder_id, + "--brewer-id", + brewer_id, + ], + token, + "brew", + ) +} + +pub fn create_cup(roast_id: &str, cafe_id: &str, token: &str) -> String { + create_entity_cli( + &["cup", "add", "--roast-id", roast_id, "--cafe-id", cafe_id], + token, + "cup", + ) +} diff --git a/tests/cli/main.rs b/tests/cli/main.rs index 23d2ca6..e19073f 100644 --- a/tests/cli/main.rs +++ b/tests/cli/main.rs @@ -2,6 +2,7 @@ pub mod backup_cli; pub mod bags_cli; pub mod brews_cli; pub mod cafes_cli; +pub mod cups_cli; pub mod gear_cli; pub mod helpers; pub mod roasters_cli;