Add example TUI test for channeltree.
MODIFY
ui/channeltree.go
ui/channeltree.go
@@ -23,7 +23,7 @@ const (
// ChannelTree is the component that displays the channel hierarchy of the
// currently loaded guild and allows interactions with those channels.
type ChannelTree struct {
- internalTreeView *tview.TreeView
+ *tview.TreeView
state *discordgo.State
@@ -36,19 +36,19 @@ type ChannelTree struct {
func NewChannelTree(state *discordgo.State) *ChannelTree {
channelTree := &ChannelTree{
state: state,
- internalTreeView: tview.NewTreeView(),
+ TreeView: tview.NewTreeView(),
channelStates: make(map[*tview.TreeNode]channelState),
channelPosition: make(map[string]int),
}
- channelTree.internalTreeView.
+ channelTree.
SetVimBindingsEnabled(config.GetConfig().OnTypeInListBehaviour == config.DoNothingOnTypeInList).
SetCycleSelection(true).
SetTopLevel(1).
SetBorder(true)
- channelTree.internalTreeView.SetRoot(tview.NewTreeNode(""))
- channelTree.internalTreeView.SetSelectedFunc(func(node *tview.TreeNode) {
+ channelTree.SetRoot(tview.NewTreeNode(""))
+ channelTree.SetSelectedFunc(func(node *tview.TreeNode) {
channelID, ok := node.GetReference().(string)
if ok && channelTree.onChannelSelect != nil {
channelTree.onChannelSelect(channelID)
@@ -62,7 +62,7 @@ func NewChannelTree(state *discordgo.State) *ChannelTree {
func (channelTree *ChannelTree) Clear() {
channelTree.channelStates = make(map[*tview.TreeNode]channelState)
channelTree.channelPosition = make(map[string]int)
- channelTree.internalTreeView.GetRoot().ClearChildren()
+ channelTree.GetRoot().ClearChildren()
}
// LoadGuild accesses the state in order to load all locally present channels
@@ -105,7 +105,7 @@ func (channelTree *ChannelTree) LoadGuild(guildID string) error {
}
createSecondLevelChannelNodes(channelTree, channel)
}
- channelTree.internalTreeView.SetCurrentNode(channelTree.internalTreeView.GetRoot())
+ channelTree.SetCurrentNode(channelTree.GetRoot())
return nil
}
@@ -115,18 +115,18 @@ func createTopLevelChannelNodes(channelTree *ChannelTree, channel *discordgo.Cha
channelTree.channelStates[channelNode] = channelUnread
channelNode.SetColor(tcell.ColorRed)
}
- channelTree.internalTreeView.GetRoot().AddChild(channelNode)
+ channelTree.GetRoot().AddChild(channelNode)
}
func createChannelCategoryNodes(channelTree *ChannelTree, channel *discordgo.Channel) {
channelNode := createChannelNode(channel)
channelNode.SetSelectable(false)
- channelTree.internalTreeView.GetRoot().AddChild(channelNode)
+ channelTree.GetRoot().AddChild(channelNode)
}
func createSecondLevelChannelNodes(channelTree *ChannelTree, channel *discordgo.Channel) {
channelNode := createChannelNode(channel)
- for _, node := range channelTree.internalTreeView.GetRoot().GetChildren() {
+ for _, node := range channelTree.GetRoot().GetChildren() {
channelID, ok := node.GetReference().(string)
if ok && channelID == channel.ParentID {
if !readstate.HasBeenRead(channel, channel.LastMessageID) {
@@ -190,7 +190,7 @@ func (channelTree *ChannelTree) RemoveChannel(channel *discordgo.Channel) {
channelID := channel.ID
if channel.Type == discordgo.ChannelTypeGuildText {
- channelTree.internalTreeView.GetRoot().Walk(func(node, parent *tview.TreeNode) bool {
+ channelTree.GetRoot().Walk(func(node, parent *tview.TreeNode) bool {
nodeChannelID, ok := node.GetReference().(string)
if ok && nodeChannelID == channelID {
channelTree.removeNode(node, parent, channelID)
@@ -231,11 +231,6 @@ func (channelTree *ChannelTree) removeNode(node, parent *tview.TreeNode, channel
}
}
-// GetRoot returns the root node of the treeview.
-func (channelTree *ChannelTree) GetRoot() *tview.TreeNode {
- return channelTree.internalTreeView.GetRoot()
-}
-
// MarkChannelAsUnread marks a channel as unread.
func (channelTree *ChannelTree) MarkChannelAsUnread(channelID string) {
channelTree.GetRoot().Walk(func(node, parent *tview.TreeNode) bool {

ADD
ui/channeltree_test.go
+package ui
+
+import (
+ "testing"
+
+ "github.com/Bios-Marcel/discordgo"
+ "github.com/gdamore/tcell"
+)
+
+func TestChannelTree(t *testing.T) {
+ simScreen := tcell.NewSimulationScreen("UTF-8")
+
+ simScreen.Init()
+ simScreen.SetSize(10, 10)
+ simScreen.Show()
+
+ state := discordgo.NewState()
+
+ c1 := &discordgo.Channel{
+ ID: "C1",
+ Name: "C1",
+ Position: 2,
+ }
+ c2 := &discordgo.Channel{
+ ID: "C2",
+ Name: "C2",
+ Position: 1,
+ }
+ c3 := &discordgo.Channel{
+ ID: "C3",
+ Name: "C3",
+ Position: 3,
+ PermissionOverwrites: []*discordgo.PermissionOverwrite{
+ &discordgo.PermissionOverwrite{
+ ID: "R1",
+ Type: "role",
+ Deny: discordgo.PermissionReadMessages,
+ },
+ },
+ }
+ g1 := &discordgo.Guild{
+ ID: "G1",
+ Name: "G1",
+ Channels: []*discordgo.Channel{
+ c1,
+ c2,
+ c3,
+ },
+ }
+ c1.GuildID = g1.ID
+ c2.GuildID = g1.ID
+ c3.GuildID = g1.ID
+
+ stateError := state.GuildAdd(g1)
+ if stateError != nil {
+ t.Errorf("Error initializing state: %s", stateError)
+ }
+
+ stateError = state.ChannelAdd(c1)
+ if stateError != nil {
+ t.Errorf("Error initializing state: %s", stateError)
+ }
+ stateError = state.ChannelAdd(c2)
+ if stateError != nil {
+ t.Errorf("Error initializing state: %s", stateError)
+ }
+
+ state.User = &discordgo.User{
+ ID: "U1",
+ }
+
+ r1 := &discordgo.Role{
+ ID: "R1",
+ Name: "Rollo",
+ Permissions: discordgo.PermissionReadMessages,
+ }
+ state.RoleAdd("G1", r1)
+
+ state.MemberAdd(&discordgo.Member{
+ GuildID: g1.ID,
+ User: state.User,
+ Roles: []string{r1.ID},
+ })
+
+ tree := NewChannelTree(state)
+ loadError := tree.LoadGuild("G1")
+
+ if loadError != nil {
+ t.Errorf("Error loading channeltree: %s", loadError)
+ }
+
+ tree.SetBorder(false)
+ tree.SetRect(0, 0, 10, 10)
+
+ tree.Draw(simScreen)
+
+ cellOne, _, _, _ := simScreen.GetContent(0, 0)
+ cellTwo, _, _, _ := simScreen.GetContent(1, 0)
+
+ if cellOne != 'C' {
+ t.Errorf("Cell missmatch. Was '%c' instead of '%c'.", cellOne, 'C')
+ }
+ if cellTwo != '2' {
+ t.Errorf("Cell missmatch. Was '%c' instead of '%c'.", cellTwo, '2')
+ }
+
+ cellOne, _, _, _ = simScreen.GetContent(0, 1)
+ cellTwo, _, _, _ = simScreen.GetContent(1, 1)
+
+ if cellOne != 'C' {
+ t.Errorf("Cell missmatch. Was '%c' instead of '%c'.", cellOne, 'C')
+ }
+ if cellTwo != '1' {
+ t.Errorf("Cell missmatch. Was '%c' instead of '%c'.", cellTwo, '1')
+ }
+
+ cellOne, _, _, _ = simScreen.GetContent(0, 2)
+ cellTwo, _, _, _ = simScreen.GetContent(1, 2)
+
+ if cellOne != ' ' {
+ t.Errorf("Cell missmatch. Was '%c' instead of '%c'.", cellOne, ' ')
+ }
+ if cellTwo != ' ' {
+ t.Errorf("Cell missmatch. Was '%c' instead of '%c'.", cellTwo, ' ')
+ }
+}

MODIFY
ui/window.go
ui/window.go
@@ -167,7 +167,7 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
window.ShowErrorDialog(channelLoadError.Error())
} else {
if config.GetConfig().FocusChannelAfterGuildSelection {
- app.SetFocus(window.channelTree.internalTreeView)
+ app.SetFocus(window.channelTree)
}
}
@@ -184,7 +184,7 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
window.registerGuildMemberHandlers()
guildPage.AddItem(guildList, 0, 1, true)
- guildPage.AddItem(channelTree.internalTreeView, 0, 2, true)
+ guildPage.AddItem(channelTree, 0, 2, true)
window.leftArea.AddPage(guildPageName, guildPage, true, false)
@@ -382,7 +382,7 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
window.app.SetFocus(window.userList.internalTreeView)
} else {
if window.leftArea.GetCurrentPage() == guildPageName {
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
return nil
} else if window.leftArea.GetCurrentPage() == privatePageName {
window.app.SetFocus(window.privateList.internalTreeView)
@@ -394,7 +394,7 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
if event.Key() == tcell.KeyLeft {
if window.leftArea.GetCurrentPage() == guildPageName {
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
return nil
} else if window.leftArea.GetCurrentPage() == privatePageName {
window.app.SetFocus(window.privateList.internalTreeView)
@@ -530,13 +530,13 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
if config.GetConfig().OnTypeInListBehaviour == config.SearchOnTypeInList {
guildList.SetSearchOnTypeEnabled(true)
- channelTree.internalTreeView.SetSearchOnTypeEnabled(true)
+ channelTree.SetSearchOnTypeEnabled(true)
window.userList.internalTreeView.SetSearchOnTypeEnabled(true)
window.privateList.internalTreeView.SetSearchOnTypeEnabled(true)
} else if config.GetConfig().OnTypeInListBehaviour == config.FocusMessageInputOnTypeInList {
guildList.SetInputCapture(tviewutil.CreateFocusTextViewOnTypeInputHandler(
window.app, window.messageInput.internalTextView))
- channelTree.internalTreeView.SetInputCapture(tviewutil.CreateFocusTextViewOnTypeInputHandler(
+ channelTree.SetInputCapture(tviewutil.CreateFocusTextViewOnTypeInputHandler(
window.app, window.messageInput.internalTextView))
window.userList.SetInputCapture(tviewutil.CreateFocusTextViewOnTypeInputHandler(
window.app, window.messageInput.internalTextView))
@@ -551,7 +551,7 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
newGuildHandler := func(event *tcell.EventKey) *tcell.EventKey {
if event.Modifiers() == tcell.ModAlt {
if event.Key() == tcell.KeyDown || event.Key() == tcell.KeyUp {
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
return nil
}
@@ -587,7 +587,7 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
}
//Channel Container arrow key navigation. Please end my life.
- oldChannelListHandler := channelTree.internalTreeView.GetInputCapture()
+ oldChannelListHandler := channelTree.GetInputCapture()
newChannelListHandler := func(event *tcell.EventKey) *tcell.EventKey {
if event.Modifiers() == tcell.ModAlt {
if event.Key() == tcell.KeyDown || event.Key() == tcell.KeyUp {
@@ -622,9 +622,9 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
}
if oldChannelListHandler == nil {
- channelTree.internalTreeView.SetInputCapture(newChannelListHandler)
+ channelTree.SetInputCapture(newChannelListHandler)
} else {
- channelTree.internalTreeView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
+ channelTree.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
handledEvent := newChannelListHandler(event)
if handledEvent != nil {
return oldChannelListHandler(event)
@@ -797,10 +797,10 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
if window.userList.internalTreeView.IsVisible() {
window.app.SetFocus(window.userList.internalTreeView)
} else {
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
}
} else if event.Key() == tcell.KeyLeft {
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
} else {
return event
}
@@ -821,10 +821,10 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
if window.userList.internalTreeView.IsVisible() {
window.app.SetFocus(window.userList.internalTreeView)
} else {
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
}
} else if event.Key() == tcell.KeyLeft {
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
} else {
return event
}
@@ -1067,9 +1067,9 @@ func (window *Window) registerMouseFocusListeners() {
return false
})
- window.channelTree.internalTreeView.SetMouseHandler(func(event *tcell.EventMouse) bool {
+ window.channelTree.SetMouseHandler(func(event *tcell.EventMouse) bool {
if event.Buttons() == tcell.Button1 {
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
return true
}
@@ -1670,7 +1670,7 @@ func (window *Window) handleGlobalShortcuts(event *tcell.EventKey) *tcell.EventK
window.RefreshLayout()
} else if shortcuts.FocusChannelContainer.Equals(event) {
window.SwitchToGuildsPage()
- window.app.SetFocus(window.channelTree.internalTreeView)
+ window.app.SetFocus(window.channelTree)
} else if shortcuts.FocusPrivateChatPage.Equals(event) {
window.SwitchToFriendsPage()
window.app.SetFocus(window.privateList.GetComponent())

Add example TUI test for channeltree.