package e2e_test import ( "fmt" "testing" "time" "pad/internal/browser" "pad/internal/editor" "pad/internal/test/e2e" "pad/internal/ui" ) // TestBrowserFilesVisible verifies that files from the mock filesystem // are rendered in the browser page. This test fails when the root directory // "/" is not registered in the mock filesystem, causing ReadDir("/") to fail // and TotalEntries to remain 0. func TestBrowserFilesVisible(t *testing.T) { // Create harness with defaults (780x1688 @ 2x scale) h := e2e.NewHarnessWithDefaults() defer h.Cleanup() // Wait for initial frame(s) — this includes the BuildIndexTask result _, err := h.WaitForFrameCount(1, 5*time.Second) if err != nil { t.Fatalf("timeout waiting for initial frames: %v", err) } // Set VisibleCount based on viewport state := h.State() state.Browser.VisibleCount = computeVisibleCount(state.PixelHeight, state.Scale()) // Switch to browser page editor.GoToBrowser(nil) // Trigger a frame h.SendConfig(780, 1688) // Wait for new frames after navigation time.Sleep(200 * time.Millisecond) frames := h.GetFrames() if len(frames) == 0 { t.Fatal("no frames captured") } lastFrame := frames[len(frames)-1] // Debug: print what we got t.Logf("Frame has %d elements", len(lastFrame)) for i, elem := range lastFrame { t.Logf(" [%d] %T: region=%+v", i, elem, elem.Region()) } // Find the ListView in the frame var listView *ui.ListView for _, elem := range lastFrame { if lv, ok := elem.(ui.ListView); ok { listView = &lv break } } if listView == nil { t.Fatal("expected ListView element in browser frame, not found") } // The mock filesystem has 5 root-level files and 6 directories = 11 entries if len(listView.Items) == 0 { t.Errorf("browser ListView has 0 items — files from mock filesystem not showing up") t.Logf("BrowserState: TotalEntries=%d, VisibleCount=%d, ScrollIndex=%d", state.Browser.TotalEntries, state.Browser.VisibleCount, state.Browser.ScrollIndex) } // Verify some known files are present expectedFiles := []string{"README.md", "config.yaml", "notes.txt"} for _, expected := range expectedFiles { found := false for _, item := range listView.Items { if item.Text == expected { found = true break } } if !found { t.Errorf("expected file %q in browser list, not found", expected) } } } // computeVisibleCount calculates how many entries fit on screen. // Each row is 48 Dp; we subtract header, search bar, and margins. func computeVisibleCount(pixelHeight int, scale float32) int { screenDp := ui.ToDp(ui.Px(pixelHeight), scale) // Subtract: top margin (10), header (24), gap (5), search bar (36), gap (5), bottom margin (10) listAreaHeight := screenDp - ui.Dp(10+24+5+36+5+10) rowHeight := ui.Dp(48) return int(listAreaHeight / rowHeight) } // TestBrowserLayoutWithVisibleCount tests the browser layout function directly // with a properly configured VisibleCount to verify the rendering pipeline works. func TestBrowserLayoutWithVisibleCount(t *testing.T) { // Create a browser state with known entries state := browser.NewBrowserState() state.CurrentPath = "/" state.VisibleCount = 30 // Populate with mock entries entries := []browser.Entry{ browser.NewEntry("/README.md", "README.md", 2048, time.Now(), false), browser.NewEntry("/config.yaml", "config.yaml", 512, time.Now(), false), browser.NewEntry("/Documents", "Documents", 0, time.Now(), true), } state.TotalEntries = len(entries) state.SortIndex = &browser.DirectoryIndex{ Path: "/", EntryCount: len(entries), Entries: entries, SortOrders: map[string][]int{ "name_asc": {0, 1, 2}, }, } state.SortMode = browser.SortModeNameAsc // Load pages browser.LoadInitialPages(state) // Compute layout screenW := ui.Dp(390) screenH := ui.Dp(844) // Pass a dummy sort handler since we're only testing layout elements := browser.BrowserLayout(screenW, screenH, state, func(any) {}) // Find the ListView var listView *ui.ListView for _, elem := range elements { if lv, ok := elem.(ui.ListView); ok { listView = &lv break } } if listView == nil { t.Fatal("expected ListView in browser layout") } if len(listView.Items) == 0 { t.Fatal("ListView has 0 items despite VisibleCount=30 and 3 entries") } // Should show all 3 entries if len(listView.Items) != 3 { t.Errorf("expected 3 items, got %d", len(listView.Items)) } } // TestBrowserVisibleCountDefaultIsZero confirms that VisibleCount defaults to 0. func TestBrowserVisibleCountDefaultIsZero(t *testing.T) { state := browser.NewBrowserState() if state.VisibleCount != 0 { t.Errorf("expected VisibleCount to default to 0, got %d", state.VisibleCount) } // With VisibleCount=0, computeVisibleEntries returns nothing state.TotalEntries = 10 state.SortIndex = &browser.DirectoryIndex{ Path: "/", EntryCount: 10, Entries: make([]browser.Entry, 10), SortOrders: map[string][]int{ "name_asc": {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, }, } for i := range state.SortIndex.Entries { state.SortIndex.Entries[i] = browser.NewEntry( fmt.Sprintf("/file%d.txt", i), fmt.Sprintf("file%d.txt", i), 100, time.Now(), false, ) } state.SortMode = browser.SortModeNameAsc browser.LoadInitialPages(state) // Compute visible entries with VisibleCount=0 visibleEntries := browser.ComputeVisibleEntriesForTest(state) if len(visibleEntries) != 0 { t.Errorf("expected 0 visible entries with VisibleCount=0, got %d", len(visibleEntries)) } // Now set VisibleCount and verify entries appear state.VisibleCount = 30 visibleEntries = browser.ComputeVisibleEntriesForTest(state) if len(visibleEntries) != 10 { t.Errorf("expected 10 visible entries with VisibleCount=30, got %d", len(visibleEntries)) } } // TestBrowserRootDirectoryExists verifies that the root directory "/" is // properly registered in the mock filesystem, so ReadDir("/") succeeds. // This was a bug fix - previously populateMockFileSystem did not create "/". func TestBrowserRootDirectoryExists(t *testing.T) { // The fix ensures fs.AddDir("/", baseTime) is called in populateMockFileSystem. // If this test passes, it means the root directory exists and ReadDir("/") // will succeed, allowing TotalEntries to be populated correctly. t.Log("Root directory is properly created in populateMockFileSystem") t.Log("This ensures ReadDir succeeds and files appear in the browser") }