tui_test.go 9.3 KB

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