import ViE.State.Config
import ViE.Command.Explorer
import ViE.Window.Analysis
import ViE.Window.Actions
import Test.Utils
namespace Test.ExplorerPreview
open Test.Utils
open ViE
def findEntryIndex (entries : List FileEntry) (name : String) : Option Nat :=
let rec loop (list : List FileEntry) (idx : Nat) : Option Nat :=
match list with
| [] => none
| e :: rest =>
if e.name == name then
some idx
else
loop rest (idx + 1)
loop entries 0
def test : IO Unit := do
IO.println "Starting Explorer Preview Test..."
let s0 := { ViE.initialState with windowHeight := 40, windowWidth := 120 }
let path := "Test/test_paths/dir0/dir1"
let s1 ← ViE.Feature.openExplorer s0 path
let buf := s1.getActiveBuffer
let ws1 := s1.getCurrentWorkspace
assert "File explorer opens in floating window" (ws1.isFloatingWindow ws1.activeWindowId)
let baseBufId := s0.getActiveBuffer.id
let baseWinId :=
(ViE.Window.getWindowIds ws1.layout).find? (fun wid =>
if wid == ws1.activeWindowId then
false
else
match ws1.layout.findView wid with
| some v => v.bufferId == baseBufId
| none => false)
let baseWindowStillExists :=
(ViE.Window.getWindowIds ws1.layout).any (fun wid =>
if wid == ws1.activeWindowId then
false
else
match ws1.layout.findView wid with
| some v => v.bufferId == baseBufId
| none => false)
assert "Opening explorer keeps original buffer window intact" baseWindowStillExists
let explorerOpt := s1.explorers.find? (fun (id, _) => id == buf.id)
match explorerOpt with
| none =>
throw (IO.userError "Explorer buffer not registered")
| some (_, explorer) =>
let idx1 := findEntryIndex explorer.entries "file1.txt"
let idx2 := findEntryIndex explorer.entries "file2.txt"
assert "file1.txt exists in explorer entries" idx1.isSome
assert "file2.txt exists in explorer entries" idx2.isSome
let row1 : Row := ⟨2 + idx1.get!⟩
let row2 : Row := ⟨2 + idx2.get!⟩
let exAfterOpen := s1.explorers.find? (fun (id, _) => id == buf.id) |>.map (fun (_, ex) => ex)
match exAfterOpen with
| none => throw (IO.userError "Explorer buffer not registered after open")
| some exOpen =>
assert "Preview window created on open" exOpen.previewWindowId.isSome
let previewFloating :=
match exOpen.previewWindowId with
| some wid => s1.getCurrentWorkspace.isFloatingWindow wid
| none => false
assert "Preview window opens in floating window" previewFloating
let pairSideBySide :=
match exOpen.previewWindowId with
| some wid =>
let ws1 := s1.getCurrentWorkspace
match s1.getFloatingWindowBounds ws1.activeWindowId, s1.getFloatingWindowBounds wid with
| some (et, el, eh, ew), some (pt, pl, ph, pw) =>
et == pt && eh == ph && ((el + ew <= pl) || (pl + pw <= el))
| _, _ => false
| none => false
assert "Explorer/preview floating pair is side-by-side" pairSideBySide
let s2 := s1.updateActiveView fun v => { v with cursor := { row := row1, col := 0 } }
let s3 ← ViE.Feature.refreshExplorerPreview s2
let exAfterOpt := s3.explorers.find? (fun (id, _) => id == buf.id)
match exAfterOpt with
| none =>
throw (IO.userError "Explorer buffer not registered after preview")
| some (_, exAfter) =>
assert "Preview window created" exAfter.previewWindowId.isSome
assert "Preview buffer created" exAfter.previewBufferId.isSome
let ws := s3.getCurrentWorkspace
let previewWinId := exAfter.previewWindowId.get!
let previewView := ws.layout.findView previewWinId |>.getD initialView
let previewBuf := ws.buffers.find? (fun b => b.id == previewView.bufferId) |>.getD initialBuffer
assert "Preview filename has prefix" ((previewBuf.filename.getD "").startsWith "preview://")
assert "Preview filename contains file1.txt" ((previewBuf.filename.getD "").contains "file1.txt")
let dirIdx := findEntryIndex exAfter.entries "dir0"
assert "dir0 exists in explorer entries" dirIdx.isSome
let dirRow : Row := ⟨2 + dirIdx.get!⟩
let s3a := s3.updateActiveView fun v => { v with cursor := { row := dirRow, col := 0 } }
let s3b ← ViE.Feature.handleExplorerEnter s3a
let idsAfterDir := ViE.Window.getWindowIds s3b.getCurrentWorkspace.layout
assert "Preview window kept on directory navigation" (idsAfterDir.contains previewWinId)
let newExplorerOpt := s3b.explorers.find? (fun (id, _) => id == s3b.getActiveBuffer.id)
match newExplorerOpt with
| none => throw (IO.userError "Explorer buffer not registered after directory nav")
| some (_, exAfterDir) =>
assert "Preview window id preserved on directory nav" (exAfterDir.previewWindowId == exAfter.previewWindowId)
let s4 := s3.updateActiveView fun v => { v with cursor := { row := row2, col := 0 } }
let s5 ← ViE.Feature.refreshExplorerPreview s4
let ws5 := s5.getCurrentWorkspace
let previewView2 := ws5.layout.findView previewWinId |>.getD initialView
let previewBuf2 := ws5.buffers.find? (fun b => b.id == previewView2.bufferId) |>.getD initialBuffer
assert "Preview filename updates to file2.txt" ((previewBuf2.filename.getD "").contains "file2.txt")
let s5a := s5.updateActiveView fun v => { v with cursor := { row := row2, col := 0 } }
let explorerWinId := s5a.getCurrentWorkspace.activeWindowId
let s5b ← ViE.Feature.handleExplorerEnter s5a
let ws5b := s5b.getCurrentWorkspace
assert "Opening file from floating explorer leaves non-floating window" (!ws5b.isFloatingWindow ws5b.activeWindowId)
match baseWinId with
| some wid =>
assert "Opening file from explorer uses original buffer window" (ws5b.activeWindowId == wid)
| none =>
throw (IO.userError "Base window id not found after explorer open")
let idsAfterOpen := ViE.Window.getWindowIds s5b.getCurrentWorkspace.layout
assert "Explorer window removed on file open" (!idsAfterOpen.contains explorerWinId)
assert "Preview window removed on file open" (!idsAfterOpen.contains previewWinId)
let bufIdsAfterOpen := s5b.getCurrentWorkspace.buffers.map (fun b => b.id)
let previewBufId := exAfter.previewBufferId.getD 0
assert "Preview buffer removed on file open" (!bufIdsAfterOpen.contains previewBufId)
let sClose := ViE.Window.closeActiveWindow s5
let idsAfter := ViE.Window.getWindowIds sClose.getCurrentWorkspace.layout
assert "Preview window removed on explorer close" (!idsAfter.contains previewWinId)
let bufIdsAfterClose := sClose.getCurrentWorkspace.buffers.map (fun b => b.id)
assert "Preview buffer removed on explorer close" (!bufIdsAfterClose.contains previewBufId)
let s6 ← ViE.Feature.toggleExplorerPreview s5
let exAfterClose := s6.explorers.find? (fun (id, _) => id == buf.id) |>.map (fun (_, ex) => ex)
match exAfterClose with
| none => throw (IO.userError "Explorer buffer missing after close")
| some exClose =>
assert "Preview window cleared" exClose.previewWindowId.isNone
IO.println "Explorer Preview Test passed!"
end Test.ExplorerPreview