commit 7faace3aab6b2b4a6accb856dca5c44d129d4438
parent dc27eca1611d21a98445e713b2be3c3204b4f083
Author: triesap <tyson@radroots.org>
Date: Wed, 22 Apr 2026 22:07:26 +0000
app: clean pack day prepared print assets
- sweep the prepared customer-label print root during desktop bootstrap
- remove request-scoped prepared assets after label print completion and export resets
- clean partial prepared-output directories when planner writes fail
- add focused pack day tests for bootstrap, completion, re-export, and window-reset cleanup
Diffstat:
2 files changed, 1006 insertions(+), 912 deletions(-)
diff --git a/crates/launchers/desktop/src/pack_day_print.rs b/crates/launchers/desktop/src/pack_day_print.rs
@@ -6,7 +6,8 @@ use std::path::{Component, Path, PathBuf};
use std::process::Command;
use radroots_app_models::{
- PackDayExportArtifactKind, PackDayExportBundle, PackDayPrintKind, PackDayPrintLabelStock,
+ PackDayExportArtifactKind, PackDayExportBundle, PackDayExportInstanceId, PackDayPrintKind,
+ PackDayPrintLabelStock,
};
use thiserror::Error;
@@ -267,6 +268,18 @@ fn io_errors_match(left: &io::Error, right: &io::Error) -> bool {
left.kind() == right.kind() && left.to_string() == right.to_string()
}
+pub(crate) fn cleanup_prepared_customer_label_asset_root() -> io::Result<()> {
+ cleanup_prepared_customer_label_assets_at_path(prepared_customer_label_asset_root())
+}
+
+pub(crate) fn cleanup_prepared_customer_label_assets_for_export_instance(
+ export_instance_id: PackDayExportInstanceId,
+) -> io::Result<()> {
+ cleanup_prepared_customer_label_assets_at_path(
+ prepared_customer_label_asset_directory_for_export_instance(export_instance_id),
+ )
+}
+
pub fn plan_pack_day_print(
bundle: &PackDayExportBundle,
kind: PackDayPrintKind,
@@ -398,6 +411,8 @@ fn prepare_customer_label_stock_asset(
let target_path = prepared_customer_label_asset_path(bundle, stock);
let prepared_asset = render_customer_label_stock_asset(&source_contents, stock);
fs::write(&target_path, prepared_asset).map_err(|source| {
+ let _ =
+ cleanup_prepared_customer_label_assets_for_export_instance(bundle.export_instance_id);
PackDayPrintError::WritePreparedAsset {
kind,
path: target_path.clone(),
@@ -408,10 +423,36 @@ fn prepare_customer_label_stock_asset(
Ok(target_path)
}
+pub(crate) fn prepared_customer_label_asset_root() -> PathBuf {
+ let root = std::env::temp_dir().join(CUSTOMER_LABEL_PREPARED_ASSET_ROOT);
+
+ #[cfg(test)]
+ {
+ root.join(format!("{:?}", std::thread::current().id()))
+ }
+
+ #[cfg(not(test))]
+ {
+ root
+ }
+}
+
+fn cleanup_prepared_customer_label_assets_at_path(path: PathBuf) -> io::Result<()> {
+ match fs::remove_dir_all(&path) {
+ Ok(()) => Ok(()),
+ Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(()),
+ Err(error) => Err(error),
+ }
+}
+
+fn prepared_customer_label_asset_directory_for_export_instance(
+ export_instance_id: PackDayExportInstanceId,
+) -> PathBuf {
+ prepared_customer_label_asset_root().join(export_instance_id.to_string())
+}
+
fn prepared_customer_label_asset_directory(bundle: &PackDayExportBundle) -> PathBuf {
- std::env::temp_dir()
- .join(CUSTOMER_LABEL_PREPARED_ASSET_ROOT)
- .join(bundle.export_instance_id.to_string())
+ prepared_customer_label_asset_directory_for_export_instance(bundle.export_instance_id)
}
fn prepared_customer_label_asset_path(
@@ -642,9 +683,10 @@ fn run_macos_print_command(
#[cfg(test)]
mod tests {
use super::{
- LETTER_MEDIA_OPTION, PackDayPrintCommandResult, PackDayPrintError,
- execute_pack_day_print_plan_with, plan_pack_day_print,
- prepared_customer_label_asset_directory, prepared_customer_label_asset_path,
+ cleanup_prepared_customer_label_asset_root, execute_pack_day_print_plan_with,
+ plan_pack_day_print, prepared_customer_label_asset_directory,
+ prepared_customer_label_asset_path, prepared_customer_label_asset_root,
+ PackDayPrintCommandResult, PackDayPrintError, LETTER_MEDIA_OPTION,
};
use radroots_app_models::{
PackDayExportArtifact, PackDayExportArtifactKind, PackDayExportBundle,
@@ -774,11 +816,10 @@ mod tests {
);
assert!(plan.target_path.is_file());
assert!(!plan.target_path.starts_with(temp_dir.path()));
- assert!(
- plan.target_path
- .to_string_lossy()
- .contains(bundle.export_instance_id.to_string().as_str())
- );
+ assert!(plan
+ .target_path
+ .to_string_lossy()
+ .contains(bundle.export_instance_id.to_string().as_str()));
assert_eq!(
fs::read_to_string(&source_path).expect("source labels should stay untouched"),
"Willow farm\nCasey\nOrder: R-1001\nPickup: North barn\nWindow: 2026-04-23T16:00:00Z to 2026-04-23T19:00:00Z\n\n---\n\nWillow farm\nTaylor\nOrder: R-1002\nPickup: North barn\nWindow: 2026-04-23T16:00:00Z to 2026-04-23T19:00:00Z\n"
@@ -878,7 +919,20 @@ mod tests {
other => panic!("unexpected error: {other:?}"),
}
- let _ = fs::remove_dir_all(prepared_customer_label_asset_directory(&bundle));
+ assert!(!prepared_directory.exists());
+ }
+
+ #[test]
+ fn cleanup_prepared_customer_label_asset_root_removes_existing_directories() {
+ let root = prepared_customer_label_asset_root();
+ let stale_directory = root.join(PackDayExportInstanceId::new().to_string());
+ fs::create_dir_all(&stale_directory).expect("stale prepared directory should create");
+ fs::write(stale_directory.join("stale.ps"), "stale").expect("stale asset should write");
+
+ cleanup_prepared_customer_label_asset_root()
+ .expect("prepared customer label asset root should clean");
+
+ assert!(!root.exists());
}
#[test]
@@ -926,12 +980,10 @@ mod tests {
.expect("pack sheet print plan should build");
assert_eq!(plan.target_path, pack_sheet_path);
- assert!(
- execute_pack_day_print_plan_with(&plan, |_| {
- Ok(PackDayPrintCommandResult::succeeded())
- })
- .is_ok()
- );
+ assert!(execute_pack_day_print_plan_with(&plan, |_| {
+ Ok(PackDayPrintCommandResult::succeeded())
+ })
+ .is_ok());
}
#[test]
diff --git a/crates/launchers/desktop/src/runtime.rs b/crates/launchers/desktop/src/runtime.rs
@@ -5,9 +5,9 @@ use std::sync::{Arc, Mutex, MutexGuard, PoisonError};
use chrono::{Duration, Utc};
use radroots_app_core::{
+ prepare_pack_day_export_bundle_at_data_root, write_prepared_pack_day_export_bundle,
AppBuildIdentity, AppDesktopRuntimePaths, AppRuntimeCapture, AppRuntimeMode,
AppRuntimePathsError, AppRuntimeSnapshot, AppSharedAccountsPaths, PackDayExportWriteError,
- prepare_pack_day_export_bundle_at_data_root, write_prepared_pack_day_export_bundle,
};
use radroots_app_models::{
ActiveSurface, AppActivityContext, AppActivityKind, AppIdentityProjection, AppStartupGate,
@@ -17,12 +17,12 @@ use radroots_app_models::{
FarmSetupProjection, FarmSummary, FarmerSection, FulfillmentWindowId,
LoggedOutStartupProjection, OrderDetailProjection, OrderId, OrderRecoveryProjection,
OrdersFilter, OrdersListProjection, OrdersScreenQueryState, PackDayExportBundle,
- PackDayExportStatus, PackDayHostHandoffKind, PackDayHostHandoffStatus, PackDayPrintKind,
- PackDayPrintStatus, PackDayProjection, PackDayScreenQueryState, PersonalSection,
- PickupLocationRecord, ProductEditorDraft, ProductId, ProductsFilter, ProductsListProjection,
- ProductsSort, RecoveryKind, RecoveryQueueProjection, RecoveryRecordId, RecoveryState,
- ReminderDeadlineProjection, ReminderDeliveryState, ReminderFeedProjection, ReminderId,
- ReminderKind, ReminderLogEntryProjection, ReminderLogProjection, ReminderSurface,
+ PackDayExportInstanceId, PackDayExportStatus, PackDayHostHandoffKind, PackDayHostHandoffStatus,
+ PackDayPrintKind, PackDayPrintStatus, PackDayProjection, PackDayScreenQueryState,
+ PersonalSection, PickupLocationRecord, ProductEditorDraft, ProductId, ProductsFilter,
+ ProductsListProjection, ProductsSort, RecoveryKind, RecoveryQueueProjection, RecoveryRecordId,
+ RecoveryState, ReminderDeadlineProjection, ReminderDeliveryState, ReminderFeedProjection,
+ ReminderId, ReminderKind, ReminderLogEntryProjection, ReminderLogProjection, ReminderSurface,
ReminderUrgency, SettingsAccountProjection, SettingsPreference, SettingsSection, ShellSection,
TodayAgendaProjection,
};
@@ -30,17 +30,17 @@ use radroots_app_remote_signer::{
RadrootsAppRemoteSignerApprovedSession, RadrootsAppRemoteSignerPendingSession,
};
use radroots_app_sqlite::{
- APP_ACTIVITY_CONTEXT_LIMIT, AppSqliteError, AppSqliteStore, BuyerRepeatDemandApplyOutcome,
- DatabaseTarget, StoredPendingSyncOperation, StoredSyncConflict, derive_farm_rules_readiness,
+ derive_farm_rules_readiness, AppSqliteError, AppSqliteStore, BuyerRepeatDemandApplyOutcome,
+ DatabaseTarget, StoredPendingSyncOperation, StoredSyncConflict, APP_ACTIVITY_CONTEXT_LIMIT,
};
use radroots_app_state::{
- APP_STATE_FILE_NAME, AppShellProjection, AppStateCommand, AppStatePersistenceRepository,
+ derive_sync_projection, AppShellProjection, AppStateCommand, AppStatePersistenceRepository,
AppStateStore, AppStateStoreError, BuyerBrowseScreenProjection, BuyerCartScreenProjection,
BuyerOrdersScreenProjection, BuyerSearchScreenProjection, BuyerSearchScreenQueryState,
FarmSetupFlowStage, FarmWorkspaceReadinessProjection, HomeRoute, OrdersScreenProjection,
PackDayExportRequest, PackDayHostHandoffRequest, PackDayPrintRequest, PackDayScreenProjection,
PersistedAppState, PersonalWorkspaceProjection, ProductsScreenProjection,
- ProductsScreenQueryState, derive_sync_projection,
+ ProductsScreenQueryState, APP_STATE_FILE_NAME,
};
use radroots_app_sync::{
AppSyncProjection, AppSyncRequest, AppSyncResult, AppSyncTransport, AppSyncTransportError,
@@ -54,19 +54,23 @@ use tracing::error;
use uuid::Uuid;
use crate::accounts::{
- DesktopAccountsBootstrapError, DesktopAccountsCommandError, DesktopAccountsProjectionError,
- DesktopLocalIdentityImportRequest, bootstrap_desktop_accounts, generate_local_account,
- identity_projection_from_manager, import_local_account, remove_selected_local_key,
- reset_local_device_state, select_active_surface, select_local_account,
+ bootstrap_desktop_accounts, generate_local_account, identity_projection_from_manager,
+ import_local_account, remove_selected_local_key, reset_local_device_state,
+ select_active_surface, select_local_account, DesktopAccountsBootstrapError,
+ DesktopAccountsCommandError, DesktopAccountsProjectionError, DesktopLocalIdentityImportRequest,
};
use crate::pack_day_host_handoff::{
- PackDayHostHandoffCommandPlan, PackDayHostHandoffError, plan_pack_day_host_handoff,
+ plan_pack_day_host_handoff, PackDayHostHandoffCommandPlan, PackDayHostHandoffError,
+};
+use crate::pack_day_print::{
+ cleanup_prepared_customer_label_asset_root,
+ cleanup_prepared_customer_label_assets_for_export_instance, plan_pack_day_print,
+ PackDayPrintCommandPlan, PackDayPrintError,
};
-use crate::pack_day_print::{PackDayPrintCommandPlan, PackDayPrintError, plan_pack_day_print};
use crate::remote_signer::{
- DesktopRemoteSignerError, DesktopRemoteSignerPaths, activate_pending_session,
- apply_remote_signer_custody, clear_pending_session, load_pending_session, purge_all_state,
- reconcile_startup, store_pending_session,
+ activate_pending_session, apply_remote_signer_custody, clear_pending_session,
+ load_pending_session, purge_all_state, reconcile_startup, store_pending_session,
+ DesktopRemoteSignerError, DesktopRemoteSignerPaths,
};
const APP_DATABASE_FILE_NAME: &str = "app.sqlite3";
@@ -884,6 +888,14 @@ impl DesktopAppRuntimeState {
default_nostr_relay_url: String,
runtime_snapshot: AppRuntimeSnapshot,
) -> Result<Self, DesktopAppRuntimeBootstrapError> {
+ if let Err(error) = cleanup_prepared_customer_label_asset_root() {
+ error!(
+ target: "pack_day",
+ event = "pack_day.print_prepared_asset_bootstrap_sweep_failed",
+ error = %error,
+ "failed to sweep prepared pack day print assets during bootstrap"
+ );
+ }
let database_path = paths.app.data.join(APP_DATABASE_FILE_NAME);
let sqlite_store = AppSqliteStore::open(DatabaseTarget::Path(database_path.clone()))?;
let database_schema_version = sqlite_store.schema_version()?;
@@ -1777,6 +1789,7 @@ impl DesktopAppRuntimeState {
let Some(farm_id) = self.selected_farm_id() else {
return Ok(false);
};
+ let previous_export_instance_id = self.current_pack_day_export_instance_id();
let Some(fulfillment_window_id) = self
.state_store
.pack_day_projection()
@@ -1808,6 +1821,10 @@ impl DesktopAppRuntimeState {
let _ = self
.state_store
.apply_in_memory(AppStateCommand::begin_pack_day_export(request.clone()));
+ self.cleanup_prepared_pack_day_print_assets_if_export_changed(
+ previous_export_instance_id,
+ "export_reset",
+ );
let prepared =
prepare_pack_day_export_bundle_at_data_root(data_root.as_path(), &source, Utc::now());
@@ -1911,14 +1928,32 @@ impl DesktopAppRuntimeState {
return Ok(false);
}
+ let cleanup_export_instance_id = (request.kind == PackDayPrintKind::PrintCustomerLabels)
+ .then_some(request.export_instance_id);
+
match result {
- Ok(()) => Ok(self
- .state_store
- .apply_in_memory(AppStateCommand::succeed_pack_day_print(request))),
+ Ok(()) => {
+ let changed = self
+ .state_store
+ .apply_in_memory(AppStateCommand::succeed_pack_day_print(request));
+ if let Some(export_instance_id) = cleanup_export_instance_id {
+ self.cleanup_prepared_pack_day_print_assets_for_export_instance(
+ export_instance_id,
+ "print_completion",
+ );
+ }
+ Ok(changed)
+ }
Err(error) => {
let _ = self
.state_store
.apply_in_memory(AppStateCommand::fail_pack_day_print(request));
+ if let Some(export_instance_id) = cleanup_export_instance_id {
+ self.cleanup_prepared_pack_day_print_assets_for_export_instance(
+ export_instance_id,
+ "print_completion",
+ );
+ }
Err(error.into())
}
}
@@ -2348,6 +2383,7 @@ impl DesktopAppRuntimeState {
context: &DesktopSelectedAccountContext,
include_personal: bool,
) -> bool {
+ let previous_export_instance_id = self.current_pack_day_export_instance_id();
let personal_changed = if include_personal {
self.state_store
.apply_in_memory(AppStateCommand::replace_personal_projection(
@@ -2447,6 +2483,10 @@ impl DesktopAppRuntimeState {
self.close_product_editor()
};
let shell_changed = self.sync_truthful_farmer_section();
+ self.cleanup_prepared_pack_day_print_assets_if_export_changed(
+ previous_export_instance_id,
+ "context_refresh",
+ );
personal_changed
|| farm_setup_changed
@@ -3128,6 +3168,7 @@ impl DesktopAppRuntimeState {
&mut self,
query: PackDayScreenQueryState,
) -> Result<bool, AppSqliteError> {
+ let previous_export_instance_id = self.current_pack_day_export_instance_id();
let fulfillment_window_changed =
self.state_store
.apply_in_memory(AppStateCommand::set_pack_day_fulfillment_window(
@@ -3143,6 +3184,10 @@ impl DesktopAppRuntimeState {
&continuity_state,
)?;
let context_changed = self.apply_selected_account_context(&selected_account_context);
+ self.cleanup_prepared_pack_day_print_assets_if_export_changed(
+ previous_export_instance_id,
+ "query_reset",
+ );
Ok(fulfillment_window_changed || context_changed)
}
@@ -3261,6 +3306,46 @@ impl DesktopAppRuntimeState {
(fulfillment_window.fulfillment_window_id == bundle.fulfillment_window_id).then_some(bundle)
}
+ fn current_pack_day_export_instance_id(&self) -> Option<PackDayExportInstanceId> {
+ self.current_pack_day_export_bundle()
+ .map(|bundle| bundle.export_instance_id)
+ }
+
+ fn cleanup_prepared_pack_day_print_assets_for_export_instance(
+ &self,
+ export_instance_id: PackDayExportInstanceId,
+ trigger: &'static str,
+ ) {
+ if let Err(error) =
+ cleanup_prepared_customer_label_assets_for_export_instance(export_instance_id)
+ {
+ error!(
+ target: "pack_day",
+ event = "pack_day.print_prepared_asset_cleanup_failed",
+ trigger,
+ export_instance_id = %export_instance_id,
+ error = %error,
+ "failed to clean prepared pack day print assets"
+ );
+ }
+ }
+
+ fn cleanup_prepared_pack_day_print_assets_if_export_changed(
+ &self,
+ previous_export_instance_id: Option<PackDayExportInstanceId>,
+ trigger: &'static str,
+ ) {
+ let current_export_instance_id = self.current_pack_day_export_instance_id();
+ if let Some(export_instance_id) = previous_export_instance_id
+ .filter(|export_instance_id| Some(*export_instance_id) != current_export_instance_id)
+ {
+ self.cleanup_prepared_pack_day_print_assets_for_export_instance(
+ export_instance_id,
+ trigger,
+ );
+ }
+ }
+
fn current_pack_day_host_handoff_request_matches(
&self,
request: &PackDayHostHandoffRequest,
@@ -4624,23 +4709,23 @@ mod tests {
FarmOperatingRulesRecord, FarmOrderMethod, FarmProfileRecord, FarmReadiness,
FarmReadinessBlocker, FarmSetupDraft, FarmSetupProjection, FarmSummary,
FarmerActivationProjection, FarmerSection, FulfillmentWindowId, FulfillmentWindowRecord,
- LoggedOutStartupProjection, OrderId, OrderStatus, OrdersFilter, PackDayExportStatus,
- PackDayHostHandoffKind, PackDayHostHandoffStatus, PackDayPackListRow, PackDayPrintKind,
- PackDayPrintStatus, PackDayProductTotalRow, PackDayProjection, PackDayRosterRow,
- PersonalSection, PickupLocationId, PickupLocationRecord, ProductEditorDraft, ProductStatus,
- ProductsFilter, ProductsSort, RecoveryKind, RecoveryRecordId, ReminderDeliveryState,
- ReminderFeedProjection, ReminderKind, SelectedSurfaceProjection, SettingsPreference,
- SettingsSection, ShellSection, TodayAgendaProjection, TodaySetupTask, TodaySetupTaskKind,
- TodaySummary,
+ LoggedOutStartupProjection, OrderId, OrderStatus, OrdersFilter, PackDayExportInstanceId,
+ PackDayExportStatus, PackDayHostHandoffKind, PackDayHostHandoffStatus, PackDayPackListRow,
+ PackDayPrintKind, PackDayPrintStatus, PackDayProductTotalRow, PackDayProjection,
+ PackDayRosterRow, PersonalSection, PickupLocationId, PickupLocationRecord,
+ ProductEditorDraft, ProductStatus, ProductsFilter, ProductsSort, RecoveryKind,
+ RecoveryRecordId, ReminderDeliveryState, ReminderFeedProjection, ReminderKind,
+ SelectedSurfaceProjection, SettingsPreference, SettingsSection, ShellSection,
+ TodayAgendaProjection, TodaySetupTask, TodaySetupTaskKind, TodaySummary,
};
use radroots_app_remote_signer::{
RadrootsAppRemoteSignerPendingSession, RadrootsAppRemoteSignerSessionRecord,
};
- use radroots_app_sqlite::{AppSqliteStore, DatabaseTarget, latest_schema_version};
+ use radroots_app_sqlite::{latest_schema_version, AppSqliteStore, DatabaseTarget};
use radroots_app_state::{
- APP_STATE_FILE_NAME, AppStateCommand, AppStatePersistenceRepository, AppStateRepository,
+ AppStateCommand, AppStatePersistenceRepository, AppStateRepository,
AppStateRepositoryError, AppStateStore, AppStateStoreError, FileBackedAppStateRepository,
- HomeRoute,
+ HomeRoute, APP_STATE_FILE_NAME,
};
use radroots_app_sync::{
AppSyncRequest, AppSyncResult, AppSyncRunStatus, AppSyncTransport, AppSyncTransportError,
@@ -4657,13 +4742,13 @@ mod tests {
use crate::accounts::DesktopLocalIdentityImportRequest;
use super::{
- APP_DATABASE_FILE_NAME, DesktopAppRuntime, DesktopAppRuntimeActivityContextError,
+ default_sync_transport, DesktopAppRuntime, DesktopAppRuntimeActivityContextError,
DesktopAppRuntimeCommandError, DesktopAppRuntimeMetadataSummary, DesktopAppRuntimeState,
- DesktopAppSyncStatusSummary, DesktopRemoteSignerPaths, SYNC_TRANSPORT_UNAVAILABLE_MESSAGE,
- default_sync_transport,
+ DesktopAppSyncStatusSummary, DesktopRemoteSignerPaths, APP_DATABASE_FILE_NAME,
+ SYNC_TRANSPORT_UNAVAILABLE_MESSAGE,
};
use crate::pack_day_host_handoff::PackDayHostHandoffError;
- use crate::pack_day_print::PackDayPrintError;
+ use crate::pack_day_print::{prepared_customer_label_asset_root, PackDayPrintError};
#[derive(Clone)]
struct SharedRecordedSyncTransport(Arc<Mutex<RecordedAppSyncTransport>>);
@@ -4775,12 +4860,10 @@ mod tests {
assert_eq!(summary.startup_gate, AppStartupGate::SetupRequired);
assert_eq!(summary.home_route, HomeRoute::SetupRequired);
assert!(summary.settings_account_projection.roster.is_empty());
- assert!(
- summary
- .settings_account_projection
- .selected_account
- .is_none()
- );
+ assert!(summary
+ .settings_account_projection
+ .selected_account
+ .is_none());
assert_eq!(
summary.logged_out_startup,
LoggedOutStartupProjection::default()
@@ -4888,12 +4971,10 @@ mod tests {
.expect("pending sync operation should save");
}
- assert!(
- runtime
- .lock_state_mut()
- .refresh_selected_account_sync()
- .expect("sync status should refresh")
- );
+ assert!(runtime
+ .lock_state_mut()
+ .refresh_selected_account_sync()
+ .expect("sync status should refresh"));
let summary = runtime.summary();
@@ -4947,11 +5028,9 @@ mod tests {
}),
);
- assert!(
- runtime
- .open_new_product_editor()
- .expect("new product editor should open")
- );
+ assert!(runtime
+ .open_new_product_editor()
+ .expect("new product editor should open"));
let summary = runtime.summary();
let pending_operations = runtime
@@ -4976,11 +5055,9 @@ mod tests {
let runtime = memory_runtime();
let (account_id, _) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .open_new_product_editor()
- .expect("new product editor should open")
- );
+ assert!(runtime
+ .open_new_product_editor()
+ .expect("new product editor should open"));
let recorded = install_recorded_sync_transport(
&runtime,
@@ -4997,11 +5074,9 @@ mod tests {
}),
);
- assert!(
- runtime
- .sync_on_app_launch()
- .expect("launch sync should succeed")
- );
+ assert!(runtime
+ .sync_on_app_launch()
+ .expect("launch sync should succeed"));
let summary = runtime.summary();
let recorded = recorded.lock().expect("recorded transport");
@@ -5040,11 +5115,9 @@ mod tests {
let runtime = memory_runtime();
let (_, _) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .open_new_product_editor()
- .expect("new product editor should open")
- );
+ assert!(runtime
+ .open_new_product_editor()
+ .expect("new product editor should open"));
let recorded = install_recorded_sync_transport(
&runtime,
@@ -5061,11 +5134,9 @@ mod tests {
}),
);
- assert!(
- runtime
- .sync_on_foreground_resume()
- .expect("resume sync should succeed")
- );
+ assert!(runtime
+ .sync_on_foreground_resume()
+ .expect("resume sync should succeed"));
let request = recorded
.lock()
@@ -5082,17 +5153,13 @@ mod tests {
let runtime = memory_runtime();
let (account_id, _) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .open_new_product_editor()
- .expect("new product editor should open")
- );
+ assert!(runtime
+ .open_new_product_editor()
+ .expect("new product editor should open"));
- assert!(
- runtime
- .sync_on_manual_refresh()
- .expect("manual refresh should complete")
- );
+ assert!(runtime
+ .sync_on_manual_refresh()
+ .expect("manual refresh should complete"));
let summary = runtime.summary();
let pending_operations = runtime
@@ -5112,15 +5179,13 @@ mod tests {
SyncCheckpointState::Failed
);
assert_eq!(summary.sync_status.pending_write_count, 1);
- assert!(
- summary
- .sync_status
- .projection
- .checkpoint
- .last_error_message
- .as_deref()
- .is_some_and(|message| { message.contains(SYNC_TRANSPORT_UNAVAILABLE_MESSAGE) })
- );
+ assert!(summary
+ .sync_status
+ .projection
+ .checkpoint
+ .last_error_message
+ .as_deref()
+ .is_some_and(|message| { message.contains(SYNC_TRANSPORT_UNAVAILABLE_MESSAGE) }));
assert_eq!(pending_operations.len(), 1);
assert_eq!(pending_operations[0].operation.attempt_count, 1);
}
@@ -5130,11 +5195,9 @@ mod tests {
let runtime = memory_runtime();
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .open_new_product_editor()
- .expect("new product editor should open")
- );
+ assert!(runtime
+ .open_new_product_editor()
+ .expect("new product editor should open"));
runtime
.lock_state()
@@ -5155,12 +5218,10 @@ mod tests {
},
)
.expect("blocking conflict should save");
- assert!(
- runtime
- .lock_state_mut()
- .refresh_selected_account_sync()
- .expect("sync status should refresh")
- );
+ assert!(runtime
+ .lock_state_mut()
+ .refresh_selected_account_sync()
+ .expect("sync status should refresh"));
let recorded = install_recorded_sync_transport(
&runtime,
@@ -5177,11 +5238,9 @@ mod tests {
}),
);
- assert!(
- !runtime
- .sync_on_app_launch()
- .expect("blocked launch sync should skip")
- );
+ assert!(!runtime
+ .sync_on_app_launch()
+ .expect("blocked launch sync should skip"));
let summary = runtime.summary();
@@ -5225,21 +5284,17 @@ mod tests {
},
)
.expect("blocking conflict should save");
- assert!(
- runtime
- .lock_state_mut()
- .refresh_selected_account_sync()
- .expect("sync status should refresh")
- );
+ assert!(runtime
+ .lock_state_mut()
+ .refresh_selected_account_sync()
+ .expect("sync status should refresh"));
- assert!(
- runtime
- .resolve_sync_conflict(
- conflict_id.as_str(),
- SyncConflictResolutionStatus::AcceptedLocal,
- )
- .expect("conflict resolution should succeed")
- );
+ assert!(runtime
+ .resolve_sync_conflict(
+ conflict_id.as_str(),
+ SyncConflictResolutionStatus::AcceptedLocal,
+ )
+ .expect("conflict resolution should succeed"));
let summary = runtime.summary();
@@ -5264,13 +5319,11 @@ mod tests {
summary.sync_status.conflicts[0].conflict.resolution,
SyncConflictResolutionStatus::AcceptedLocal
);
- assert!(
- summary.sync_status.conflicts[0]
- .conflict
- .resolved_at
- .as_deref()
- .is_some()
- );
+ assert!(summary.sync_status.conflicts[0]
+ .conflict
+ .resolved_at
+ .as_deref()
+ .is_some());
}
#[test]
@@ -5278,11 +5331,9 @@ mod tests {
let runtime = memory_runtime();
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .open_new_product_editor()
- .expect("new product editor should open")
- );
+ assert!(runtime
+ .open_new_product_editor()
+ .expect("new product editor should open"));
runtime
.lock_state()
@@ -5303,12 +5354,10 @@ mod tests {
},
)
.expect("review-required conflict should save");
- assert!(
- runtime
- .lock_state_mut()
- .refresh_selected_account_sync()
- .expect("sync status should refresh")
- );
+ assert!(runtime
+ .lock_state_mut()
+ .refresh_selected_account_sync()
+ .expect("sync status should refresh"));
let recorded = install_recorded_sync_transport(
&runtime,
@@ -5325,11 +5374,9 @@ mod tests {
}),
);
- assert!(
- runtime
- .sync_on_manual_refresh()
- .expect("manual refresh should succeed")
- );
+ assert!(runtime
+ .sync_on_manual_refresh()
+ .expect("manual refresh should succeed"));
let recorded = recorded.lock().expect("recorded transport");
let request = recorded
@@ -5422,11 +5469,9 @@ mod tests {
startup_issue: None,
});
- assert!(
- runtime
- .clear_startup_pending_remote_signer_session()
- .expect("clear pending should succeed")
- );
+ assert!(runtime
+ .clear_startup_pending_remote_signer_session()
+ .expect("clear pending should succeed"));
assert!(runtime.begin_generate_key_startup());
assert_eq!(
runtime.summary().logged_out_startup.phase,
@@ -5441,11 +5486,9 @@ mod tests {
let (runtime, paths) = bootstrapped_runtime("restart_pending_recovery");
let pending_session = fixture_pending_session();
- assert!(
- runtime
- .store_startup_pending_remote_signer_session(&pending_session)
- .expect("store pending should succeed")
- );
+ assert!(runtime
+ .store_startup_pending_remote_signer_session(&pending_session)
+ .expect("store pending should succeed"));
let restarted = restart_runtime(paths.clone());
let restored = restarted
@@ -5474,16 +5517,12 @@ mod tests {
let (runtime, paths) = bootstrapped_runtime("restart_after_explicit_cancel");
let pending_session = fixture_pending_session();
- assert!(
- runtime
- .store_startup_pending_remote_signer_session(&pending_session)
- .expect("store pending should succeed")
- );
- assert!(
- runtime
- .clear_startup_pending_remote_signer_session()
- .expect("clear pending should succeed")
- );
+ assert!(runtime
+ .store_startup_pending_remote_signer_session(&pending_session)
+ .expect("store pending should succeed"));
+ assert!(runtime
+ .clear_startup_pending_remote_signer_session()
+ .expect("clear pending should succeed"));
let restarted = restart_runtime(paths.clone());
@@ -5549,11 +5588,9 @@ mod tests {
let (runtime, paths) = bootstrapped_runtime("restart_buyer_search_detail");
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Personal)
- .expect("surface should switch into marketplace")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Personal)
+ .expect("surface should switch into marketplace"));
let fulfillment_window_id = seed_buyer_marketplace_support(
&runtime,
account_id.as_str(),
@@ -5583,16 +5620,12 @@ mod tests {
))
.expect("buyer detail product should attach a fulfillment window");
- assert!(
- runtime
- .set_personal_search_query("salad")
- .expect("buyer search query should update")
- );
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Search, product_id)
- .expect("buyer search detail should open")
- );
+ assert!(runtime
+ .set_personal_search_query("salad")
+ .expect("buyer search query should update"));
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Search, product_id)
+ .expect("buyer search detail should open"));
let restarted = restart_runtime(paths.clone());
let summary = restarted.summary();
@@ -5632,26 +5665,18 @@ mod tests {
"2026-04-20T09:30:00Z",
);
- assert!(
- runtime
- .set_products_search_query("pea")
- .expect("products query should update")
- );
- assert!(
- runtime
- .select_products_filter(ProductsFilter::Drafts)
- .expect("products filter should update")
- );
- assert!(
- runtime
- .select_products_sort(ProductsSort::Name)
- .expect("products sort should update")
- );
- assert!(
- runtime
- .open_existing_product_editor(product_id)
- .expect("product editor should open")
- );
+ assert!(runtime
+ .set_products_search_query("pea")
+ .expect("products query should update"));
+ assert!(runtime
+ .select_products_filter(ProductsFilter::Drafts)
+ .expect("products filter should update"));
+ assert!(runtime
+ .select_products_sort(ProductsSort::Name)
+ .expect("products sort should update"));
+ assert!(runtime
+ .open_existing_product_editor(product_id)
+ .expect("product editor should open"));
let restarted = restart_runtime(paths.clone());
let summary = restarted.summary();
@@ -5697,16 +5722,12 @@ mod tests {
))
.expect("order should update to packed");
- assert!(
- runtime
- .select_orders_filter(OrdersFilter::Packed)
- .expect("orders filter should update")
- );
- assert!(
- runtime
- .open_order_detail(order_id)
- .expect("order detail should open")
- );
+ assert!(runtime
+ .select_orders_filter(OrdersFilter::Packed)
+ .expect("orders filter should update"));
+ assert!(runtime
+ .open_order_detail(order_id)
+ .expect("order detail should open"));
let restarted = restart_runtime(paths.clone());
let summary = restarted.summary();
@@ -5734,11 +5755,9 @@ mod tests {
let (_, farm_id) = provision_ready_farmer_account(&runtime);
let (fulfillment_window_id, _) = seed_order_workspace(&runtime, farm_id);
- assert!(
- runtime
- .open_orders_fulfillment_window(fulfillment_window_id)
- .expect("orders window should open")
- );
+ assert!(runtime
+ .open_orders_fulfillment_window(fulfillment_window_id)
+ .expect("orders window should open"));
let mut persisted_state = runtime.lock_state().state_store.persisted_state().clone();
persisted_state.seller.orders_query.fulfillment_window_id =
Some(FulfillmentWindowId::new());
@@ -5756,14 +5775,12 @@ mod tests {
ShellSection::Farmer(FarmerSection::Orders)
);
assert_eq!(summary.orders_projection.query.fulfillment_window_id, None);
- assert!(
- summary
- .orders_projection
- .list
- .rows
- .iter()
- .any(|row| { row.fulfillment_window_id == Some(fulfillment_window_id) })
- );
+ assert!(summary
+ .orders_projection
+ .list
+ .rows
+ .iter()
+ .any(|row| { row.fulfillment_window_id == Some(fulfillment_window_id) }));
cleanup_bootstrapped_runtime_paths(&paths);
}
@@ -5796,13 +5813,11 @@ mod tests {
summary.pack_day_projection.query.fulfillment_window_id,
None
);
- assert!(
- summary
- .pack_day_projection
- .projection
- .fulfillment_window
- .is_some()
- );
+ assert!(summary
+ .pack_day_projection
+ .projection
+ .fulfillment_window
+ .is_some());
assert_ne!(
summary.pack_day_projection.query.fulfillment_window_id,
Some(stale_fulfillment_window_id)
@@ -6073,34 +6088,28 @@ mod tests {
let _ = provision_ready_farmer_account(&runtime);
assert!(!runtime.select_farmer_section(FarmerSection::PackDay));
- assert!(
- !runtime
- .open_pack_day(None)
- .expect("pack day route should stay blocked")
- );
+ assert!(!runtime
+ .open_pack_day(None)
+ .expect("pack day route should stay blocked"));
assert_eq!(
runtime.summary().shell_projection.selected_section,
ShellSection::Farmer(FarmerSection::Today)
);
- assert!(
- runtime
- .summary()
- .pack_day_projection
- .projection
- .fulfillment_window
- .is_none()
- );
+ assert!(runtime
+ .summary()
+ .pack_day_projection
+ .projection
+ .fulfillment_window
+ .is_none());
}
#[test]
fn runtime_routes_between_farmer_home_and_products_through_explicit_methods() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -6136,11 +6145,9 @@ mod tests {
.expect("sqlite store")
.save_farm_setup(account_id.as_str(), &farm_setup_projection)
.expect("farm setup should save");
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
assert!(runtime.select_farmer_section(FarmerSection::Products));
assert_eq!(
@@ -6277,20 +6284,16 @@ mod tests {
.expect("account should refresh after buyer workspace seeding");
let summary = runtime.summary();
assert_eq!(summary.personal_projection.search.listings.rows.len(), 2);
- assert!(
- summary
- .personal_projection
- .search
- .query
- .fulfillment_methods
- .is_empty()
- );
-
- assert!(
- runtime
- .set_personal_search_query("pea")
- .expect("buyer search query should apply")
- );
+ assert!(summary
+ .personal_projection
+ .search
+ .query
+ .fulfillment_methods
+ .is_empty());
+
+ assert!(runtime
+ .set_personal_search_query("pea")
+ .expect("buyer search query should apply"));
let searched = runtime.summary();
assert_eq!(searched.personal_projection.search.listings.rows.len(), 1);
assert_eq!(
@@ -6298,11 +6301,9 @@ mod tests {
"Pea shoots"
);
- assert!(
- runtime
- .set_personal_search_fulfillment_method(FarmOrderMethod::Pickup, true)
- .expect("buyer fulfillment filter should apply")
- );
+ assert!(runtime
+ .set_personal_search_fulfillment_method(FarmOrderMethod::Pickup, true)
+ .expect("buyer fulfillment filter should apply"));
let filtered = runtime.summary();
assert_eq!(
filtered
@@ -6325,11 +6326,9 @@ mod tests {
fn runtime_personal_product_detail_adds_to_cart_and_routes_into_cart() {
let runtime = memory_runtime();
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Personal)
- .expect("surface should switch into marketplace")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Personal)
+ .expect("surface should switch into marketplace"));
let fulfillment_window_id = seed_buyer_marketplace_support(
&runtime,
account_id.as_str(),
@@ -6359,17 +6358,13 @@ mod tests {
))
.expect("buyer detail product should attach a fulfillment window");
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Browse, product_id)
- .expect("buyer detail should open")
- );
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Browse, product_id)
+ .expect("buyer detail should open"));
assert!(runtime.increase_personal_product_quantity(PersonalSection::Browse));
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, false)
- .expect("buyer product should add to cart")
- );
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, false)
+ .expect("buyer product should add to cart"));
let summary = runtime.summary();
assert_eq!(
@@ -6395,14 +6390,12 @@ mod tests {
.as_deref(),
Some("North field farm")
);
- assert!(
- summary
- .personal_projection
- .cart
- .cart
- .replace_confirmation
- .is_none()
- );
+ assert!(summary
+ .personal_projection
+ .cart
+ .cart
+ .replace_confirmation
+ .is_none());
assert_eq!(
summary
.personal_projection
@@ -6419,11 +6412,9 @@ mod tests {
fn runtime_cross_farm_buyer_add_requires_replace_confirmation() {
let runtime = memory_runtime();
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Personal)
- .expect("surface should switch into marketplace")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Personal)
+ .expect("surface should switch into marketplace"));
let first_window_id = seed_buyer_marketplace_support(
&runtime,
account_id.as_str(),
@@ -6452,16 +6443,12 @@ mod tests {
where id = '{first_product_id}'"
))
.expect("first product should attach a fulfillment window");
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Browse, first_product_id)
- .expect("first buyer detail should open")
- );
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, false)
- .expect("first buyer product should add to cart")
- );
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Browse, first_product_id)
+ .expect("first buyer detail should open"));
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, false)
+ .expect("first buyer product should add to cart"));
let other_farm_id = FarmId::new();
runtime
@@ -6504,16 +6491,12 @@ mod tests {
))
.expect("second product should attach a fulfillment window");
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Browse, second_product_id)
- .expect("second buyer detail should open")
- );
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, false)
- .expect("cross-farm add should require confirmation")
- );
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Browse, second_product_id)
+ .expect("second buyer detail should open"));
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, false)
+ .expect("cross-farm add should require confirmation"));
let confirmation_summary = runtime.summary();
assert_eq!(
@@ -6545,11 +6528,9 @@ mod tests {
"Willow Farm"
);
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, true)
- .expect("confirmed cross-farm add should replace the cart")
- );
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, true)
+ .expect("confirmed cross-farm add should replace the cart"));
let replaced_summary = runtime.summary();
assert_eq!(
replaced_summary.shell_projection.selected_section,
@@ -6572,25 +6553,21 @@ mod tests {
.as_deref(),
Some("Willow Farm")
);
- assert!(
- replaced_summary
- .personal_projection
- .cart
- .cart
- .replace_confirmation
- .is_none()
- );
+ assert!(replaced_summary
+ .personal_projection
+ .cart
+ .cart
+ .replace_confirmation
+ .is_none());
}
#[test]
fn runtime_removing_buyer_cart_line_clears_cart_and_checkout_readiness() {
let runtime = memory_runtime();
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Personal)
- .expect("surface should switch into marketplace")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Personal)
+ .expect("surface should switch into marketplace"));
let fulfillment_window_id = seed_buyer_marketplace_support(
&runtime,
account_id.as_str(),
@@ -6619,22 +6596,16 @@ mod tests {
where id = '{product_id}'"
))
.expect("buyer detail product should attach a fulfillment window");
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Browse, product_id)
- .expect("buyer detail should open")
- );
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, false)
- .expect("buyer product should add to cart")
- );
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Browse, product_id)
+ .expect("buyer detail should open"));
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, false)
+ .expect("buyer product should add to cart"));
- assert!(
- runtime
- .remove_personal_cart_line(product_id)
- .expect("buyer cart line should remove")
- );
+ assert!(runtime
+ .remove_personal_cart_line(product_id)
+ .expect("buyer cart line should remove"));
let summary = runtime.summary();
assert!(summary.personal_projection.cart.cart.lines.is_empty());
@@ -6650,11 +6621,9 @@ mod tests {
fn runtime_places_buyer_order_and_routes_into_personal_orders() {
let runtime = memory_runtime();
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Personal)
- .expect("surface should switch into marketplace")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Personal)
+ .expect("surface should switch into marketplace"));
let fulfillment_window_id = seed_buyer_marketplace_support(
&runtime,
account_id.as_str(),
@@ -6683,31 +6652,23 @@ mod tests {
where id = '{product_id}'"
))
.expect("buyer detail product should attach a fulfillment window");
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Browse, product_id)
- .expect("buyer detail should open")
- );
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, false)
- .expect("buyer product should add to cart")
- );
- assert!(
- runtime
- .save_personal_checkout_draft(BuyerCheckoutDraft {
- name: "Casey Buyer".to_owned(),
- email: "casey@example.com".to_owned(),
- phone: "555-0101".to_owned(),
- order_note: "Leave by the cooler".to_owned(),
- })
- .expect("buyer checkout draft should save")
- );
- assert!(
- runtime
- .place_personal_order()
- .expect("buyer order should place")
- );
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Browse, product_id)
+ .expect("buyer detail should open"));
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, false)
+ .expect("buyer product should add to cart"));
+ assert!(runtime
+ .save_personal_checkout_draft(BuyerCheckoutDraft {
+ name: "Casey Buyer".to_owned(),
+ email: "casey@example.com".to_owned(),
+ phone: "555-0101".to_owned(),
+ order_note: "Leave by the cooler".to_owned(),
+ })
+ .expect("buyer checkout draft should save"));
+ assert!(runtime
+ .place_personal_order()
+ .expect("buyer order should place"));
let summary = runtime.summary();
assert_eq!(
@@ -6754,11 +6715,9 @@ mod tests {
fn runtime_opens_buyer_order_detail_from_personal_orders() {
let runtime = memory_runtime();
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Personal)
- .expect("surface should switch into marketplace")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Personal)
+ .expect("surface should switch into marketplace"));
let fulfillment_window_id = seed_buyer_marketplace_support(
&runtime,
account_id.as_str(),
@@ -6787,40 +6746,30 @@ mod tests {
where id = '{product_id}'"
))
.expect("buyer detail product should attach a fulfillment window");
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Browse, product_id)
- .expect("buyer detail should open")
- );
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, false)
- .expect("buyer product should add to cart")
- );
- assert!(
- runtime
- .save_personal_checkout_draft(BuyerCheckoutDraft {
- name: "Casey Buyer".to_owned(),
- email: "casey@example.com".to_owned(),
- phone: String::new(),
- order_note: String::new(),
- })
- .expect("buyer checkout draft should save")
- );
- assert!(
- runtime
- .place_personal_order()
- .expect("buyer order should place")
- );
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Browse, product_id)
+ .expect("buyer detail should open"));
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, false)
+ .expect("buyer product should add to cart"));
+ assert!(runtime
+ .save_personal_checkout_draft(BuyerCheckoutDraft {
+ name: "Casey Buyer".to_owned(),
+ email: "casey@example.com".to_owned(),
+ phone: String::new(),
+ order_note: String::new(),
+ })
+ .expect("buyer checkout draft should save"));
+ assert!(runtime
+ .place_personal_order()
+ .expect("buyer order should place"));
let order_id = runtime.summary().personal_projection.orders.list.rows[0].order_id;
assert!(runtime.select_personal_section(PersonalSection::Browse));
assert!(runtime.lock_state_mut().set_personal_order_detail(None));
- assert!(
- runtime
- .open_personal_order_detail(order_id)
- .expect("buyer order detail should open")
- );
+ assert!(runtime
+ .open_personal_order_detail(order_id)
+ .expect("buyer order detail should open"));
let summary = runtime.summary();
assert_eq!(
@@ -6843,11 +6792,9 @@ mod tests {
fn runtime_repeat_personal_order_readds_only_currently_eligible_items() {
let runtime = memory_runtime();
let (account_id, farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Personal)
- .expect("surface should switch into marketplace")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Personal)
+ .expect("surface should switch into marketplace"));
let fulfillment_window_id = seed_buyer_marketplace_support(
&runtime,
account_id.as_str(),
@@ -6885,41 +6832,29 @@ mod tests {
where id in ('{available_product_id}', '{unavailable_product_id}')"
))
.expect("buyer detail products should attach a fulfillment window");
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Browse, available_product_id)
- .expect("available buyer detail should open")
- );
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, false)
- .expect("available buyer product should add to cart")
- );
- assert!(
- runtime
- .open_personal_product_detail(PersonalSection::Browse, unavailable_product_id)
- .expect("unavailable buyer detail should open")
- );
- assert!(
- runtime
- .add_personal_product_to_cart(PersonalSection::Browse, false)
- .expect("second buyer product should add to cart")
- );
- assert!(
- runtime
- .save_personal_checkout_draft(BuyerCheckoutDraft {
- name: "Casey Buyer".to_owned(),
- email: "casey@example.com".to_owned(),
- phone: String::new(),
- order_note: String::new(),
- })
- .expect("buyer checkout draft should save")
- );
- assert!(
- runtime
- .place_personal_order()
- .expect("buyer order should place")
- );
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Browse, available_product_id)
+ .expect("available buyer detail should open"));
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, false)
+ .expect("available buyer product should add to cart"));
+ assert!(runtime
+ .open_personal_product_detail(PersonalSection::Browse, unavailable_product_id)
+ .expect("unavailable buyer detail should open"));
+ assert!(runtime
+ .add_personal_product_to_cart(PersonalSection::Browse, false)
+ .expect("second buyer product should add to cart"));
+ assert!(runtime
+ .save_personal_checkout_draft(BuyerCheckoutDraft {
+ name: "Casey Buyer".to_owned(),
+ email: "casey@example.com".to_owned(),
+ phone: String::new(),
+ order_note: String::new(),
+ })
+ .expect("buyer checkout draft should save"));
+ assert!(runtime
+ .place_personal_order()
+ .expect("buyer order should place"));
let order_id = runtime.summary().personal_projection.orders.list.rows[0].order_id;
runtime
@@ -6934,11 +6869,9 @@ mod tests {
)
.expect("product should archive");
- assert!(
- runtime
- .open_personal_order_detail(order_id)
- .expect("buyer order detail should reopen")
- );
+ assert!(runtime
+ .open_personal_order_detail(order_id)
+ .expect("buyer order detail should reopen"));
let detail_summary = runtime.summary();
let repeat_demand = detail_summary
.personal_projection
@@ -6951,11 +6884,9 @@ mod tests {
assert_eq!(repeat_demand.available_item_count, 1);
assert_eq!(repeat_demand.unavailable_item_count, 1);
- assert!(
- runtime
- .repeat_personal_order(order_id, false)
- .expect("repeat demand should add available items to cart")
- );
+ assert!(runtime
+ .repeat_personal_order(order_id, false)
+ .expect("repeat demand should add available items to cart"));
let summary = runtime.summary();
assert_eq!(
@@ -6968,25 +6899,21 @@ mod tests {
available_product_id
);
assert_eq!(summary.personal_projection.cart.cart.lines[0].quantity, 1);
- assert!(
- summary
- .personal_projection
- .cart
- .cart
- .replace_confirmation
- .is_none()
- );
+ assert!(summary
+ .personal_projection
+ .cart
+ .cart
+ .replace_confirmation
+ .is_none());
}
#[test]
fn runtime_products_queries_refresh_the_repository_backed_projection() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -7041,11 +6968,9 @@ mod tests {
"2026-04-18T09:00:00Z",
);
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
let summary = runtime.summary();
assert_eq!(summary.products_projection.list.summary.total_products, 2);
@@ -7059,18 +6984,14 @@ mod tests {
ProductsSort::default()
);
- assert!(
- runtime
- .select_products_filter(ProductsFilter::NeedAttention)
- .expect("filter should apply")
- );
+ assert!(runtime
+ .select_products_filter(ProductsFilter::NeedAttention)
+ .expect("filter should apply"));
assert_eq!(runtime.summary().products_projection.list.rows.len(), 2);
- assert!(
- runtime
- .set_products_search_query("pea")
- .expect("search should apply")
- );
+ assert!(runtime
+ .set_products_search_query("pea")
+ .expect("search should apply"));
let searched = runtime.summary();
assert_eq!(searched.products_projection.list.rows.len(), 1);
assert_eq!(
@@ -7078,11 +6999,9 @@ mod tests {
"Pea shoots"
);
- assert!(
- runtime
- .select_products_sort(ProductsSort::Name)
- .expect("sort should apply")
- );
+ assert!(runtime
+ .select_products_sort(ProductsSort::Name)
+ .expect("sort should apply"));
assert_eq!(
runtime.summary().products_projection.query.sort,
ProductsSort::Name
@@ -7093,11 +7012,9 @@ mod tests {
fn runtime_open_products_filter_routes_today_follow_ons_into_products() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -7134,21 +7051,17 @@ mod tests {
.save_farm_setup(account_id.as_str(), &farm_setup_projection)
.expect("farm setup should save");
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
assert_eq!(
runtime.summary().shell_projection.selected_section,
ShellSection::Farmer(FarmerSection::Today)
);
- assert!(
- runtime
- .open_products_filter(ProductsFilter::Drafts)
- .expect("products follow-on should route")
- );
+ assert!(runtime
+ .open_products_filter(ProductsFilter::Drafts)
+ .expect("products follow-on should route"));
let summary = runtime.summary();
assert_eq!(
@@ -7185,11 +7098,9 @@ mod tests {
);
assert!(orders_summary.orders_projection.detail.is_none());
- assert!(
- runtime
- .open_order_detail(order_id)
- .expect("order detail should open")
- );
+ assert!(runtime
+ .open_order_detail(order_id)
+ .expect("order detail should open"));
let detail_summary = runtime.summary();
assert_eq!(
detail_summary.shell_projection.selected_section,
@@ -7235,11 +7146,9 @@ mod tests {
let (runtime, paths) = bootstrapped_runtime("pack_day_export_requires_context");
let (_, _farm_id) = provision_ready_farmer_account(&runtime);
- assert!(
- !runtime
- .export_pack_day()
- .expect("missing pack day context should no-op")
- );
+ assert!(!runtime
+ .export_pack_day()
+ .expect("missing pack day context should no-op"));
assert_eq!(
runtime.summary().pack_day_projection.export.status,
PackDayExportStatus::Idle
@@ -7282,11 +7191,9 @@ mod tests {
}),
);
- assert!(
- runtime
- .export_pack_day()
- .expect("pack day export should succeed")
- );
+ assert!(runtime
+ .export_pack_day()
+ .expect("pack day export should succeed"));
let summary = runtime.summary();
let export = &summary.pack_day_projection.export;
@@ -7328,17 +7235,51 @@ mod tests {
}
#[test]
+ fn runtime_bootstrap_sweeps_prepared_pack_day_print_assets() {
+ let paths = temp_desktop_runtime_paths("pack_day_print_bootstrap_sweep");
+ let stale_root = prepared_customer_label_asset_root();
+ let stale_directory = stale_root.join(PackDayExportInstanceId::new().to_string());
+ let _ = fs::remove_file(&stale_root);
+ let _ = fs::remove_dir_all(&stale_root);
+ fs::create_dir_all(&stale_directory).expect("stale prepared directory should create");
+ fs::write(stale_directory.join("stale.ps"), "stale").expect("stale asset should write");
+
+ let _ = restart_runtime(paths.clone());
+
+ assert!(!stale_root.exists());
+
+ cleanup_bootstrapped_runtime_paths(&paths);
+ }
+
+ #[test]
+ fn runtime_bootstrap_keeps_running_when_prepared_pack_day_print_root_sweep_fails() {
+ let paths = temp_desktop_runtime_paths("pack_day_print_bootstrap_best_effort");
+ let stale_root = prepared_customer_label_asset_root();
+ let _ = fs::remove_file(&stale_root);
+ let _ = fs::remove_dir_all(&stale_root);
+ if let Some(parent) = stale_root.parent() {
+ fs::create_dir_all(parent).expect("prepared asset root parent should create");
+ }
+ fs::write(&stale_root, "blocked").expect("prepared asset root blocker should write");
+
+ let _ = restart_runtime(paths.clone());
+
+ assert!(stale_root.is_file());
+
+ let _ = fs::remove_file(&stale_root);
+ cleanup_bootstrapped_runtime_paths(&paths);
+ }
+
+ #[test]
fn runtime_prepare_pack_day_host_handoff_uses_the_current_export_bundle_for_file_actions() {
let (runtime, paths) = bootstrapped_runtime("pack_day_host_handoff_prepare");
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")
- );
+ assert!(runtime
+ .export_pack_day()
+ .expect("pack day export should succeed"));
for (kind, suffix) in [
(PackDayHostHandoffKind::OpenPackSheet, "pack_sheet.txt"),
@@ -7379,11 +7320,9 @@ mod tests {
assert_eq!(prepared.1.kind, kind);
assert!(prepared.1.target_path.ends_with(suffix));
- assert!(
- runtime
- .finish_pack_day_host_handoff(prepared.0, Ok(()))
- .expect("host handoff success should apply")
- );
+ assert!(runtime
+ .finish_pack_day_host_handoff(prepared.0, Ok(()))
+ .expect("host handoff success should apply"));
}
cleanup_bootstrapped_runtime_paths(&paths);
@@ -7396,11 +7335,9 @@ mod tests {
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")
- );
+ assert!(runtime
+ .export_pack_day()
+ .expect("pack day export should succeed"));
let (request, _) = runtime
.prepare_pack_day_host_handoff(PackDayHostHandoffKind::RevealBundle)
@@ -7448,11 +7385,9 @@ mod tests {
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")
- );
+ assert!(runtime
+ .export_pack_day()
+ .expect("pack day export should succeed"));
let (request, _) = runtime
.prepare_pack_day_host_handoff(PackDayHostHandoffKind::RevealBundle)
@@ -7464,11 +7399,9 @@ mod tests {
.state_store
.apply_in_memory(AppStateCommand::reset_pack_day_host_handoff());
- assert!(
- !runtime
- .finish_pack_day_host_handoff(request, Ok(()))
- .expect("stale completion should no-op")
- );
+ assert!(!runtime
+ .finish_pack_day_host_handoff(request, Ok(()))
+ .expect("stale completion should no-op"));
assert_eq!(
runtime.summary().pack_day_projection.host_handoff.status,
PackDayHostHandoffStatus::Idle
@@ -7484,11 +7417,9 @@ mod tests {
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")
- );
+ assert!(runtime
+ .export_pack_day()
+ .expect("pack day export should succeed"));
for (kind, expected_exported_suffix) in [
(PackDayPrintKind::PrintPackSheet, Some("pack_sheet.txt")),
@@ -7541,25 +7472,19 @@ mod tests {
.bundle
.as_ref()
.expect("pack day export bundle");
- assert!(
- prepared
- .1
- .target_path
- .ends_with("customer_labels_avery_5160_letter_30_up.ps")
- );
- assert!(
- !prepared
- .1
- .target_path
- .starts_with(PathBuf::from(&export_bundle.bundle_directory))
- );
- assert!(
- prepared
- .1
- .target_path
- .to_string_lossy()
- .contains(export_bundle.export_instance_id.to_string().as_str())
- );
+ assert!(prepared
+ .1
+ .target_path
+ .ends_with("customer_labels_avery_5160_letter_30_up.ps"));
+ assert!(!prepared
+ .1
+ .target_path
+ .starts_with(PathBuf::from(&export_bundle.bundle_directory)));
+ assert!(prepared
+ .1
+ .target_path
+ .to_string_lossy()
+ .contains(export_bundle.export_instance_id.to_string().as_str()));
assert_eq!(
prepared.1.command_args,
vec![
@@ -7571,11 +7496,9 @@ mod tests {
}
}
- assert!(
- runtime
- .finish_pack_day_print(prepared.0, Ok(()))
- .expect("print success should apply")
- );
+ assert!(runtime
+ .finish_pack_day_print(prepared.0, Ok(()))
+ .expect("print success should apply"));
if let PackDayPrintKind::PrintCustomerLabels = kind {
if let Some(parent) = prepared.1.target_path.parent() {
@@ -7594,11 +7517,9 @@ mod tests {
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")
- );
+ assert!(runtime
+ .export_pack_day()
+ .expect("pack day export should succeed"));
let (request, _) = runtime
.prepare_pack_day_print(PackDayPrintKind::PrintPackSheet)
@@ -7624,17 +7545,183 @@ mod tests {
}
#[test]
+ fn runtime_finish_pack_day_print_cleans_customer_label_assets_and_keeps_cleanup_failures_best_effort(
+ ) {
+ let (runtime, paths) = bootstrapped_runtime("pack_day_print_cleanup");
+ 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 (success_request, success_plan) = runtime
+ .prepare_pack_day_print(PackDayPrintKind::PrintCustomerLabels)
+ .expect("customer labels should prepare")
+ .expect("customer labels plan should exist");
+ let success_directory = success_plan
+ .target_path
+ .parent()
+ .expect("prepared asset parent")
+ .to_path_buf();
+ assert!(success_directory.is_dir());
+
+ assert!(runtime
+ .finish_pack_day_print(success_request, Ok(()))
+ .expect("print success should apply"));
+ assert!(!success_directory.exists());
+
+ let (failure_request, failure_plan) = runtime
+ .prepare_pack_day_print(PackDayPrintKind::PrintCustomerLabels)
+ .expect("customer labels should prepare again")
+ .expect("customer labels plan should exist again");
+ let failure_directory = failure_plan
+ .target_path
+ .parent()
+ .expect("prepared asset parent")
+ .to_path_buf();
+ fs::remove_file(&failure_plan.target_path).expect("prepared asset should remove");
+ fs::remove_dir_all(&failure_directory).expect("prepared asset directory should remove");
+ fs::write(&failure_directory, "blocked").expect("cleanup blocker should write");
+
+ let error = runtime
+ .finish_pack_day_print(
+ failure_request.clone(),
+ Err(PackDayPrintError::UnsupportedPlatform),
+ )
+ .expect_err("print failure should surface");
+ assert!(matches!(
+ error,
+ DesktopAppRuntimeCommandError::PackDayPrint(PackDayPrintError::UnsupportedPlatform)
+ ));
+ assert!(failure_directory.is_file());
+
+ let summary = runtime.summary();
+ assert_eq!(
+ summary.pack_day_projection.print.status,
+ PackDayPrintStatus::Failed
+ );
+ assert_eq!(
+ summary.pack_day_projection.print.request,
+ Some(failure_request)
+ );
+
+ let _ = fs::remove_file(&failure_directory);
+ cleanup_bootstrapped_runtime_paths(&paths);
+ }
+
+ #[test]
+ fn runtime_reexport_pack_day_cleans_previous_customer_label_prepared_assets() {
+ let (runtime, paths) = bootstrapped_runtime("pack_day_print_reexport_cleanup");
+ 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("initial pack day export should succeed"));
+ let first_bundle = runtime
+ .summary()
+ .pack_day_projection
+ .export
+ .bundle
+ .clone()
+ .expect("initial export bundle");
+
+ let (_request, plan) = runtime
+ .prepare_pack_day_print(PackDayPrintKind::PrintCustomerLabels)
+ .expect("customer labels should prepare")
+ .expect("customer labels plan should exist");
+ let prepared_directory = plan
+ .target_path
+ .parent()
+ .expect("prepared asset parent")
+ .to_path_buf();
+ assert!(prepared_directory.is_dir());
+ let _ = runtime
+ .lock_state_mut()
+ .state_store
+ .apply_in_memory(AppStateCommand::reset_pack_day_print());
+
+ assert!(runtime
+ .export_pack_day()
+ .expect("replacement pack day export should succeed"));
+
+ let summary = runtime.summary();
+ let replacement_bundle = summary
+ .pack_day_projection
+ .export
+ .bundle
+ .as_ref()
+ .expect("replacement export bundle");
+ assert_ne!(
+ replacement_bundle.export_instance_id,
+ first_bundle.export_instance_id
+ );
+ assert!(!prepared_directory.exists());
+
+ cleanup_bootstrapped_runtime_paths(&paths);
+ }
+
+ #[test]
+ fn runtime_pack_day_window_change_cleans_previous_customer_label_prepared_assets() {
+ let (runtime, paths) = bootstrapped_runtime("pack_day_print_window_cleanup");
+ let (_, farm_id) = provision_ready_farmer_account(&runtime);
+ let (fulfillment_window_id, _) = seed_order_workspace(&runtime, farm_id);
+ let (other_fulfillment_window_id, _) =
+ seed_second_order_workspace(&runtime, farm_id, fulfillment_window_id);
+
+ assert!(runtime
+ .open_pack_day(Some(fulfillment_window_id))
+ .expect("first pack day window should open"));
+ assert!(runtime
+ .export_pack_day()
+ .expect("initial pack day export should succeed"));
+
+ let (_request, plan) = runtime
+ .prepare_pack_day_print(PackDayPrintKind::PrintCustomerLabels)
+ .expect("customer labels should prepare")
+ .expect("customer labels plan should exist");
+ let prepared_directory = plan
+ .target_path
+ .parent()
+ .expect("prepared asset parent")
+ .to_path_buf();
+ assert!(prepared_directory.is_dir());
+ let _ = runtime
+ .lock_state_mut()
+ .state_store
+ .apply_in_memory(AppStateCommand::reset_pack_day_print());
+
+ assert!(runtime
+ .open_pack_day(Some(other_fulfillment_window_id))
+ .expect("second pack day window should open"));
+
+ let summary = runtime.summary();
+ assert_eq!(
+ summary.pack_day_projection.query.fulfillment_window_id,
+ Some(other_fulfillment_window_id)
+ );
+ assert_eq!(
+ summary.pack_day_projection.export.status,
+ PackDayExportStatus::Idle
+ );
+ assert!(!prepared_directory.exists());
+
+ cleanup_bootstrapped_runtime_paths(&paths);
+ }
+
+ #[test]
fn runtime_finish_pack_day_print_ignores_stale_background_completion() {
let (runtime, paths) = bootstrapped_runtime("pack_day_print_stale");
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")
- );
+ assert!(runtime
+ .export_pack_day()
+ .expect("pack day export should succeed"));
let (request, _) = runtime
.prepare_pack_day_print(PackDayPrintKind::PrintPickupRoster)
@@ -7646,11 +7733,9 @@ mod tests {
.state_store
.apply_in_memory(AppStateCommand::reset_pack_day_print());
- assert!(
- !runtime
- .finish_pack_day_print(request, Ok(()))
- .expect("stale completion should no-op")
- );
+ assert!(!runtime
+ .finish_pack_day_print(request, Ok(()))
+ .expect("stale completion should no-op"));
assert_eq!(
runtime.summary().pack_day_projection.print.status,
PackDayPrintStatus::Idle
@@ -7717,23 +7802,19 @@ mod tests {
.expect("order should update to scheduled");
assert!(runtime.open_orders().expect("orders should open"));
- assert!(
- runtime
- .mark_order_packed(order_id)
- .expect("mark packed should succeed")
- );
+ assert!(runtime
+ .mark_order_packed(order_id)
+ .expect("mark packed should succeed"));
let summary = runtime.summary();
assert_eq!(summary.sync_status.pending_write_count, 1);
- assert!(
- summary
- .orders_projection
- .reminders
- .items
- .iter()
- .any(|item| item.kind == ReminderKind::SyncImpact
- && item.title == "Pending local changes")
- );
+ assert!(summary
+ .orders_projection
+ .reminders
+ .items
+ .iter()
+ .any(|item| item.kind == ReminderKind::SyncImpact
+ && item.title == "Pending local changes"));
}
#[test]
@@ -7761,12 +7842,10 @@ mod tests {
)
.expect("blocking conflict should save");
- assert!(
- runtime
- .lock_state_mut()
- .refresh_selected_account_sync()
- .expect("sync status should refresh")
- );
+ assert!(runtime
+ .lock_state_mut()
+ .refresh_selected_account_sync()
+ .expect("sync status should refresh"));
let summary = runtime.summary();
let reminder = summary
@@ -7808,12 +7887,10 @@ mod tests {
},
)
.expect("blocking conflict should save");
- assert!(
- runtime
- .lock_state_mut()
- .refresh_selected_account_sync()
- .expect("sync status should refresh")
- );
+ assert!(runtime
+ .lock_state_mut()
+ .refresh_selected_account_sync()
+ .expect("sync status should refresh"));
let reminder_id = runtime
.summary()
@@ -7824,53 +7901,43 @@ mod tests {
.find(|item| item.kind == ReminderKind::SyncImpact)
.expect("sync reminder")
.reminder_id;
- assert!(
- runtime
- .acknowledge_reminder(reminder_id)
- .expect("reminder should acknowledge")
- );
+ assert!(runtime
+ .acknowledge_reminder(reminder_id)
+ .expect("reminder should acknowledge"));
let acknowledged_summary = runtime.summary();
- assert!(
- acknowledged_summary
- .orders_projection
- .reminders
- .items
- .iter()
- .any(|item| {
- item.reminder_id == reminder_id
- && item.delivery_state == ReminderDeliveryState::Acknowledged
- })
- );
- assert!(
- acknowledged_summary
- .reminder_log
- .entries
- .iter()
- .any(|entry| {
- entry.reminder_id == reminder_id
- && entry.delivery_state == ReminderDeliveryState::Acknowledged
- })
- );
+ assert!(acknowledged_summary
+ .orders_projection
+ .reminders
+ .items
+ .iter()
+ .any(|item| {
+ item.reminder_id == reminder_id
+ && item.delivery_state == ReminderDeliveryState::Acknowledged
+ }));
+ assert!(acknowledged_summary
+ .reminder_log
+ .entries
+ .iter()
+ .any(|entry| {
+ entry.reminder_id == reminder_id
+ && entry.delivery_state == ReminderDeliveryState::Acknowledged
+ }));
- assert!(
- runtime
- .resolve_sync_conflict(
- conflict_id.as_str(),
- SyncConflictResolutionStatus::AcceptedLocal,
- )
- .expect("conflict resolution should succeed")
- );
+ assert!(runtime
+ .resolve_sync_conflict(
+ conflict_id.as_str(),
+ SyncConflictResolutionStatus::AcceptedLocal,
+ )
+ .expect("conflict resolution should succeed"));
let resolved_summary = runtime.summary();
- assert!(
- resolved_summary
- .orders_projection
- .reminders
- .items
- .iter()
- .all(|item| { item.reminder_id != reminder_id })
- );
+ assert!(resolved_summary
+ .orders_projection
+ .reminders
+ .items
+ .iter()
+ .all(|item| { item.reminder_id != reminder_id }));
assert!(resolved_summary.reminder_log.entries.iter().any(|entry| {
entry.reminder_id == reminder_id
&& entry.delivery_state == ReminderDeliveryState::Resolved
@@ -7923,11 +7990,9 @@ mod tests {
.execute_batch(&sql)
.expect("recovery record should seed");
- assert!(
- runtime
- .open_order_detail(order_id)
- .expect("order detail should open")
- );
+ assert!(runtime
+ .open_order_detail(order_id)
+ .expect("order detail should open"));
let summary = runtime.summary();
assert_eq!(summary.orders_projection.recovery_queue.items.len(), 1);
@@ -7977,16 +8042,12 @@ mod tests {
let (_, farm_id) = provision_ready_farmer_account(&runtime);
let (_, order_id) = seed_order_workspace(&runtime, farm_id);
- assert!(
- runtime
- .select_orders_filter(OrdersFilter::Packed)
- .expect("orders filter should update")
- );
- assert!(
- runtime
- .open_order_detail(order_id)
- .expect("order detail should open")
- );
+ assert!(runtime
+ .select_orders_filter(OrdersFilter::Packed)
+ .expect("orders filter should update"));
+ assert!(runtime
+ .open_order_detail(order_id)
+ .expect("order detail should open"));
assert!(runtime.open_orders().expect("orders should reopen"));
let summary = runtime.summary();
@@ -8063,11 +8124,9 @@ mod tests {
.execute_batch(&sql)
.expect("second orders workspace should seed");
- assert!(
- runtime
- .open_orders_fulfillment_window(fulfillment_window_id)
- .expect("orders window follow-on should route")
- );
+ assert!(runtime
+ .open_orders_fulfillment_window(fulfillment_window_id)
+ .expect("orders window follow-on should route"));
let summary = runtime.summary();
assert_eq!(
@@ -8104,27 +8163,21 @@ mod tests {
.execute_batch(&sql)
.expect("order should update to scheduled");
- assert!(
- runtime
- .select_orders_filter(OrdersFilter::Scheduled)
- .expect("scheduled filter should apply")
- );
+ assert!(runtime
+ .select_orders_filter(OrdersFilter::Scheduled)
+ .expect("scheduled filter should apply"));
assert_eq!(runtime.summary().orders_projection.list.rows.len(), 1);
assert_eq!(
runtime.summary().orders_projection.list.rows[0].status,
OrderStatus::Scheduled
);
- assert!(
- runtime
- .open_order_detail(order_id)
- .expect("order detail should open")
- );
- assert!(
- runtime
- .mark_order_packed(order_id)
- .expect("order should mark packed")
- );
+ assert!(runtime
+ .open_order_detail(order_id)
+ .expect("order detail should open"));
+ assert!(runtime
+ .mark_order_packed(order_id)
+ .expect("order should mark packed"));
let packed_summary = runtime.summary();
assert_eq!(
packed_summary
@@ -8149,27 +8202,21 @@ mod tests {
1
);
- assert!(
- runtime
- .select_orders_filter(OrdersFilter::Packed)
- .expect("packed filter should apply")
- );
+ assert!(runtime
+ .select_orders_filter(OrdersFilter::Packed)
+ .expect("packed filter should apply"));
assert_eq!(runtime.summary().orders_projection.list.rows.len(), 1);
assert_eq!(
runtime.summary().orders_projection.list.rows[0].status,
OrderStatus::Packed
);
- assert!(
- runtime
- .open_order_detail(order_id)
- .expect("packed detail should open")
- );
- assert!(
- runtime
- .mark_order_completed(order_id)
- .expect("order should mark completed")
- );
+ assert!(runtime
+ .open_order_detail(order_id)
+ .expect("packed detail should open"));
+ assert!(runtime
+ .mark_order_completed(order_id)
+ .expect("order should mark completed"));
let completed_summary = runtime.summary();
assert_eq!(
completed_summary
@@ -8181,11 +8228,9 @@ mod tests {
OrderStatus::Completed
);
- assert!(
- runtime
- .select_orders_filter(OrdersFilter::Completed)
- .expect("completed filter should apply")
- );
+ assert!(runtime
+ .select_orders_filter(OrdersFilter::Completed)
+ .expect("completed filter should apply"));
assert_eq!(runtime.summary().orders_projection.list.rows.len(), 1);
assert_eq!(
runtime.summary().orders_projection.list.rows[0].status,
@@ -8197,11 +8242,9 @@ mod tests {
fn runtime_stock_updates_refresh_today_and_products_projections() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -8247,22 +8290,18 @@ mod tests {
"2026-04-18T10:00:00Z",
);
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
let product_id = runtime.summary().products_projection.list.rows[0].product_id;
assert_eq!(
runtime.summary().today_projection.low_stock_products.len(),
1
);
- assert!(
- runtime
- .update_product_stock(product_id, 12)
- .expect("stock update should succeed")
- );
+ assert!(runtime
+ .update_product_stock(product_id, 12)
+ .expect("stock update should succeed"));
let summary = runtime.summary();
assert_eq!(
@@ -8276,11 +8315,9 @@ mod tests {
fn runtime_open_new_product_editor_creates_a_local_draft_and_opens_it() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -8317,11 +8354,9 @@ mod tests {
.save_farm_setup(account_id.as_str(), &farm_setup_projection)
.expect("farm setup should save");
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
assert_eq!(
runtime
.summary()
@@ -8332,11 +8367,9 @@ mod tests {
0
);
- assert!(
- runtime
- .open_new_product_editor()
- .expect("new product editor should open")
- );
+ assert!(runtime
+ .open_new_product_editor()
+ .expect("new product editor should open"));
let summary = runtime.summary();
assert_eq!(summary.products_projection.list.summary.total_products, 1);
@@ -8354,11 +8387,9 @@ mod tests {
fn runtime_open_existing_and_save_product_editor_refreshes_products_projection() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -8404,16 +8435,12 @@ mod tests {
"2026-04-18T10:00:00Z",
);
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
- assert!(
- runtime
- .open_existing_product_editor(product_id)
- .expect("existing product editor should open")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
+ assert!(runtime
+ .open_existing_product_editor(product_id)
+ .expect("existing product editor should open"));
let saved_draft = ProductEditorDraft {
title: "Salad mix".to_owned(),
@@ -8426,11 +8453,9 @@ mod tests {
status: radroots_app_models::ProductStatus::Published,
};
- assert!(
- runtime
- .save_product_editor_draft(saved_draft.clone())
- .expect("product editor draft should save")
- );
+ assert!(runtime
+ .save_product_editor_draft(saved_draft.clone())
+ .expect("product editor draft should save"));
let summary = runtime.summary();
assert_eq!(
@@ -8467,11 +8492,9 @@ mod tests {
fn runtime_account_commands_refresh_identity_projection() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("First".to_owned()))
- .expect("first account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("First".to_owned()))
+ .expect("first account should generate"));
let first_summary = runtime.summary();
let first_account_id = first_summary
.settings_account_projection
@@ -8482,11 +8505,9 @@ mod tests {
.account_id
.clone();
- assert!(
- runtime
- .generate_local_account(Some("Second".to_owned()))
- .expect("second account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Second".to_owned()))
+ .expect("second account should generate"));
let second_summary = runtime.summary();
let second_account_id = second_summary
.settings_account_projection
@@ -8512,11 +8533,9 @@ mod tests {
ActiveSurface::Farmer,
true,
);
- assert!(
- runtime
- .select_local_account(second_account_id.as_str())
- .expect("selection should succeed")
- );
+ assert!(runtime
+ .select_local_account(second_account_id.as_str())
+ .expect("selection should succeed"));
let selected_summary = runtime.summary();
assert_eq!(selected_summary.startup_gate, AppStartupGate::Farmer);
assert_eq!(selected_summary.home_route, HomeRoute::FarmSetupOnboarding);
@@ -8529,11 +8548,9 @@ mod tests {
Some(ActiveSurface::Farmer)
);
- assert!(
- runtime
- .remove_selected_local_key()
- .expect("selected local key should remove")
- );
+ assert!(runtime
+ .remove_selected_local_key()
+ .expect("selected local key should remove"));
let removed_summary = runtime.summary();
assert_eq!(removed_summary.settings_account_projection.roster.len(), 1);
assert_eq!(
@@ -8556,13 +8573,11 @@ mod tests {
);
let imported_identity = RadrootsIdentity::generate();
- assert!(
- runtime
- .import_local_account(DesktopLocalIdentityImportRequest::raw_secret_key(
- imported_identity.nsec(),
- ))
- .expect("raw import should succeed")
- );
+ assert!(runtime
+ .import_local_account(DesktopLocalIdentityImportRequest::raw_secret_key(
+ imported_identity.nsec(),
+ ))
+ .expect("raw import should succeed"));
let imported_summary = runtime.summary();
assert_eq!(imported_summary.settings_account_projection.roster.len(), 2);
assert_eq!(
@@ -8579,11 +8594,9 @@ mod tests {
fn runtime_select_active_surface_persists_selected_surface() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -8594,18 +8607,14 @@ mod tests {
.account_id
.clone();
save_surface_activation(&runtime, account_id.as_str(), ActiveSurface::Farmer, true);
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
assert_eq!(runtime.summary().startup_gate, AppStartupGate::Farmer);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Personal)
- .expect("surface should select")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Personal)
+ .expect("surface should select"));
let personal_summary = runtime.summary();
assert_eq!(personal_summary.startup_gate, AppStartupGate::Personal);
assert_eq!(
@@ -8629,11 +8638,9 @@ mod tests {
ActiveSurface::Personal
);
- assert!(
- runtime
- .select_active_surface(ActiveSurface::Farmer)
- .expect("surface should reselect")
- );
+ assert!(runtime
+ .select_active_surface(ActiveSurface::Farmer)
+ .expect("surface should reselect"));
let farmer_summary = runtime.summary();
assert_eq!(farmer_summary.startup_gate, AppStartupGate::Farmer);
assert_eq!(
@@ -8662,11 +8669,9 @@ mod tests {
fn selecting_farmer_account_loads_persisted_farm_setup_draft() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -8690,11 +8695,9 @@ mod tests {
.expect("farm setup should save");
save_surface_activation(&runtime, account_id.as_str(), ActiveSurface::Farmer, true);
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
let summary = runtime.summary();
assert_eq!(summary.startup_gate, AppStartupGate::Farmer);
@@ -8706,11 +8709,9 @@ mod tests {
fn finishing_farm_setup_persists_saved_farm_and_today_projection() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -8722,11 +8723,9 @@ mod tests {
.clone();
let farm_id =
save_farmer_surface_activation(&runtime, account_id.as_str(), ActiveSurface::Farmer);
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
assert_eq!(runtime.summary().home_route, HomeRoute::FarmSetupOnboarding);
let draft = FarmSetupDraft::new(
@@ -8789,11 +8788,9 @@ mod tests {
fn loading_farm_rules_projection_seeds_profile_from_saved_farm() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -8830,11 +8827,9 @@ mod tests {
.save_farm_setup(account_id.as_str(), &farm_setup_projection)
.expect("farm setup should save");
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
let projection = runtime
.load_farm_rules_projection()
@@ -8863,11 +8858,9 @@ mod tests {
fn saving_farm_rules_projection_refreshes_saved_farm_summary_and_pickup_defaults() {
let runtime = memory_runtime();
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -8904,11 +8897,9 @@ mod tests {
.save_farm_setup(account_id.as_str(), &farm_setup_projection)
.expect("farm setup should save");
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
let default_pickup_location_id = PickupLocationId::new();
let market_pickup_location_id = PickupLocationId::new();
@@ -9041,11 +9032,9 @@ mod tests {
fn runtime_reset_local_device_state_clears_store_file_and_projection() {
let (runtime, paths) = file_backed_runtime("reset");
- assert!(
- runtime
- .generate_local_account(Some("First".to_owned()))
- .expect("first account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("First".to_owned()))
+ .expect("first account should generate"));
let first_account_id = runtime
.summary()
.settings_account_projection
@@ -9055,11 +9044,9 @@ mod tests {
.account
.account_id
.clone();
- assert!(
- runtime
- .generate_local_account(Some("Second".to_owned()))
- .expect("second account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Second".to_owned()))
+ .expect("second account should generate"));
let second_account_id = runtime
.summary()
.settings_account_projection
@@ -9083,21 +9070,17 @@ mod tests {
);
assert!(paths.store_path.exists());
- assert!(
- runtime
- .reset_local_device_state()
- .expect("device state should reset")
- );
+ assert!(runtime
+ .reset_local_device_state()
+ .expect("device state should reset"));
let summary = runtime.summary();
assert_eq!(summary.startup_gate, AppStartupGate::SetupRequired);
assert!(summary.settings_account_projection.roster.is_empty());
- assert!(
- summary
- .settings_account_projection
- .selected_account
- .is_none()
- );
+ assert!(summary
+ .settings_account_projection
+ .selected_account
+ .is_none());
assert!(!paths.store_path.exists());
assert_eq!(
runtime
@@ -9510,11 +9493,9 @@ mod tests {
}
fn provision_ready_farmer_account(runtime: &DesktopAppRuntime) -> (String, FarmId) {
- assert!(
- runtime
- .generate_local_account(Some("Farmer".to_owned()))
- .expect("account should generate")
- );
+ assert!(runtime
+ .generate_local_account(Some("Farmer".to_owned()))
+ .expect("account should generate"));
let account_id = runtime
.summary()
.settings_account_projection
@@ -9550,11 +9531,9 @@ mod tests {
.expect("sqlite store")
.save_farm_setup(account_id.as_str(), &farm_setup_projection)
.expect("farm setup should save");
- assert!(
- runtime
- .select_local_account(account_id.as_str())
- .expect("account should select")
- );
+ assert!(runtime
+ .select_local_account(account_id.as_str())
+ .expect("account should select"));
(account_id, farm_id)
}
@@ -9656,6 +9635,69 @@ mod tests {
(fulfillment_window_id, order_id)
}
+ fn seed_second_order_workspace(
+ runtime: &DesktopAppRuntime,
+ farm_id: FarmId,
+ source_fulfillment_window_id: FulfillmentWindowId,
+ ) -> (FulfillmentWindowId, OrderId) {
+ let fulfillment_window_id = FulfillmentWindowId::new();
+ let order_id = OrderId::new();
+ let sql = format!(
+ "insert into fulfillment_windows (
+ id,
+ farm_id,
+ starts_at,
+ ends_at,
+ capacity_limit,
+ created_at,
+ updated_at,
+ pickup_location_id,
+ label,
+ order_cutoff_at
+ )
+ select
+ '{fulfillment_window_id}',
+ farm_id,
+ '2099-04-19T16:00:00Z',
+ '2099-04-19T18:00:00Z',
+ capacity_limit,
+ '2099-04-19T16:00:00Z',
+ '2099-04-19T16:00:00Z',
+ pickup_location_id,
+ 'Saturday pickup',
+ '2099-04-18T18:00:00Z'
+ from fulfillment_windows
+ where id = '{source_fulfillment_window_id}' and farm_id = '{farm_id}';
+ insert into orders (
+ id,
+ farm_id,
+ fulfillment_window_id,
+ order_number,
+ customer_display_name,
+ status,
+ updated_at
+ ) values (
+ '{order_id}',
+ '{farm_id}',
+ '{fulfillment_window_id}',
+ 'R-101',
+ 'Robin',
+ 'scheduled',
+ '2026-04-17T11:00:00Z'
+ )"
+ );
+ runtime
+ .lock_state()
+ .sqlite_store
+ .as_ref()
+ .expect("sqlite store")
+ .connection()
+ .execute_batch(&sql)
+ .expect("second orders workspace should seed");
+
+ (fulfillment_window_id, order_id)
+ }
+
fn cleanup_paths(paths: &AppSharedAccountsPaths) {
let Some(base) = paths.data_root.ancestors().nth(3).map(PathBuf::from) else {
return;