app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 56b20b7333b887f4524fe7c9da323fbb4b25e825
parent 739a9658bdc5ec66ff24d10a489d0dca4c39b944
Author: triesap <tyson@radroots.org>
Date:   Tue, 28 Apr 2026 19:13:46 +0000

tests: prove pack day batch workflow

- add no-printer workflow coverage for batch print success and queue failure
- expose the batch print executor injection hook to crate-local tests
- keep the action presentation proof under the workflow filter
- run the workflow filter from the checked-in app validation script

Diffstat:
Mcrates/launchers/desktop/src/pack_day_print.rs | 8++++----
Mcrates/launchers/desktop/src/runtime.rs | 105++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mcrates/launchers/desktop/src/window.rs | 2+-
Mscripts/check.sh | 1+
4 files changed, 110 insertions(+), 6 deletions(-)

diff --git a/crates/launchers/desktop/src/pack_day_print.rs b/crates/launchers/desktop/src/pack_day_print.rs @@ -48,7 +48,7 @@ pub struct PackDayBatchPrintCommandPlan { } #[derive(Clone, Debug, Eq, PartialEq)] -struct PackDayPrintCommandResult { +pub(crate) struct PackDayPrintCommandResult { success: bool, exit_code: Option<i32>, stderr: String, @@ -56,7 +56,7 @@ struct PackDayPrintCommandResult { impl PackDayPrintCommandResult { #[cfg(test)] - fn succeeded() -> Self { + pub(crate) fn succeeded() -> Self { Self { success: true, exit_code: Some(0), @@ -65,7 +65,7 @@ impl PackDayPrintCommandResult { } #[cfg(test)] - fn failed(exit_code: Option<i32>, stderr: impl Into<String>) -> Self { + pub(crate) fn failed(exit_code: Option<i32>, stderr: impl Into<String>) -> Self { Self { success: false, exit_code, @@ -819,7 +819,7 @@ fn execute_pack_day_print_plan_with( }) } -fn execute_pack_day_batch_print_plan_with( +pub(crate) fn execute_pack_day_batch_print_plan_with( plan: &PackDayBatchPrintCommandPlan, mut run_command: impl FnMut( &PackDayPrintCommandPlan, diff --git a/crates/launchers/desktop/src/runtime.rs b/crates/launchers/desktop/src/runtime.rs @@ -4875,7 +4875,8 @@ mod tests { }; use crate::pack_day_host_handoff::PackDayHostHandoffError; use crate::pack_day_print::{ - prepared_customer_label_asset_root, PackDayBatchPrintError, PackDayPrintError, + execute_pack_day_batch_print_plan_with, prepared_customer_label_asset_root, + PackDayBatchPrintError, PackDayPrintCommandResult, PackDayPrintError, }; #[derive(Clone)] @@ -7848,6 +7849,108 @@ mod tests { } #[test] + fn pack_day_batch_workflow_success_submits_frozen_v1_and_records_success() { + let (runtime, paths) = bootstrapped_runtime("pack_day_batch_workflow_success"); + let (_, farm_id) = provision_ready_farmer_account(&runtime); + + seed_order_workspace(&runtime, farm_id); + assert!(runtime.open_pack_day(None).expect("pack day should open")); + assert!(runtime + .export_pack_day() + .expect("pack day export should succeed")); + + let (request, plan) = runtime + .prepare_pack_day_batch_print() + .expect("batch print should prepare") + .expect("batch print should produce a plan"); + let mut submitted = Vec::new(); + + execute_pack_day_batch_print_plan_with(&plan, |print_plan| { + submitted.push(PackDayBatchPrintArtifact::from_print_kind(print_plan.kind)); + Ok(PackDayPrintCommandResult::succeeded()) + }) + .expect("batch print execution should succeed"); + + assert_eq!(submitted, Vec::from(PackDayBatchPrintArtifact::all_v1())); + assert!(runtime + .finish_pack_day_batch_print(request.clone(), Ok(())) + .expect("batch print success should apply")); + + let summary = runtime.summary(); + let batch_print = &summary.pack_day_projection.batch_print; + assert_eq!(batch_print.status, PackDayBatchPrintStatus::Succeeded); + assert_eq!(batch_print.request, Some(request)); + assert_eq!(batch_print.failed_artifact, None); + assert_eq!(batch_print.failure, None); + + cleanup_bootstrapped_runtime_paths(&paths); + } + + #[test] + fn pack_day_batch_workflow_queue_failure_records_failed_artifact_state() { + let (runtime, paths) = bootstrapped_runtime("pack_day_batch_workflow_queue_failure"); + let (_, farm_id) = provision_ready_farmer_account(&runtime); + + seed_order_workspace(&runtime, farm_id); + assert!(runtime.open_pack_day(None).expect("pack day should open")); + assert!(runtime + .export_pack_day() + .expect("pack day export should succeed")); + + let (request, plan) = runtime + .prepare_pack_day_batch_print() + .expect("batch print should prepare") + .expect("batch print should produce a plan"); + let mut submitted = Vec::new(); + + let execution_error = execute_pack_day_batch_print_plan_with(&plan, |print_plan| { + submitted.push(PackDayBatchPrintArtifact::from_print_kind(print_plan.kind)); + match print_plan.kind { + PackDayPrintKind::PrintPackSheet => Ok(PackDayPrintCommandResult::succeeded()), + PackDayPrintKind::PrintPickupRoster => Ok(PackDayPrintCommandResult::failed( + Some(2), + "lp stopped before submit", + )), + PackDayPrintKind::PrintCustomerLabels => { + panic!("batch should stop before customer labels") + } + } + }) + .expect_err("batch print execution should fail"); + + assert_eq!( + submitted, + vec![ + PackDayBatchPrintArtifact::from_print_kind(PackDayPrintKind::PrintPackSheet), + PackDayBatchPrintArtifact::from_print_kind(PackDayPrintKind::PrintPickupRoster), + ] + ); + let failed_artifact = + PackDayBatchPrintArtifact::from_print_kind(PackDayPrintKind::PrintPickupRoster); + let runtime_error = runtime + .finish_pack_day_batch_print(request.clone(), Err(execution_error)) + .expect_err("batch print failure should surface"); + assert!(matches!( + runtime_error, + DesktopAppRuntimeCommandError::PackDayBatchPrint(PackDayBatchPrintError::QueueExit { + .. + }) + )); + + let summary = runtime.summary(); + let batch_print = &summary.pack_day_projection.batch_print; + assert_eq!(batch_print.status, PackDayBatchPrintStatus::Failed); + assert_eq!(batch_print.request, Some(request)); + assert_eq!(batch_print.failed_artifact, Some(failed_artifact)); + assert_eq!( + batch_print.failure, + Some(PackDayBatchPrintFailureKind::QueueExit) + ); + + cleanup_bootstrapped_runtime_paths(&paths); + } + + #[test] fn runtime_finish_pack_day_print_records_failures_in_state() { let (runtime, paths) = bootstrapped_runtime("pack_day_print_failure"); let (_, farm_id) = provision_ready_farmer_account(&runtime); diff --git a/crates/launchers/desktop/src/window.rs b/crates/launchers/desktop/src/window.rs @@ -13841,7 +13841,7 @@ mod tests { } #[test] - fn pack_day_batch_print_action_only_surfaces_after_a_successful_export() { + fn pack_day_batch_workflow_action_only_surfaces_after_a_successful_export() { let temp_dir = TestDirectory::new(); write_artifact(temp_dir.path(), "pack_sheet.txt"); write_artifact(temp_dir.path(), "pickup_roster.txt"); diff --git a/scripts/check.sh b/scripts/check.sh @@ -11,6 +11,7 @@ cargo test -p radroots_app_state pack_day cargo test -p radroots_app_i18n pack_day cargo test -p radroots_app pack_day_print cargo test -p radroots_app pack_day_batch +cargo test -p radroots_app pack_day_batch_workflow cargo test -p radroots_app source_guards cargo check -p radroots_app