tui_test.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. func Test_Model_Init(t *testing.T) {
  10. testModel := Model{Path: "tests/bugs/test-1"}
  11. testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1")
  12. assert.Equal(t, testModel.Init()(), tea.Msg(testIssue))
  13. testModel = Model{Path: "tests/bugs"}
  14. testCollection, _ := IssueCollection{}.NewFromPath("tests/bugs")
  15. assert.Equal(t, testModel.Init()(), tea.Msg(testCollection))
  16. }
  17. func Test_Model_Update_quit_on_keymsg(t *testing.T) {
  18. testModel := Model{}
  19. testKey := tea.Key{Type: tea.KeyCtrlC}
  20. testMsg := tea.KeyMsg(testKey)
  21. model, cmd := testModel.Update(testMsg)
  22. assert.Equal(t, testModel, model)
  23. if cmd != nil {
  24. cmdMsg := cmd()
  25. assert.Equal(t, tea.QuitMsg{}, cmdMsg)
  26. } else {
  27. assert.Fail(t, "should return cmd!")
  28. }
  29. }
  30. func Test_Model_Update_scroll_up(t *testing.T) {
  31. ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/")
  32. testModel := Model{widget: ic}
  33. testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'j'}}
  34. testMsg := tea.KeyMsg(testKey)
  35. model, cmd := testModel.Update(testMsg)
  36. widget, _ := model.(Model).widget.(IssueCollection)
  37. assert.Equal(t, ic.selection+1, widget.selection)
  38. if cmd == nil {
  39. assert.Fail(t, "should return tea.Cmd")
  40. }
  41. // test select wraparound
  42. ic.selection = len(ic.Collection) - 1
  43. testModel = Model{widget: ic}
  44. model, cmd = testModel.Update(testMsg)
  45. widget, _ = model.(Model).widget.(IssueCollection)
  46. assert.Equal(t, 0, widget.selection)
  47. if cmd == nil {
  48. assert.Fail(t, "should return tea.Cmd")
  49. }
  50. }
  51. func Test_Model_Update_scroll_down(t *testing.T) {
  52. ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/")
  53. testModel := Model{widget: ic}
  54. testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'k'}}
  55. testMsg := tea.KeyMsg(testKey)
  56. model, cmd := testModel.Update(testMsg)
  57. widget, _ := model.(Model).widget.(IssueCollection)
  58. assert.Equal(t, len(ic.Collection)-1, widget.selection)
  59. if cmd == nil {
  60. assert.Fail(t, "should return tea.Cmd")
  61. }
  62. // test select wraparound
  63. ic.selection = len(ic.Collection) - 1
  64. testModel = Model{widget: ic}
  65. model, _ = testModel.Update(testMsg)
  66. widget, _ = model.(Model).widget.(IssueCollection)
  67. assert.Equal(t, len(ic.Collection)-2, widget.selection)
  68. // if cmd == nil {
  69. // assert.Fail(t, "should return tea.Cmd")
  70. // }
  71. // ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/")
  72. // testModel := Model{widget: ic}
  73. // testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'j'}}
  74. // testMsg := tea.KeyMsg(testKey)
  75. // model, cmd := testModel.Update(testMsg)
  76. // widget, _ := testModel.widget.(IssueCollection)
  77. // assert.Equal(t, len(ic.Collection)-1, widget.selection)
  78. // if cmd == nil {
  79. // assert.Fail(t, "should return tea.Cmd")
  80. // }
  81. // model, cmd = model.Update(testMsg)
  82. // assert.Equal(t, len(ic.Collection)-2, widget.selection)
  83. // if cmd == nil {
  84. // assert.Fail(t, "should return tea.Cmd")
  85. // }
  86. }
  87. func Test_Model_Update_load_on_enter(t *testing.T) {
  88. ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs")
  89. testModel := Model{widget: ic}
  90. testKey := tea.Key{Type: tea.KeyEnter, Runes: []rune{}}
  91. testMsg := tea.KeyMsg(testKey)
  92. testPath := ic.Collection[ic.selection].Path
  93. model, cmd := testModel.Update(testMsg)
  94. assert.Equal(t, testPath, model.(Model).Path)
  95. if cmd == nil {
  96. assert.Fail(t, "should return tea.Cmd")
  97. }
  98. }
  99. func Test_Model_Update_renderIssue(t *testing.T) {
  100. testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1")
  101. testModel := Model{}
  102. model, cmd := testModel.Update(tea.Msg(testIssue))
  103. widget, _ := model.(Model).widget.(Issue)
  104. if cmd == nil {
  105. assert.Fail(t, "should return cmd")
  106. }
  107. assert.Equal(t, testIssue.Title, widget.Title)
  108. assert.Equal(t, testIssue.render(), cmd())
  109. }
  110. func Test_Model_Update_renderIssueCollection(t *testing.T) {
  111. testCollection, _ := IssueCollection{}.NewFromPath("tests/bugs")
  112. testModel := Model{}
  113. model, cmd := testModel.Update(tea.Msg(testCollection))
  114. widget, _ := model.(Model).widget.(IssueCollection)
  115. if cmd == nil {
  116. assert.Fail(t, "should return cmd")
  117. }
  118. assert.Equal(t, len(testCollection.Collection), len(widget.Collection))
  119. assert.Equal(t, testCollection.render(), cmd())
  120. }
  121. func Test_Model_Update_updates_content(t *testing.T) {
  122. testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1")
  123. testModel := Model{widget: testIssue}
  124. testWidget := testModel.widget.(Issue)
  125. testModel.content = testWidget.render().(string)
  126. model, cmd := testModel.Update(tea.Msg(testModel.content))
  127. if cmd != nil {
  128. assert.Fail(t, "should not return cmd")
  129. }
  130. assert.Equal(t, testModel.content, model.(Model).content)
  131. }
  132. func Test_Model_Update_do_nothing(t *testing.T) {
  133. testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1")
  134. testModel := Model{widget: testIssue}
  135. var testMsg int
  136. model, cmd := testModel.Update(testMsg)
  137. assert.Equal(t, testModel, model)
  138. assert.Nil(t, cmd)
  139. }
  140. func Test_Model_renderIssue(t *testing.T) {
  141. testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1")
  142. testRender := testIssue.render()
  143. renderContent, _ := testRender.(string)
  144. assert.True(t, strings.Contains(renderContent, "test description"))
  145. }
  146. func Test_Model_View(t *testing.T) {
  147. testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1")
  148. model, cmd := Model{}.Update(tea.Msg(testIssue)) // gives render cmd
  149. model, cmd = model.Update(cmd()) // handle internal render
  150. if cmd != nil {
  151. assert.Fail(t, "should not return cmd")
  152. }
  153. testView := testIssue.render().(string) + "\nj/k: down/up\tenter: select\tq: quit"
  154. assert.Equal(t, testView, model.(Model).View())
  155. render2 := Model{}.View()
  156. assert.Equal(t, "loading...", render2)
  157. }
  158. func Test_create_create_cmd(t *testing.T) {
  159. // test data init
  160. testData := make(map[string]string)
  161. // because the resulting test data never gets written from memory to disk,
  162. // we can set just about any test path
  163. testC := initialCreateModel("tests/bugs/test-create-in-memory", "lorem ipsum")
  164. for i := range testC.inputFields {
  165. testData[testC.inputFields[i].title] = fmt.Sprintf("test%d", i)
  166. testC.inputFields[i].input.SetValue(fmt.Sprintf("test%d", i))
  167. }
  168. commaSplit := func(t string) []string {
  169. s := strings.Split(t, ",")
  170. for i, v := range s {
  171. s[i] = strings.TrimLeft(v, " \t\n")
  172. s[i] = strings.TrimRight(s[i], " \t\n")
  173. s[i] = parseHumanToPath(s[i])
  174. }
  175. return s
  176. }
  177. var testIssue = Issue{
  178. Path: "tests/bugs/test0", // tests that title permutation has propogated
  179. Tags: VariadicField{Path: "/tags"},
  180. Blockedby: VariadicField{Path: "/blockedby"},
  181. }
  182. for key, value := range testData {
  183. switch key {
  184. case "title":
  185. testIssue.Title = value
  186. case "status":
  187. testIssue.Status = Field{Path: "/status", Data: value}
  188. case "description":
  189. testIssue.Description = Field{Path: "/description", Data: value}
  190. case "tags":
  191. splitTags := commaSplit(value)
  192. for _, tag := range splitTags {
  193. testIssue.Tags.Fields = append(testIssue.Tags.Fields, Field{Path: tag})
  194. }
  195. case "blockers":
  196. splitBlockedby := commaSplit(value)
  197. for _, blocker := range splitBlockedby {
  198. testIssue.Blockedby.Fields = append(testIssue.Blockedby.Fields, Field{Path: blocker})
  199. }
  200. }
  201. }
  202. result := testC.create()
  203. assert.IsType(t, createResult(testIssue), result)
  204. assert.Equal(t, createResult(testIssue).Path, result.(createResult).Path)
  205. }