package e2e_test import ( "testing" "time" "pad/internal/editor" "pad/internal/test/e2e" "pad/internal/ui" ) func TestEditorClickToMoveCursorWithScroll(t *testing.T) { h := e2e.NewHarnessWithDefaults() h.Run() // Start the harness! defer h.Cleanup() // Switch to editor page editor.GoToEditor(nil) h.SendConfig(780, 1688) // Give it a moment to initialize time.Sleep(200 * time.Millisecond) // Wait for frame _, err := h.WaitForFrameCount(1, 5*time.Second) if err != nil { t.Fatalf("timeout waiting for frame: %v", err) } // Setup: // - 2 lines, each 10 chars + newline. // - Line height = 14 * 1.2 = 16.8 (rounded?) Let's check EditorLineHeight() // EditorLineHeight is 14 * 1.2 = 16.8. lineHeight := 16.8 editor.TheState.Editor.Buffer = "Line 1\nLine 2\nLine 3" // Scroll to start of Line 2 (skip Line 1) editor.TheState.ScrollOffset = ui.Dp(lineHeight) // GlyphLayout: // Line 1: y = 0 // Line 2: y = 16.8 // Line 3: y = 33.6 editor.TheState.Editor.GlyphLayout = ui.GlyphLayout{ ByteOffsets: []int{0, 7, 14}, // Start of each line X: []ui.Dp{10, 10, 10}, Y: []ui.Dp{ui.Dp(0), ui.Dp(lineHeight), ui.Dp(lineHeight * 2)}, Advance: []ui.Dp{10, 10, 10}, } // Tap at y=10 (within the text area). // Because of scroll=16.8, this should correspond to: // visualLine = (y + scroll) / lineHeight = (10 + 16.8) / 16.8 = 26.8 / 16.8 = 1.59 -> 1 // Line 1 is index 0. Line 2 is index 1. // So visualLine 1 should be Line 2. // The problem is that SetCursorFromPoint expects y in DP, but receives it as raw pixels // if we're not careful. Let's pass the y value properly. // The test harness sends raw pixel coordinates to handler. // EditorLayout converts tap point: // localY := float64(pt.Y - editorRegion.Y + TheState.ScrollOffset) // So the handler receives Y as pt.Y, where pt.Y is relative to the screen. // The test harness doesn't seem to account for region offset. // Let's debug by printing in the test. t.Logf("ScrollOffset: %v", editor.TheState.ScrollOffset) h.SendInput([]ui.InputEvent{ { Handler: func(data any) { if pt, ok := data.(ui.Point); ok { // Manually simulate the offset correction that EditorLayout does // editorRegion.Y is margin(10) + statusBarH(52) = 62. // Let's set pt.Y to 10 + 62 = 72. localY := float64(pt.Y) - 62.0 + float64(editor.TheState.ScrollOffset) editor.SetCursorFromPoint(float64(pt.X), localY) } }, Data: ui.Point{X: 10, Y: 72}, }, }) // Assert cursor moved to start of Line 2 (offset 7) time.Sleep(100 * time.Millisecond) // Give logic goroutine a moment to process input t.Logf("Cursor position: %d", editor.TheState.Editor.CursorPosition) if editor.TheState.Editor.CursorPosition != 7 { t.Errorf("expected cursor to move to 7 (Line 2), but got %d", editor.TheState.Editor.CursorPosition) } }