package com.peachpasswords.ui.settings import androidx.compose.ui.unit.dp import org.junit.Assert.assertEquals import org.junit.Test class SettingsStackTest { // ── Collapsed tab layout: fixed browser-parity stride ───────────────────── @Test fun collapsed_tabs_use_fixed_browser_stride() { // Browser StackDeck.tsx: top = EXPANDED_H - TAB_OVERLAP + distance * (TAB_H - TAB_OVERLAP) // = 258 - 14 + distance * (46 - 14) = 244 + distance * 32. Independent of // screen height — the deck reads as a tight stack, not spread to fill. assertEquals(244.dp, collapsedTabTop(0)) assertEquals(276.dp, collapsedTabTop(1)) assertEquals(308.dp, collapsedTabTop(2)) } @Test fun collapsed_tab_stride_is_constant() { // Every successive tab steps down by exactly one stride (32dp), regardless // of how many tabs there are — no dynamic fill. val stride = collapsedTabTop(3) - collapsedTabTop(2) assertEquals(32.dp, stride) assertEquals(collapsedTabTop(5) - collapsedTabTop(4), stride) } @Test fun settings_deck_fills_down_to_just_above_the_build_label() { // Reserves the label's nav-bar inset (passed in) + its padding/line height // (xs 4dp + 12dp = 16dp) + a 1dp gap = navBarBottom + 17dp. No hard cap, so // tall panels (Galaxy Z Fold 7) fill to the label instead of stranding dead // space below the stack and clipping the Pro card's copy/reveal buttons. assertEquals(883.dp, settingsDeckHeight(900.dp, 0.dp)) assertEquals(463.dp, settingsDeckHeight(480.dp, 0.dp)) assertEquals(7.dp, settingsDeckHeight(24.dp, 0.dp)) assertEquals(1183.dp, settingsDeckHeight(1200.dp, 0.dp)) // A larger nav-bar inset (three-button nav) simply reserves more at the bottom. assertEquals(835.dp, settingsDeckHeight(900.dp, 48.dp)) } // ── Drag gesture resolution ─────────────────────────────────────────────── @Test fun settings_stack_drag_up_expands_card() { // Collapsed (deck) card dragged up past the 60px threshold → focus it. assertEquals(DragOutcome.EXPAND, resolveStackDrag(dragOffsetPx = -90f, thresholdPx = 60f, isExpanded = false)) } @Test fun settings_stack_drag_down_collapses_card() { // Focused card dragged down past the threshold → back to the deck. assertEquals(DragOutcome.COLLAPSE, resolveStackDrag(dragOffsetPx = 90f, thresholdPx = 60f, isExpanded = true)) } @Test fun settings_stack_drag_below_threshold_is_noop() { assertEquals(DragOutcome.NONE, resolveStackDrag(-40f, 60f, isExpanded = false)) assertEquals(DragOutcome.NONE, resolveStackDrag(40f, 60f, isExpanded = true)) // Right direction, wrong state: dragging an already-focused card up does nothing. assertEquals(DragOutcome.NONE, resolveStackDrag(-90f, 60f, isExpanded = true)) // Dragging a collapsed card down does nothing. assertEquals(DragOutcome.NONE, resolveStackDrag(90f, 60f, isExpanded = false)) } }