Coverage Summary for Class: Route (com.georgeci.moneysurfer.navigation)

Class Method, % Branch, % Line, % Instruction, %
Route$AccountChooser 100% (1/1) 50% (12/24) 100% (4/4) 79.8% (103/129)
Route$AccountChooser$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$AccountCreation 100% (1/1) 50% (12/24) 100% (4/4) 79.8% (103/129)
Route$AccountCreation$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$AccountDetails 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$AccountDetails$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$AccountsManage 100% (1/1) 100% (1/1) 100% (19/19)
Route$AccountTransactionCreation 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$AccountTransactionCreation$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$BudgetCreation 100% (1/1) 50% (5/10) 100% (2/2) 83% (44/53)
Route$BudgetCreation$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$BudgetDetails 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$BudgetDetails$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$Budgets 100% (1/1) 100% (1/1) 100% (19/19)
Route$CategoriesManage 100% (1/1) 100% (1/1) 100% (19/19)
Route$CategoryChooser 100% (1/1) 50% (13/26) 100% (4/4) 79.7% (106/133)
Route$CategoryChooser$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$CategoryCreation 100% (1/1) 50% (5/10) 100% (2/2) 83% (44/53)
Route$CategoryCreation$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$CategoryDetails 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$CategoryDetails$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$Dashboard 100% (1/1) 100% (1/1) 100% (19/19)
Route$DashboardCustomize 100% (1/1) 100% (1/1) 100% (19/19)
Route$GoalContribution 100% (1/1) 75% (6/8) 100% (3/3) 89.2% (58/65)
Route$GoalContribution$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$GoalCreation 100% (1/1) 100% (1/1) 100% (19/19)
Route$GoalDetails 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$GoalDetails$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$GoalEdit 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$GoalEdit$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$Goals 100% (1/1) 100% (1/1) 100% (19/19)
Route$IncomingInvites 100% (1/1) 100% (1/1) 100% (19/19)
Route$Insights 100% (1/1) 100% (1/1) 100% (19/19)
Route$Legal 100% (1/1) 100% (1/1) 100% (19/19)
Route$Onboarding 100% (1/1) 100% (1/1) 100% (19/19)
Route$Settings 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsAbout 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsAppearance 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsBackup 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsCsv 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsDebugConfig 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsDebugLog 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsDeleteAccount 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsLicenses 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsPreferences 100% (1/1) 100% (1/1) 100% (19/19)
Route$SettingsSync 100% (1/1) 100% (1/1) 100% (19/19)
Route$SignIn 100% (1/1) 100% (1/1) 100% (19/19)
Route$TopLevel
Route$TransactionCreation 100% (1/1) 83.3% (25/30) 100% (5/5) 92.1% (152/165)
Route$TransactionCreation$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$TransactionDetails 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$TransactionDetails$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$TransactionFilters 100% (1/1) 50% (9/18) 100% (3/3) 80.6% (75/93)
Route$TransactionFilters$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$TransactionsByAccount 100% (1/1) 50% (5/10) 100% (2/2) 85% (51/60)
Route$TransactionsByAccount$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$WorkspaceCreation 100% (1/1) 50% (5/10) 100% (2/2) 83% (44/53)
Route$WorkspaceCreation$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$WorkspaceInvite 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$WorkspaceInvite$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$WorkspaceManage 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$WorkspaceManage$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$WorkspaceMemberActions 100% (1/1) 50% (1/2) 100% (3/3) 88.1% (37/42)
Route$WorkspaceMemberActions$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$WorkspaceMembers 100% (1/1) 50% (1/2) 100% (2/2) 82.1% (23/28)
Route$WorkspaceMembers$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Route$WorkspaceSelector 100% (1/1) 50% (7/14) 100% (3/3) 81.2% (69/85)
Route$WorkspaceSelector$Companion 100% (1/1) 100% (1/1) 100% (4/4)
Total 100% (67/67) 55.8% (115/206) 100% (102/102) 88% (1641/1865)


 package com.georgeci.moneysurfer.navigation
 
 import androidx.navigation3.runtime.NavKey
 import kotlinx.serialization.Serializable
 
 sealed interface Route : NavKey {
 
     /** Marker for routes that appear as top-level destinations in the navigation suite (rail/drawer/bar). */
     sealed interface TopLevel : Route
 
     /** First-launch welcome screen, shown once before sign-in / first-account setup. */
     @Serializable
     data object Onboarding : Route
 
     @Serializable
     data object SignIn : Route
 
     @Serializable
     data object Legal : Route
 
     /**
      * [cloudDataUnavailable] marks the sign-in path where the account is known to own workspaces
      * that never reached the local database — the selector says so instead of looking like a
      * brand-new account with nothing in it (issue #342).
      */
     @Serializable
     data class WorkspaceSelector(
         val showActions: Boolean = false,
         val cloudDataUnavailable: Boolean = false,
     ) : Route
 
     @Serializable
     data class WorkspaceCreation(
         val workspaceId: String? = null,
     ) : Route
 
     @Serializable
     data class WorkspaceMembers(
         val workspaceId: String,
     ) : Route
 
     @Serializable
     data class WorkspaceManage(
         val workspaceId: String,
     ) : Route
 
     @Serializable
     data class WorkspaceInvite(
         val workspaceId: String,
     ) : Route
 
     @Serializable
     data class WorkspaceMemberActions(
         val workspaceId: String,
         val targetUserId: String,
     ) : Route
 
     @Serializable
     data object IncomingInvites : Route
 
     @Serializable
     data object Dashboard : TopLevel
 
     /** Widget visibility and order for the dashboard — reached from its top bar, not a tab. */
     @Serializable
     data object DashboardCustomize : Route
 
     /**
      * [firstRun] marks the offline first-launch step: the screen creates the very first account,
      * adopts its currency as the workspace base currency, and lands on Dashboard instead of
      * popping back. [accountType] pre-selects the type the onboarding asked about — it is the
      * `AccountType` enum name, kept as a String so `navigation` stays free of domain enums in
      * its saved back stack.
      */
     @Serializable
     data class AccountCreation(
         val accountId: String? = null,
         val firstRun: Boolean = false,
         val accountType: String? = null,
     ) : Route
 
     @Serializable
     data object AccountsManage : TopLevel
 
     @Serializable
     data class CategoryCreation(
         val categoryId: String? = null,
     ) : Route
 
     @Serializable
     data object CategoriesManage : TopLevel
 
     /**
      * Standalone spending analytics. Every other surface built on the spend aggregates is a
      * dashboard *widget*; this is the screen where the whole picture lives, so it is a destination
      * of its own rather than a detail of the dashboard.
      */
     @Serializable
     data object Insights : TopLevel
 
     @Serializable
     data object Budgets : TopLevel
 
     @Serializable
     data class BudgetDetails(val budgetId: String) : Route
 
     /** Create when [budgetId] is null, edit otherwise — one screen, as with accounts and categories. */
     @Serializable
     data class BudgetCreation(
         val budgetId: String? = null,
     ) : Route
 
     @Serializable
     data class CategoryDetails(val categoryId: String) : Route
 
     @Serializable
     data class CategoryChooser(
         val selectedCategoryId: String? = null,
         val filterType: String? = null,
         /**
          * Name of a `CategoryPickerVariant` — which of the two picker layouts to open. Null
          * takes the feature's default rather than binding navigation to the enum.
          */
         val variant: String? = null,
     ) : Route
 
     @Serializable
     data class AccountChooser(
         val selectedAccountId: String? = null,
         val excludeAccountId: String? = null,
         /** Offer the "Transfer between accounts instead" footer — only for a single-account pick. */
         val showTransferShortcut: Boolean = false,
     ) : Route
 
     @Serializable
     data class TransactionsByAccount(val accountId: String? = null) : TopLevel
 
     /**
      * Full-screen transaction filters. [accountId] is the list's own scope, not a filter: when it
      * is set the screen hides its account picker, because the list is already restricted to that
      * account. [anchorEpochDay] is the day the list is currently paged to, so the screen's live
      * result count resolves the same date window when the range still follows the period pager.
      */
     @Serializable
     data class TransactionFilters(
         val accountId: String? = null,
         val anchorEpochDay: Long? = null,
     ) : Route
 
     @Serializable
     data class TransactionCreation(
         val transactionId: String? = null,
         val accountId: String? = null,
         /**
          * Read [transactionId] as a template for a brand-new transaction instead of editing it.
          * A flag rather than a second id field: the screen loads exactly one transaction either
          * way, and two nullable id fields could disagree about which.
          */
         val duplicate: Boolean = false,
         /**
          * Open the form already switched to Transfer. Same request the account picker's "transfer
          * instead" footer makes once the screen is open — a caller that already knows the user
          * wants a transfer (the dashboard's quick actions) says so up front instead. The screen
          * still runs it through the type switch, so a build with transfers off ignores it.
          */
         val transfer: Boolean = false,
     ) : Route
 
     /**
      * Adding a transaction from an account's detail pane — the same screen and the same ViewModel
      * as [TransactionCreation], reached through its own route only so the pane host can present it
      * as the design's inline add panel beside the account (issue #391).
      *
      * It cannot simply be [TransactionCreation] with different metadata: a nav entry declares its
      * pane once, for every caller, and the transactions list opens the very same form *as* its
      * detail pane. Below the three-column breakpoint this route behaves exactly like
      * [TransactionCreation] — same full-screen form, same state.
      */
     @Serializable
     data class AccountTransactionCreation(val accountId: String) : Route
 
     @Serializable
     data class AccountDetails(val accountId: String) : Route
 
     @Serializable
     data class TransactionDetails(val transactionId: String) : Route
 
     /** Savings goals list. Also reachable from the dashboard's goals widget. */
     @Serializable
     data object Goals : TopLevel
 
     @Serializable
     data class GoalDetails(val goalId: String) : Route
 
     @Serializable
     data object GoalCreation : Route
 
     @Serializable
     data class GoalEdit(val goalId: String) : Route
 
     /** [mode] is a [GoalContributionMode] name — add money or take it back out. */
     @Serializable
     data class GoalContribution(
         val goalId: String,
         val mode: String = GoalContributionMode.ADD.name,
     ) : Route
 
     @Serializable
     data object Settings : TopLevel
 
     @Serializable
     data object SettingsAppearance : Route
 
     @Serializable
     data object SettingsPreferences : Route
 
     @Serializable
     data object SettingsSync : Route
 
     @Serializable
     data object SettingsBackup : Route
 
     @Serializable
     data object SettingsCsv : Route
 
     @Serializable
     data object SettingsAbout : Route
 
     @Serializable
     data object SettingsLicenses : Route
 
     /** Online-only user-account deletion flow (issue #213). */
     @Serializable
     data object SettingsDeleteAccount : Route
 
     /**
      * QA configuration panel. Registered in both builds, but Settings only surfaces a way here when
      * a real debug-overrides layer is bound — release builds resolve `DebugConfigSource.Empty`.
      */
     @Serializable
     data object SettingsDebugConfig : Route
 
     /**
      * The last Warn/Error log lines this process produced, reachable from [SettingsDebugConfig].
      * Gated by the same debug-layer signal — the buffer behind it is only filled in debug builds.
      */
     @Serializable
     data object SettingsDebugLog : Route
 }