package issues import ( "fmt" "strings" "testing" tea "github.com/charmbracelet/bubbletea" "github.com/stretchr/testify/assert" ) // Model tests --------------------------------------------------------------- // ---------------------------------------------------------------------------- func Test_Model_load_cmd_loads_issue(t *testing.T) {} func Test_Model_load_cmd_loads_collection(t *testing.T) {} func Test_Model_load_cmd_loads_edit(t *testing.T) {} func Test_Model_Init_throws_load(t *testing.T) { testModel := Model{Path: "tests/bugs/test-1"} payloadFunc := testModel.Init() assert.IsType(t, tea.Cmd(testModel.load), payloadFunc, tea.Cmd(testModel.load), payloadFunc) testModel = Model{Path: "tests/bugs"} payloadFunc = testModel.Init() assert.IsType(t, tea.Cmd(testModel.load), payloadFunc, tea.Cmd(testModel.load), payloadFunc) testModel = Model{Path: "tests/bugs/doesntexistyet"} payloadFunc = testModel.Init() assert.IsType(t, tea.Cmd(testModel.load), payloadFunc, tea.Cmd(testModel.load), payloadFunc) } func Test_Model_Update_quit_on_ctrl_c(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_renderIssue(t *testing.T) { testIssue, _ := Issue{}.NewFromPath("tests/bugs/test-1") model := tea.Model(Model{widget: testIssue}) testModel := Model{widget: testIssue} model, cmd := model.Update(tea.Msg(testIssue)) if cmd == nil { assert.Fail(t, "should return cmd") } widget, ok := model.(Model).widget.(Issue) assert.True(t, ok, "widget should be type Issue") assert.Equal(t, testIssue.Title, widget.Title) assert.Equal(t, testModel.View(), model.View()) } func Test_Model_Update_renderIssueCollection(t *testing.T) { testCollection, _ := IssueCollection{}.NewFromPath("tests/bugs") model := tea.Model(Model{widget: testCollection}) testModel := Model{widget: testCollection} var cmd tea.Cmd model, cmd = testModel.Update(tea.Msg(testCollection)) if cmd == nil { assert.Fail(t, "should return cmd") } widget, ok := model.(Model).widget.(IssueCollection) assert.True(t, ok, "widget should be type Issue") assert.Equal(t, len(testCollection.Collection), len(widget.Collection)) assert.Equal(t, testModel.View(), model.View()) } func Test_Model_Update_updates_content_on_render(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 cmds") } 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} // create a type wrapper for switch/case channel routing type testMsg int var tm testMsg model, cmd := testModel.Update(tm) assert.Equal(t, testModel, model) assert.NotNil(t, cmd) } // widget tests -------------------------------------------------------------- // ---------------------------------------------------------------------------- // -------- Issue widget definitions ------------------------------------------ // ---------------------------------------------------------------------------- func Test_Issue_render(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_Issue_keyhelp(t *testing.T) {} // -------- IssueCollection widget tests -------------------------------------- // ---------------------------------------------------------------------------- func Test_IssueCollection_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_IssueCollection_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_IssueCollection_update_load_on_enter(t *testing.T) { var ic widget ic, _ = IssueCollection.NewFromPath(IssueCollection{}, "tests/bugs") testKey := tea.Key{Type: tea.KeyEnter, Runes: []rune{}} testMsg := tea.KeyMsg(testKey) testPath := ic.(IssueCollection).Collection[ic.(IssueCollection).selection].Path var cmd tea.Cmd ic, cmd = ic.update(testMsg) assert.Equal(t, testPath, ic.(IssueCollection).Path) // assert.IsType(t, Issue{}, model.widget) if cmd == nil { assert.Fail(t, "should return tea.Cmd") } } func Test_IssueCollection_render(t *testing.T) {} func Test_IssueCollection_keyhelp(t *testing.T) {} // -------- edit widget tests ------------------------------------------------ // ---------------------------------------------------------------------------- func Test_edit_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 testC := newEditWidget("tests/bugs/test-create-in-memory") for i := range testC.(edit).inputFields { testData[testC.(edit).inputFields[i].title] = fmt.Sprintf("test%d", i) testC.(edit).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/test0", // tests that title permutation has propogated 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 := testC.(edit).createIssueObject() assert.IsType(t, createResult(testIssue), result) assert.Equal(t, createResult(testIssue).Path, result.(createResult).Path) } func Test_edit_render(t *testing.T) {} func Test_edit_keyhelp(t *testing.T) {} // misc...--------------------------------------------------------------------- // ---------------------------------------------------------------------------- // duplicated by Test_Model_update_render* func Test_Model_View(t *testing.T) { // TODO DEPRECATE testIssue, _ := Issue.NewFromPath(Issue{}, "tests/bugs/test-1") testModel := Model{widget: testIssue} 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 return cmds") } assert.Equal(t, testModel.View(), model.(Model).View()) render2 := Model{}.View() assert.Equal(t, "loading...", render2) }