- Define pool.FileSystem interface in internal/io/pool/filesystem.go - Move DirEntry interface to internal/io/pool/types/types.go to break the pool <-> mock import cycle - Implement real.FileSystem with atomic writes (temp file + os.Rename) - Update mock.FileSystem to satisfy pool.FileSystem interface - Update worker pool tasks to accept pool.FileSystem interface - Update main.go to use RealFileSystem by default, with -root flag - Update all browser/editor/test references to types.DirEntry
133 lines
4.1 KiB
Go
133 lines
4.1 KiB
Go
package browser
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"pad/internal/io/pool"
|
|
"pad/internal/io/pool/mock"
|
|
)
|
|
|
|
// TestTapDirectory verifies that tapping a directory entry updates the
|
|
// BrowserState.CurrentPath.
|
|
func TestTapDirectory(t *testing.T) {
|
|
state := NewBrowserState()
|
|
mfs := mock.NewFileSystem()
|
|
wp := pool.NewWorkerPool(1)
|
|
bm, _ := NewBrowserManager(state, wp, mfs)
|
|
state.CurrentPath = "/root"
|
|
|
|
// Mock entries: a subdirectory "sub" and a file
|
|
entries := []Entry{
|
|
NewEntry("/root/sub", "sub", 0, time.Time{}, true),
|
|
NewEntry("/root/file.txt", "file.txt", 100, time.Time{}, false),
|
|
}
|
|
// Inject entries into the state
|
|
state.Pages[0] = NewPage(0, entries)
|
|
state.TotalEntries = 2
|
|
|
|
// Simulate tapping the directory at index 0
|
|
HandleBrowserTap(bm, state, 0)
|
|
|
|
if state.CurrentPath != "/root/sub" {
|
|
t.Errorf("expected CurrentPath='/root/sub', got %s", state.CurrentPath)
|
|
}
|
|
}
|
|
|
|
// TestTapUp verifies that tapping a ".." entry updates the
|
|
// BrowserState.CurrentPath to the parent directory.
|
|
func TestTapUp(t *testing.T) {
|
|
state := NewBrowserState()
|
|
mfs := mock.NewFileSystem()
|
|
wp := pool.NewWorkerPool(1)
|
|
bm, _ := NewBrowserManager(state, wp, mfs)
|
|
state.CurrentPath = "/root/sub"
|
|
|
|
// Mock entries: ".." and a file
|
|
entries := []Entry{
|
|
NewEntry("/root", "..", 0, time.Time{}, true),
|
|
NewEntry("/root/sub/file.txt", "file.txt", 100, time.Time{}, false),
|
|
}
|
|
state.Pages[0] = NewPage(0, entries)
|
|
state.TotalEntries = 2
|
|
|
|
// Simulate tapping the ".." entry at index 0
|
|
HandleBrowserTap(bm, state, 0)
|
|
|
|
if state.CurrentPath != "/root" {
|
|
t.Errorf("expected CurrentPath='/root', got %s", state.CurrentPath)
|
|
}
|
|
}
|
|
|
|
// TestTapWithSearchResults verifies that tapping a file in the search
|
|
// results list opens the correct file, not the file at the same index
|
|
// in the full directory listing.
|
|
func TestTapWithSearchResults(t *testing.T) {
|
|
state := NewBrowserState()
|
|
mfs := mock.NewFileSystem()
|
|
wp := pool.NewWorkerPool(1)
|
|
bm, _ := NewBrowserManager(state, wp, mfs)
|
|
state.CurrentPath = "/root"
|
|
|
|
// Mock entries: 5 files, sorted by name
|
|
entries := []Entry{
|
|
NewEntry("/root/alpha.txt", "alpha.txt", 100, time.Time{}, false),
|
|
NewEntry("/root/beta.txt", "beta.txt", 200, time.Time{}, false),
|
|
NewEntry("/root/gamma.txt", "gamma.txt", 300, time.Time{}, false),
|
|
NewEntry("/root/delta.txt", "delta.txt", 400, time.Time{}, false),
|
|
NewEntry("/root/epsilon.txt", "epsilon.txt", 500, time.Time{}, false),
|
|
}
|
|
state.Pages[0] = NewPage(0, entries)
|
|
state.TotalEntries = 5
|
|
|
|
// Simulate a search for "beta" that matches only index 1
|
|
state.Query = "beta"
|
|
state.SearchResults = []int{1}
|
|
|
|
// Tapping row 0 of the search results should open beta.txt (entry index 1),
|
|
// NOT alpha.txt (entry index 0).
|
|
HandleBrowserTap(bm, state, 0)
|
|
|
|
// Verify SelectedIndex was set to the resolved entry index (1), not the row index (0).
|
|
if state.SelectedIndex != 1 {
|
|
t.Errorf("expected SelectedIndex=1, got %d", state.SelectedIndex)
|
|
}
|
|
}
|
|
|
|
// TestTapWithMultipleSearchResults verifies tapping different rows of
|
|
// search results resolves to the correct entries.
|
|
func TestTapWithMultipleSearchResults(t *testing.T) {
|
|
state := NewBrowserState()
|
|
mfs := mock.NewFileSystem()
|
|
wp := pool.NewWorkerPool(1)
|
|
bm, _ := NewBrowserManager(state, wp, mfs)
|
|
state.CurrentPath = "/root"
|
|
|
|
// Mock entries: 5 files
|
|
entries := []Entry{
|
|
NewEntry("/root/aaa.txt", "aaa.txt", 100, time.Time{}, false),
|
|
NewEntry("/root/zzz.txt", "zzz.txt", 200, time.Time{}, false),
|
|
NewEntry("/root/aaa2.txt", "aaa2.txt", 300, time.Time{}, false),
|
|
NewEntry("/root/zzz2.txt", "zzz2.txt", 400, time.Time{}, false),
|
|
NewEntry("/root/mid.txt", "mid.txt", 500, time.Time{}, false),
|
|
}
|
|
state.Pages[0] = NewPage(0, entries)
|
|
state.TotalEntries = 5
|
|
|
|
// Simulate a search for "zzz" that matches indices 1 and 3
|
|
state.Query = "zzz"
|
|
state.SearchResults = []int{1, 3}
|
|
|
|
// Tapping row 0 should resolve to entry index 1 (zzz.txt)
|
|
HandleBrowserTap(bm, state, 0)
|
|
if state.SelectedIndex != 1 {
|
|
t.Errorf("row 0: expected SelectedIndex=1, got %d", state.SelectedIndex)
|
|
}
|
|
|
|
// Tapping row 1 should resolve to entry index 3 (zzz2.txt)
|
|
HandleBrowserTap(bm, state, 1)
|
|
if state.SelectedIndex != 3 {
|
|
t.Errorf("row 1: expected SelectedIndex=3, got %d", state.SelectedIndex)
|
|
}
|
|
}
|