diff --git a/internal/style/format_test.go b/internal/style/format_test.go index f17e7f00..41504e9e 100644 --- a/internal/style/format_test.go +++ b/internal/style/format_test.go @@ -24,183 +24,145 @@ import ( "github.com/stretchr/testify/assert" ) -func TestGetKeyLengthZero(t *testing.T) { - var keys = map[string]string{ - "": "the zero key", - } - - if getKeyLength(keys) != 0 { - t.Error("the longest key has a length greater than zero") - } -} - -func TestGetKeyLengthMatched(t *testing.T) { - var keys = map[string]string{ - "key1": "unlocks the building", - "key2": "unlocks the room", - } - - if getKeyLength(keys) != 4 { - t.Error("the longest key should have length 4") - } -} - -func TestGetKeyLengthLong(t *testing.T) { - var keys = map[string]string{ - "longer_key1": "locks the building", - "very_long_key2": "locks the room", - } - - if getKeyLength(keys) != 14 { - t.Error("the longest key `very_long_key2` should have length 14") - } -} - -func TestGetKeyLengthFirst(t *testing.T) { - var keys = map[string]string{ - "longest_key1": "short value", - "short_key2": "longer value", - } - - if getKeyLength(keys) != 12 { - t.Error("the longest key `longest_key1` should have length 12") +func TestGetKeyLength(t *testing.T) { + tests := map[string]struct { + keys map[string]string + expected int + }{ + "empty key has zero length": { + keys: map[string]string{"": "the zero key"}, + expected: 0, + }, + "equal length keys return that length": { + keys: map[string]string{"key1": "unlocks the building", "key2": "unlocks the room"}, + expected: 4, + }, + "returns length of longest key": { + keys: map[string]string{"longer_key1": "locks the building", "very_long_key2": "locks the room"}, + expected: 14, + }, + "longest key is first": { + keys: map[string]string{"longest_key1": "short value", "short_key2": "longer value"}, + expected: 12, + }, } -} - -// Verify no text is output with an empty input text -func TestSectionfEmpty(t *testing.T) { - formattedText := Sectionf(TextSection{ - Emoji: "", - Text: "", - Secondary: []string{}, - }) - if formattedText != "" { - t.Error("non-zero text returned when none was expected") + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.expected, getKeyLength(tc.keys)) + }) } } -// Verify no text is output with an empty input text -func TestSectionfHeader(t *testing.T) { - expected := Emoji("tada") + "Congrats\n" + Indent(Secondary("You did it")) + "\n" - formattedText := Sectionf(TextSection{ - Emoji: "tada", - Text: "Congrats", - Secondary: []string{"You did it"}, - }) - if formattedText != expected { - t.Error("section is not formatted as expected") +func TestSectionf(t *testing.T) { + tests := map[string]struct { + section TextSection + expected string + }{ + "empty text returns empty string": { + section: TextSection{Emoji: "", Text: "", Secondary: []string{}}, + expected: "", + }, + "header with emoji and secondary text": { + section: TextSection{Emoji: "tada", Text: "Congrats", Secondary: []string{"You did it"}}, + expected: Emoji("tada") + "Congrats\n" + Indent(Secondary("You did it")) + "\n", + }, + "no emoji starts text immediately": { + section: TextSection{Emoji: "", Text: "On the left. Where I like it.", Secondary: []string{}}, + expected: "On the left. Where I like it.\n", + }, } -} - -// Verify text begins immediately if no emoji is input -func TestSectionfEmptyEmoji(t *testing.T) { - text := "On the left. Where I like it." - formattedText := Sectionf(TextSection{ - Emoji: "", - Text: text, - Secondary: []string{}, - }) - - if formattedText != text+"\n" { - t.Error("additional spacing added to text") + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.expected, Sectionf(tc.section)) + }) } } -// Verify no text is output with an empty input text func TestSectionHeaderfEmpty(t *testing.T) { - text := "" - formattedText := SectionHeaderf("tada", text) - if formattedText != "" { - t.Error("non-zero text returned when none was expected") - } -} - -// Verify no text is output with an empty input -func TestSectionSecondaryfEmpty(t *testing.T) { - text := "" - formattedText := SectionSecondaryf("%s", text) - if formattedText != "" { - t.Log(formattedText) - t.Error("non-zero text returned when none was expected") - } + assert.Equal(t, "", SectionHeaderf("tada", "")) } -// Verify plain string is preserved and properly indented -func TestSectionSecondaryfPlain(t *testing.T) { - text := "If you have a moment, go grab a glass of water!" - formattedText := SectionSecondaryf("%s", text) - if !strings.Contains(formattedText, text) { - t.Error("input text is not preserved") - } - if formattedText != Indent(Secondary(text))+"\n" { - t.Error("output is not indented") - } -} - -// Verify string formats input variables -func TestSectionSecondaryfFormat(t *testing.T) { - text := "App ID: %s\tStatus: %s" - appID := "A123456" - status := "Installed" - formattedText := SectionSecondaryf(text, appID, status) - if !strings.Contains(formattedText, "App ID: A123456\tStatus: Installed") { - t.Error("formatted string does not contain variables") +func TestSectionSecondaryf(t *testing.T) { + tests := map[string]struct { + format string + args []interface{} + validate func(t *testing.T, result string) + }{ + "empty input returns empty string": { + format: "%s", + args: []interface{}{""}, + validate: func(t *testing.T, result string) { + assert.Equal(t, "", result) + }, + }, + "plain text is preserved and indented": { + format: "%s", + args: []interface{}{"If you have a moment, go grab a glass of water!"}, + validate: func(t *testing.T, result string) { + text := "If you have a moment, go grab a glass of water!" + assert.Contains(t, result, text) + assert.Equal(t, Indent(Secondary(text))+"\n", result) + }, + }, + "formats input variables": { + format: "App ID: %s\tStatus: %s", + args: []interface{}{"A123456", "Installed"}, + validate: func(t *testing.T, result string) { + assert.Contains(t, result, "App ID: A123456\tStatus: Installed") + }, + }, + "multi-line input is properly indented": { + format: "%s", + args: []interface{}{"L1\nL2\nL3"}, + validate: func(t *testing.T, result string) { + lines := strings.Split(result, "\n") + for i, line := range strings.Split("L1\nL2\nL3", "\n") { + assert.Equal(t, Indent(Secondary(line)), lines[i]) + } + }, + }, } -} - -// Verify multi-line input is properly indented -func TestSectionSecondaryfIndent(t *testing.T) { - text := "L1\nL2\nL3" - formattedText := SectionSecondaryf("%s", text) - - for i, line := range strings.Split(text, "\n") { - lines := strings.Split(formattedText, "\n") - if strings.Compare(lines[i], Indent(Secondary(line))) != 0 { - t.Errorf("new line not properly indented\n"+ - "expect: *%s*\nactual: *%s*", Indent(Secondary(line)), lines[i]) - } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + result := SectionSecondaryf(tc.format, tc.args...) + tc.validate(t, result) + }) } } -// Verify a `process command`-like string is presented -func TestCommandfPrimary(t *testing.T) { - // rename the process for fuzz-like testing - processTemp := os.Args[0] - process := "renamed-slack-command" - os.Args[0] = "renamed-slack-command" - command := "feedback" - - formatted := Commandf(command, true) - if !strings.Contains(formatted, process+" "+command) { - t.Errorf("a `process command`-like string is not present in output:\n%s", formatted) +func TestCommandf(t *testing.T) { + tests := map[string]struct { + process string + command string + isPrimary bool + }{ + "primary command contains process and command": { + process: "renamed-slack-command", + command: "feedback", + isPrimary: true, + }, + "secondary command contains process and command": { + process: "a-renamed-slack-cli", + command: "feedback", + isPrimary: false, + }, } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + processTemp := os.Args[0] + os.Args[0] = tc.process + defer func() { os.Args[0] = processTemp }() - os.Args[0] = processTemp -} - -// Verify a "process command"-like string is presented -func TestCommandfSecondary(t *testing.T) { - // Rename the process for fuzzy testing - processTemp := os.Args[0] - process := "a-renamed-slack-cli" - os.Args[0] = "a-renamed-slack-cli" - command := "feedback" - - formatted := Commandf(command, false) - if !strings.Contains(formatted, process+" "+command) { - t.Errorf("a `process command`-like string is not present") + formatted := Commandf(tc.command, tc.isPrimary) + assert.Contains(t, formatted, tc.process+" "+tc.command) + }) } - - os.Args[0] = processTemp } -// Verify the text indented is not modified func TestIndent(t *testing.T) { text := "a few spaces are expected at the start of this line, but no other changes" indented := Indent(text) - if !strings.Contains(indented, text) { - t.Error("original text is not preserved") - } + assert.Contains(t, indented, text) } func TestTracef(t *testing.T) { @@ -265,62 +227,60 @@ func TestSurveyIcons(t *testing.T) { */ func TestStyleFlags(t *testing.T) { - defer func() { - ToggleStyles(false) - ToggleCharm(false) - }() - ToggleStyles(true) - ToggleCharm(true) - tests := map[string]struct { - input string - expected string + charmEnabled bool + input string + expectedFunc func() string }{ "short and long flag with type and description": { - input: " -s, --long string Description text", - expected: Yellow(" -s, --long string ") + Secondary("Description text"), + charmEnabled: true, + input: " -s, --long string Description text", + expectedFunc: func() string { return Yellow(" -s, --long string ") + Secondary("Description text") }, }, "long-only flag with description": { - input: " --verbose Enable verbose output", - expected: Yellow(" --verbose ") + Secondary("Enable verbose output"), + charmEnabled: true, + input: " --verbose Enable verbose output", + expectedFunc: func() string { return Yellow(" --verbose ") + Secondary("Enable verbose output") }, }, "plain text without flag pattern returned unchanged": { - input: "some plain text", - expected: "some plain text", + charmEnabled: true, + input: "some plain text", + expectedFunc: func() string { return "some plain text" }, }, "empty string returned unchanged": { - input: "", - expected: "", + charmEnabled: true, + input: "", + expectedFunc: func() string { return "" }, }, "multiline flag output": { - input: " -a, --all Show all\n --verbose Enable verbose", - expected: Yellow(" -a, --all ") + Secondary("Show all") + "\n" + Yellow(" --verbose ") + Secondary("Enable verbose"), + charmEnabled: true, + input: " -a, --all Show all\n --verbose Enable verbose", + expectedFunc: func() string { + return Yellow(" -a, --all ") + Secondary("Show all") + "\n" + Yellow(" --verbose ") + Secondary("Enable verbose") + }, + }, + "charm disabled returns input unchanged": { + charmEnabled: false, + input: " -s, --long string Description text", + expectedFunc: func() string { return " -s, --long string Description text" }, }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { + ToggleStyles(tc.charmEnabled) + ToggleCharm(tc.charmEnabled) + defer func() { + ToggleStyles(false) + ToggleCharm(false) + }() actual := StyleFlags(tc.input) - assert.Equal(t, tc.expected, actual) + assert.Equal(t, tc.expectedFunc(), actual) }) } } -func TestStyleFlags_CharmDisabled(t *testing.T) { - defer func() { - ToggleStyles(false) - ToggleCharm(false) - }() - ToggleStyles(false) - ToggleCharm(false) - - input := " -s, --long string Description text" - actual := StyleFlags(input) - assert.Equal(t, input, actual) -} - func Test_ExampleCommandsf(t *testing.T) { tests := map[string]struct { - name string commands []ExampleCommand expected []string }{ @@ -419,43 +379,6 @@ func Test_ExampleTemplatef(t *testing.T) { } } -func Test_styleExampleLine(t *testing.T) { - defer func() { - ToggleStyles(false) - ToggleCharm(false) - }() - ToggleStyles(true) - ToggleCharm(true) - - tests := map[string]struct { - input string - expected string - }{ - "full-line comment is styled as secondary": { - input: "# Create a new project", - expected: Secondary("# Create a new project"), - }, - "command with inline comment splits styling": { - input: "$ slack create # Create a project", - expected: Yellow("$ ") + CommandText("slack create") + Secondary(" # Create a project"), - }, - "command without comment is styled as command": { - input: "$ slack create my-app", - expected: Yellow("$ ") + CommandText("slack create my-app"), - }, - "plain text without prefix is returned as-is": { - input: "some other text", - expected: "some other text", - }, - } - for name, tc := range tests { - t.Run(name, func(t *testing.T) { - actual := styleExampleLine(tc.input) - assert.Equal(t, tc.expected, actual) - }) - } -} - func Test_ExampleTemplatef_Charm(t *testing.T) { defer func() { ToggleStyles(false) diff --git a/internal/style/style_test.go b/internal/style/style_test.go index 26cc1cea..564c2a7c 100644 --- a/internal/style/style_test.go +++ b/internal/style/style_test.go @@ -17,7 +17,6 @@ package style import ( "testing" - lipgloss "charm.land/lipgloss/v2" "github.com/stretchr/testify/assert" ) @@ -119,15 +118,6 @@ func TestPluralize(t *testing.T) { } } -// Verify no text is output when no emoji is given -func TestEmojiEmpty(t *testing.T) { - alias := "" - emoji := Emoji(alias) - if emoji != "" { - t.Errorf("non-empty text returned, when none was expected") - } -} - func TestToggleCharm(t *testing.T) { tests := map[string]struct { initial bool @@ -259,24 +249,6 @@ func TestFaint(t *testing.T) { }) } -func TestRender(t *testing.T) { - defer func() { - ToggleStyles(false) - }() - - t.Run("returns plain text when colors are off", func(t *testing.T) { - ToggleStyles(false) - result := render(lipgloss.NewStyle().Bold(true), "test") - assert.Equal(t, "test", result) - }) - - t.Run("returns styled text when colors are on", func(t *testing.T) { - ToggleStyles(true) - result := render(lipgloss.NewStyle().Bold(true), "test") - assert.Contains(t, RemoveANSI(result), "test") - }) -} - func TestStyler(t *testing.T) { t.Run("returns an aurora instance", func(t *testing.T) { s := Styler() @@ -294,6 +266,10 @@ func TestEmoji(t *testing.T) { assert.Equal(t, "", Emoji("gear")) }) + t.Run("returns empty for empty alias", func(t *testing.T) { + assert.Equal(t, "", Emoji("")) + }) + t.Run("returns empty for whitespace alias", func(t *testing.T) { ToggleStyles(true) assert.Equal(t, "", Emoji(" "))