package issues import ( "fmt" "strings" "testing" tea "github.com/charmbracelet/bubbletea" "github.com/stretchr/testify/assert" ) func Test_Model_Init(t *testing.T) { testModel := Model{Path: "tests/bugs/test-1"} testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1") assert.Equal(t, testModel.Init()(), tea.Msg(testIssue)) testModel = Model{Path: "tests/bugs"} testCollection, _ := IssueCollection{}.NewFromPath("tests/bugs") assert.Equal(t, testModel.Init()(), tea.Msg(testCollection)) } func Test_Model_Update_quit_on_keymsg(t *testing.T) { testModel := Model{} testKey := tea.Key{Type: tea.KeyCtrlC} testMsg := tea.KeyMsg(testKey) model, cmd := testModel.Update(testMsg) assert.Equal(t, testModel, model) if cmd != nil { cmdMsg := cmd() assert.Equal(t, tea.QuitMsg{}, cmdMsg) } else { assert.Fail(t, "should return cmd!") } } func Test_Model_Update_scroll_up(t *testing.T) { ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/") testModel := Model{widget: ic} testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'j'}} testMsg := tea.KeyMsg(testKey) model, cmd := testModel.Update(testMsg) widget, _ := model.(Model).widget.(IssueCollection) assert.Equal(t, ic.selection+1, widget.selection) if cmd == nil { assert.Fail(t, "should return tea.Cmd") } // test select wraparound ic.selection = len(ic.Collection) - 1 testModel = Model{widget: ic} model, cmd = testModel.Update(testMsg) widget, _ = model.(Model).widget.(IssueCollection) assert.Equal(t, 0, widget.selection) if cmd == nil { assert.Fail(t, "should return tea.Cmd") } } func Test_Model_Update_scroll_down(t *testing.T) { ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/") testModel := Model{widget: ic} testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'k'}} testMsg := tea.KeyMsg(testKey) model, cmd := testModel.Update(testMsg) widget, _ := model.(Model).widget.(IssueCollection) assert.Equal(t, len(ic.Collection)-1, widget.selection) if cmd == nil { assert.Fail(t, "should return tea.Cmd") } // test select wraparound ic.selection = len(ic.Collection) - 1 testModel = Model{widget: ic} model, _ = testModel.Update(testMsg) widget, _ = model.(Model).widget.(IssueCollection) assert.Equal(t, len(ic.Collection)-2, widget.selection) // if cmd == nil { // assert.Fail(t, "should return tea.Cmd") // } // ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs/") // testModel := Model{widget: ic} // testKey := tea.Key{Type: tea.KeyRunes, Runes: []rune{'j'}} // testMsg := tea.KeyMsg(testKey) // model, cmd := testModel.Update(testMsg) // widget, _ := testModel.widget.(IssueCollection) // assert.Equal(t, len(ic.Collection)-1, widget.selection) // if cmd == nil { // assert.Fail(t, "should return tea.Cmd") // } // model, cmd = model.Update(testMsg) // assert.Equal(t, len(ic.Collection)-2, widget.selection) // if cmd == nil { // assert.Fail(t, "should return tea.Cmd") // } } func Test_Model_Update_load_on_enter(t *testing.T) { ic, _ := IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs") testModel := Model{widget: ic} testKey := tea.Key{Type: tea.KeyEnter, Runes: []rune{}} testMsg := tea.KeyMsg(testKey) testPath := ic.Collection[ic.selection].Path model, cmd := testModel.Update(testMsg) assert.Equal(t, testPath, model.(Model).Path) if cmd == nil { assert.Fail(t, "should return tea.Cmd") } } func Test_Model_Update_renderIssue(t *testing.T) { testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1") testModel := Model{} model, cmd := testModel.Update(tea.Msg(testIssue)) widget, _ := model.(Model).widget.(Issue) if cmd == nil { assert.Fail(t, "should return cmd") } assert.Equal(t, testIssue.Title, widget.Title) assert.Equal(t, testIssue.render(), cmd()) } func Test_Model_Update_renderIssueCollection(t *testing.T) { testCollection, _ := IssueCollection{}.NewFromPath("tests/bugs") testModel := Model{} model, cmd := testModel.Update(tea.Msg(testCollection)) widget, _ := model.(Model).widget.(IssueCollection) if cmd == nil { assert.Fail(t, "should return cmd") } assert.Equal(t, len(testCollection.Collection), len(widget.Collection)) assert.Equal(t, testCollection.render(), cmd()) } func Test_Model_Update_updates_content(t *testing.T) { testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1") testModel := Model{widget: testIssue} testWidget := testModel.widget.(Issue) testModel.content = testWidget.render().(string) model, cmd := testModel.Update(tea.Msg(testModel.content)) if cmd != nil { assert.Fail(t, "should not return cmd") } assert.Equal(t, testModel.content, model.(Model).content) } func Test_Model_Update_do_nothing(t *testing.T) { testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1") testModel := Model{widget: testIssue} var testMsg int model, cmd := testModel.Update(testMsg) assert.Equal(t, testModel, model) assert.Nil(t, cmd) } func Test_Model_renderIssue(t *testing.T) { testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1") testRender := testIssue.render() renderContent, _ := testRender.(string) assert.True(t, strings.Contains(renderContent, "test description")) } func Test_Model_View(t *testing.T) { testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1") model, cmd := Model{}.Update(tea.Msg(testIssue)) // gives render cmd model, cmd = model.Update(cmd()) // handle internal render if cmd != nil { assert.Fail(t, "should not return cmd") } testView := testIssue.render().(string) + "\nj/k: down/up\tenter: select\tq: quit" assert.Equal(t, testView, model.(Model).View()) render2 := Model{}.View() assert.Equal(t, "loading...", render2) } func Test_createIssue_create_cmd(t *testing.T) { // test data init testData := make(map[string]string) // because the resulting test data never gets written from memory to disk, // we can set just about any test path testCi := initialCreateIssueModel("tests/bugs/test-create-in-memory", "lorem ipsum") for i := range testCi.inputFields { testData[testCi.inputFields[i].title] = fmt.Sprintf("test%d", i) testCi.inputFields[i].input.SetValue(fmt.Sprintf("test%d", i)) } commaSplit := func(t string) []string { s := strings.Split(t, ",") for i, v := range s { s[i] = strings.TrimLeft(v, " \t\n") s[i] = strings.TrimRight(s[i], " \t\n") s[i] = parseHumanToPath(s[i]) } return s } var testIssue = Issue{ Path: "tests/bugs/test-create-in-memory", Tags: VariadicField{Path: "/tags"}, Blockedby: VariadicField{Path: "/blockedby"}, } for key, value := range testData { switch key { case "title": testIssue.Title = value case "status": testIssue.Status = Field{Path: "/status", Data: value} case "description": testIssue.Description = Field{Path: "/description", Data: value} case "tags": splitTags := commaSplit(value) for _, tag := range splitTags { testIssue.Tags.Fields = append(testIssue.Tags.Fields, Field{Path: tag}) } case "blockers": splitBlockedby := commaSplit(value) for _, blocker := range splitBlockedby { testIssue.Blockedby.Fields = append(testIssue.Blockedby.Fields, Field{Path: blocker}) } } } result := testCi.create() assert.IsType(t, createResult(testIssue), result) assert.Equal(t, createResult(testIssue).Path, result.(createResult).Path) }