tui_test.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. package issues
  2. import (
  3. "fmt"
  4. "strings"
  5. "testing"
  6. "charm.land/bubbles/v2/cursor"
  7. tea "github.com/charmbracelet/bubbletea"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. // Model tests ---------------------------------------------------------------
  11. // ----------------------------------------------------------------------------
  12. func Test_Model_load_cmd_loads_issue(t *testing.T) {}
  13. func Test_Model_load_cmd_loads_collection(t *testing.T) {}
  14. func Test_Model_load_cmd_loads_edit(t *testing.T) {}
  15. func Test_Model_Init_throws_load(t *testing.T) {
  16. testModel := Model{Path: "tests/bugs/test-1"}
  17. payloadFunc := testModel.Init()
  18. assert.IsType(t, tea.Cmd(testModel.load), payloadFunc, tea.Cmd(testModel.load), payloadFunc)
  19. testModel = Model{Path: "tests/bugs"}
  20. payloadFunc = testModel.Init()
  21. assert.IsType(t, tea.Cmd(testModel.load), payloadFunc, tea.Cmd(testModel.load), payloadFunc)
  22. testModel = Model{Path: "tests/bugs/doesntexistyet"}
  23. payloadFunc = testModel.Init()
  24. assert.IsType(t, tea.Cmd(testModel.load), payloadFunc, tea.Cmd(testModel.load), payloadFunc)
  25. }
  26. func Test_Model_Update_quit_on_ctrl_c(t *testing.T) {
  27. testModel := Model{}
  28. testKey := tea.Key{Type: tea.KeyCtrlC}
  29. testMsg := tea.KeyMsg(testKey)
  30. model, cmd := testModel.Update(testMsg)
  31. assert.Equal(t, testModel, model)
  32. if cmd != nil {
  33. cmdMsg := cmd()
  34. assert.Equal(t, tea.QuitMsg{}, cmdMsg)
  35. } else {
  36. assert.Fail(t, "should return cmd!")
  37. }
  38. }
  39. func Test_Model_Update_renderIssue(t *testing.T) {
  40. testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1")
  41. model := tea.Model(Model{widget: testIssue})
  42. testModel := Model{widget: testIssue}
  43. model, cmd := model.Update(tea.Msg(testIssue))
  44. if cmd == nil {
  45. assert.Fail(t, "should return cmd")
  46. }
  47. widget, ok := model.(Model).widget.(Issue)
  48. assert.True(t, ok, "widget should be type Issue")
  49. assert.Equal(t, testIssue.Title, widget.Title)
  50. assert.Equal(t, testModel.View(), model.View())
  51. }
  52. func Test_Model_Update_renderIssueCollection(t *testing.T) {
  53. testCollection, _ := IssueCollection{}.NewFromPath("tests/bugs")
  54. model := tea.Model(Model{widget: testCollection})
  55. testModel := Model{widget: testCollection}
  56. var cmd tea.Cmd
  57. model, cmd = testModel.Update(tea.Msg(testCollection))
  58. if cmd == nil {
  59. assert.Fail(t, "should return cmd")
  60. }
  61. widget, ok := model.(Model).widget.(IssueCollection)
  62. assert.True(t, ok, "widget should be type Issue")
  63. assert.Equal(t, len(testCollection.Collection), len(widget.Collection))
  64. assert.Equal(t, testModel.View(), model.View())
  65. }
  66. func Test_Model_Update_updates_content_on_render(t *testing.T) {
  67. testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1")
  68. testModel := Model{widget: testIssue}
  69. testWidget := testModel.widget.(Issue)
  70. testModel.content = testWidget.render().(string)
  71. model, cmd := testModel.Update(tea.Msg(testModel.content))
  72. if cmd != nil {
  73. assert.Fail(t, "should return cmds")
  74. }
  75. assert.Equal(t, testModel.content, model.(Model).content)
  76. }
  77. func Test_Model_Update_do_nothing(t *testing.T) {
  78. testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1")
  79. testModel := Model{widget: testIssue}
  80. // create a type wrapper for switch/case channel routing
  81. type testMsg int
  82. var tm testMsg
  83. model, cmd := testModel.Update(tm)
  84. assert.Equal(t, testModel, model)
  85. assert.Nil(t, cmd)
  86. }
  87. // widget tests --------------------------------------------------------------
  88. // ----------------------------------------------------------------------------
  89. // -------- Issue widget definitions ------------------------------------------
  90. // ----------------------------------------------------------------------------
  91. func Test_Issue_render(t *testing.T) {
  92. testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1")
  93. testRender := testIssue.render()
  94. renderContent, _ := testRender.(string)
  95. assert.True(t, strings.Contains(renderContent, "test description"))
  96. }
  97. func Test_Issue_keyhelp(t *testing.T) {}
  98. // -------- IssueCollection widget tests --------------------------------------
  99. // ----------------------------------------------------------------------------
  100. func Test_IssueCollection_update_scroll_up(t *testing.T) {
  101. ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/")
  102. testModel := Model{widget: ic}
  103. testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'j'}}
  104. testMsg := tea.KeyMsg(testKey)
  105. model, cmd := testModel.Update(testMsg)
  106. widget, _ := model.(Model).widget.(IssueCollection)
  107. assert.Equal(t, ic.selection+1, widget.selection)
  108. if cmd == nil {
  109. assert.Fail(t, "should return tea.Cmd")
  110. }
  111. // test select wraparound
  112. ic.selection = len(ic.Collection) - 1
  113. testModel = Model{widget: ic}
  114. model, cmd = testModel.Update(testMsg)
  115. widget, _ = model.(Model).widget.(IssueCollection)
  116. assert.Equal(t, 0, widget.selection)
  117. if cmd == nil {
  118. assert.Fail(t, "should return tea.Cmd")
  119. }
  120. }
  121. func Test_IssueCollection_update_scroll_down(t *testing.T) {
  122. ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/")
  123. testModel := Model{widget: ic}
  124. testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'k'}}
  125. testMsg := tea.KeyMsg(testKey)
  126. model, cmd := testModel.Update(testMsg)
  127. widget, _ := model.(Model).widget.(IssueCollection)
  128. assert.Equal(t, len(ic.Collection)-1, widget.selection)
  129. if cmd == nil {
  130. assert.Fail(t, "should return tea.Cmd")
  131. }
  132. // test select wraparound
  133. ic.selection = len(ic.Collection) - 1
  134. testModel = Model{widget: ic}
  135. model, _ = testModel.Update(testMsg)
  136. widget, _ = model.(Model).widget.(IssueCollection)
  137. assert.Equal(t, len(ic.Collection)-2, widget.selection)
  138. // if cmd == nil {
  139. // assert.Fail(t, "should return tea.Cmd")
  140. // }
  141. // ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/")
  142. // testModel := Model{widget: ic}
  143. // testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'j'}}
  144. // testMsg := tea.KeyMsg(testKey)
  145. // model, cmd := testModel.Update(testMsg)
  146. // widget, _ := testModel.widget.(IssueCollection)
  147. // assert.Equal(t, len(ic.Collection)-1, widget.selection)
  148. // if cmd == nil {
  149. // assert.Fail(t, "should return tea.Cmd")
  150. // }
  151. // model, cmd = model.Update(testMsg)
  152. // assert.Equal(t, len(ic.Collection)-2, widget.selection)
  153. // if cmd == nil {
  154. // assert.Fail(t, "should return tea.Cmd")
  155. // }
  156. }
  157. func Test_IssueCollection_update_load_on_enter(t *testing.T) {
  158. var ic widget
  159. ic, _ = IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs")
  160. testKey := tea.Key{Type: tea.KeyEnter, Runes: []rune{}}
  161. testMsg := tea.KeyMsg(testKey)
  162. testPath := ic.(IssueCollection).Collection[ic.(IssueCollection).selection].Path
  163. var cmd tea.Cmd
  164. ic, cmd = ic.update(testMsg)
  165. assert.Equal(t, testPath, ic.(IssueCollection).Path)
  166. // assert.IsType(t, Issue{}, model.widget)
  167. if cmd == nil {
  168. assert.Fail(t, "should return tea.Cmd")
  169. }
  170. }
  171. func Test_IssueCollection_render(t *testing.T) {}
  172. func Test_IssueCollection_keyhelp(t *testing.T) {}
  173. // -------- edit widget tests ------------------------------------------------
  174. // ----------------------------------------------------------------------------
  175. func Test_edit_update(t *testing.T) {}
  176. func Test_edit_init(t *testing.T) {
  177. testWidget := newEditWidget("tests/bugs/test-1")
  178. result := testWidget.(edit).init()
  179. t.Skip()
  180. assert.NotNil(t, result, result)
  181. assert.IsType(t, cursor.BlinkMsg{}, result())
  182. }
  183. func Test_edit_create_cmd(t *testing.T) {
  184. // test data init
  185. testData := make(map[string]string)
  186. // because the resulting test data never gets written from memory to disk,
  187. // we can set just about any test path
  188. testC := newEditWidget("tests/bugs/test-create-in-memory")
  189. for i := range testC.(edit).inputFields {
  190. testData[testC.(edit).inputFields[i].title] = fmt.Sprintf("test%d", i)
  191. testC.(edit).inputFields[i].input.SetValue(fmt.Sprintf("test%d", i))
  192. }
  193. commaSplit := func(t string) []string {
  194. s := strings.Split(t, ",")
  195. for i, v := range s {
  196. s[i] = strings.TrimLeft(v, " \t\n")
  197. s[i] = strings.TrimRight(s[i], " \t\n")
  198. s[i] = parseHumanToPath(s[i])
  199. }
  200. return s
  201. }
  202. var testIssue = Issue{
  203. Path: "tests/bugs/test0", // tests that title permutation has propogated
  204. Tags: VariadicField{Path: "/tags"},
  205. Blockedby: VariadicField{Path: "/blockedby"},
  206. }
  207. for key, value := range testData {
  208. switch key {
  209. case "title":
  210. testIssue.Title = value
  211. case "status":
  212. testIssue.Status = Field{Path: "/status", Data: value}
  213. case "description":
  214. testIssue.Description = Field{Path: "/description", Data: value}
  215. case "tags":
  216. splitTags := commaSplit(value)
  217. for _, tag := range splitTags {
  218. testIssue.Tags.Fields = append(testIssue.Tags.Fields, Field{Path: tag})
  219. }
  220. case "blockers":
  221. splitBlockedby := commaSplit(value)
  222. for _, blocker := range splitBlockedby {
  223. testIssue.Blockedby.Fields = append(testIssue.Blockedby.Fields, Field{Path: blocker})
  224. }
  225. }
  226. }
  227. result := testC.(edit).createIssueObject()
  228. assert.IsType(t, createResult(testIssue), result)
  229. assert.Equal(t, createResult(testIssue).Path, result.(createResult).Path)
  230. }
  231. func Test_edit_render(t *testing.T) {}
  232. func Test_edit_keyhelp(t *testing.T) {}
  233. // misc...---------------------------------------------------------------------
  234. // ----------------------------------------------------------------------------
  235. // duplicated by Test_Model_update_render*
  236. func Test_Model_View(t *testing.T) { // TODO DEPRECATE
  237. testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1")
  238. testModel := Model{widget: testIssue}
  239. model, cmd := Model{}.Update(tea.Msg(testIssue)) // gives render cmd
  240. model, cmd = model.Update(cmd()) // handle internal render
  241. if cmd != nil {
  242. assert.Fail(t, "should return not cmds")
  243. }
  244. assert.NotEqual(t, testModel.View(), model.(Model).View())
  245. render2 := Model{}.View()
  246. assert.Equal(t, "loading...", testModel.View(), render2)
  247. }