Auto commit Fri Mar 20 11:01:01 PM CDT 2026
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
package com.mindmachine.mvp.session
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.test.ExperimentalTestApi
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performTouchInput
|
||||
import androidx.compose.ui.test.swipeLeft
|
||||
import androidx.compose.ui.test.swipeUp
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
/**
|
||||
* Compose UI tests for TimelineEditorScreen gesture handling.
|
||||
* These tests run without a physical device using Compose testing framework.
|
||||
*/
|
||||
@OptIn(ExperimentalTestApi::class)
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TimelineEditorGestureTest {
|
||||
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
@Test
|
||||
fun timelineGraph_renders_without_crashing() {
|
||||
composeTestRule.setContent {
|
||||
// Create a minimal test state
|
||||
var state by remember { mutableStateOf(TimelineEditorState.default()) }
|
||||
|
||||
TimelineGraph(
|
||||
title = "Visual",
|
||||
leftLabel = "Flash Interval",
|
||||
rightLabel = "Blank Interval",
|
||||
curveLeft = state.visualLeft,
|
||||
curveRight = state.visualRight,
|
||||
activeCurve = state.activeCurve,
|
||||
viewport = state.viewport,
|
||||
selection = state.selection,
|
||||
playheadSec = state.playheadSec,
|
||||
onViewportChanged = { state = state.copy(viewport = it) },
|
||||
onSelectionChanged = { sel -> state = state.copy(selection = sel).clampSelection() },
|
||||
onUpdateCurve = { curveId, newCurve -> state = state.withCurve(curveId, newCurve) },
|
||||
onTapSideSelect = { side ->
|
||||
state = state.copy(activeCurve = if (side == Side.LEFT) TimelineEditorState.ActiveCurve.VISUAL_LEFT else TimelineEditorState.ActiveCurve.VISUAL_RIGHT)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Basic sanity check that the graph renders
|
||||
composeTestRule.waitForIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun single_finger_vertical_swipe_does_not_crash() {
|
||||
composeTestRule.setContent {
|
||||
var state by remember { mutableStateOf(TimelineEditorState.default()) }
|
||||
|
||||
TimelineGraph(
|
||||
title = "Visual",
|
||||
leftLabel = "Flash Interval",
|
||||
rightLabel = "Blank Interval",
|
||||
curveLeft = state.visualLeft,
|
||||
curveRight = state.visualRight,
|
||||
activeCurve = state.activeCurve,
|
||||
viewport = state.viewport,
|
||||
selection = state.selection,
|
||||
playheadSec = state.playheadSec,
|
||||
onViewportChanged = { state = state.copy(viewport = it) },
|
||||
onSelectionChanged = { sel -> state = state.copy(selection = sel).clampSelection() },
|
||||
onUpdateCurve = { curveId, newCurve -> state = state.withCurve(curveId, newCurve) },
|
||||
onTapSideSelect = { side ->
|
||||
state = state.copy(activeCurve = if (side == Side.LEFT) TimelineEditorState.ActiveCurve.VISUAL_LEFT else TimelineEditorState.ActiveCurve.VISUAL_RIGHT)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule.waitForIdle()
|
||||
|
||||
// Perform vertical swipe (used for dragging points)
|
||||
composeTestRule.onNodeWithTag("timeline_graph")
|
||||
.performTouchInput {
|
||||
swipeUp(startY = 150f, endY = 50f)
|
||||
}
|
||||
|
||||
composeTestRule.waitForIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun single_finger_horizontal_swipe_does_not_crash() {
|
||||
composeTestRule.setContent {
|
||||
var state by remember { mutableStateOf(TimelineEditorState.default()) }
|
||||
|
||||
TimelineGraph(
|
||||
title = "Visual",
|
||||
leftLabel = "Flash Interval",
|
||||
rightLabel = "Blank Interval",
|
||||
curveLeft = state.visualLeft,
|
||||
curveRight = state.visualRight,
|
||||
activeCurve = state.activeCurve,
|
||||
viewport = state.viewport,
|
||||
selection = state.selection,
|
||||
playheadSec = state.playheadSec,
|
||||
onViewportChanged = { state = state.copy(viewport = it) },
|
||||
onSelectionChanged = { sel -> state = state.copy(selection = sel).clampSelection() },
|
||||
onUpdateCurve = { curveId, newCurve -> state = state.withCurve(curveId, newCurve) },
|
||||
onTapSideSelect = { side ->
|
||||
state = state.copy(activeCurve = if (side == Side.LEFT) TimelineEditorState.ActiveCurve.VISUAL_LEFT else TimelineEditorState.ActiveCurve.VISUAL_RIGHT)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule.waitForIdle()
|
||||
|
||||
// Perform horizontal swipe (panning)
|
||||
composeTestRule.onNodeWithTag("timeline_graph")
|
||||
.performTouchInput {
|
||||
swipeLeft(startX = 250f, endX = 150f)
|
||||
}
|
||||
|
||||
composeTestRule.waitForIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun multi_touch_gesture_does_not_crash() {
|
||||
composeTestRule.setContent {
|
||||
var state by remember { mutableStateOf(TimelineEditorState.default()) }
|
||||
|
||||
TimelineGraph(
|
||||
title = "Visual",
|
||||
leftLabel = "Flash Interval",
|
||||
rightLabel = "Blank Interval",
|
||||
curveLeft = state.visualLeft,
|
||||
curveRight = state.visualRight,
|
||||
activeCurve = state.activeCurve,
|
||||
viewport = state.viewport,
|
||||
selection = state.selection,
|
||||
playheadSec = state.playheadSec,
|
||||
onViewportChanged = { state = state.copy(viewport = it) },
|
||||
onSelectionChanged = { sel -> state = state.copy(selection = sel).clampSelection() },
|
||||
onUpdateCurve = { curveId, newCurve -> state = state.withCurve(curveId, newCurve) },
|
||||
onTapSideSelect = { side ->
|
||||
state = state.copy(activeCurve = if (side == Side.LEFT) TimelineEditorState.ActiveCurve.VISUAL_LEFT else TimelineEditorState.ActiveCurve.VISUAL_RIGHT)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
composeTestRule.waitForIdle()
|
||||
|
||||
// Simulate multi-touch gesture (two fingers)
|
||||
composeTestRule.onNodeWithTag("timeline_graph")
|
||||
.performTouchInput {
|
||||
down(0, androidx.compose.ui.geometry.Offset(100f, 100f))
|
||||
down(1, androidx.compose.ui.geometry.Offset(200f, 100f))
|
||||
moveTo(0, androidx.compose.ui.geometry.Offset(150f, 100f))
|
||||
moveTo(1, androidx.compose.ui.geometry.Offset(250f, 100f))
|
||||
up(0)
|
||||
up(1)
|
||||
}
|
||||
|
||||
composeTestRule.waitForIdle()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user