tui_test.go 7.3 KB

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