-
Notifications
You must be signed in to change notification settings - Fork 1.7k
test: add unit tests for pkg/terminal package #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| package terminal | ||
|
|
||
| import ( | ||
| "context" | ||
| "io" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestIsMarkdownContent_Headers(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| input string | ||
| expected bool | ||
| }{ | ||
| {"h1 prefix", "# Title", true}, | ||
| {"h2 prefix", "## Subtitle", true}, | ||
| {"h3 in body", "some text\n# Header", true}, | ||
| {"plain text", "just some regular text", false}, | ||
| {"empty string", "", false}, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| assert.Equal(t, tt.expected, IsMarkdownContent(tt.input)) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestIsMarkdownContent_CodeBlocks(t *testing.T) { | ||
| assert.True(t, IsMarkdownContent("```go\nfmt.Println()\n```")) | ||
| } | ||
|
|
||
| func TestIsMarkdownContent_Bold(t *testing.T) { | ||
| assert.True(t, IsMarkdownContent("this is **bold** text")) | ||
| } | ||
|
|
||
| func TestIsMarkdownContent_Links(t *testing.T) { | ||
| assert.True(t, IsMarkdownContent("click [here](https://example.com)")) | ||
| } | ||
|
|
||
| func TestIsMarkdownContent_Lists(t *testing.T) { | ||
| assert.True(t, IsMarkdownContent("items:\n- first\n- second")) | ||
| } | ||
|
|
||
| func TestIsMarkdownContent_PlainText(t *testing.T) { | ||
| assert.False(t, IsMarkdownContent("no markdown here at all")) | ||
| assert.False(t, IsMarkdownContent("single line")) | ||
| } | ||
|
|
||
| func TestInteractivePromptContext_ReadsInput(t *testing.T) { | ||
| reader := strings.NewReader("hello world\n") | ||
| ctx := context.Background() | ||
|
|
||
| result, err := InteractivePromptContext(ctx, "Enter", reader) | ||
| require.NoError(t, err) | ||
| assert.Equal(t, "hello world", result) | ||
| } | ||
|
|
||
| func TestInteractivePromptContext_TrimsWhitespace(t *testing.T) { | ||
| reader := strings.NewReader(" trimmed \n") | ||
| ctx := context.Background() | ||
|
|
||
| result, err := InteractivePromptContext(ctx, "Enter", reader) | ||
| require.NoError(t, err) | ||
| assert.Equal(t, "trimmed", result) | ||
| } | ||
|
|
||
| func TestInteractivePromptContext_CancelledContext(t *testing.T) { | ||
| pr, pw := io.Pipe() | ||
| defer pw.Close() | ||
|
|
||
| ctx, cancel := context.WithCancel(context.Background()) | ||
| cancel() | ||
|
|
||
| _, err := InteractivePromptContext(ctx, "Enter", pr) | ||
| require.ErrorIs(t, err, context.Canceled) | ||
| } | ||
|
|
||
| func TestGetYesNoInputContext_Yes(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| input string | ||
| }{ | ||
| {"lowercase y", "y\n"}, | ||
| {"lowercase yes", "yes\n"}, | ||
| {"uppercase Y", "Y\n"}, | ||
| {"uppercase YES", "YES\n"}, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| reader := strings.NewReader(tt.input) | ||
| result, err := GetYesNoInputContext(context.Background(), "Confirm?", reader) | ||
| require.NoError(t, err) | ||
| assert.True(t, result) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestGetYesNoInputContext_No(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| input string | ||
| }{ | ||
| {"lowercase n", "n\n"}, | ||
| {"lowercase no", "no\n"}, | ||
| {"uppercase N", "N\n"}, | ||
| {"uppercase NO", "NO\n"}, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| reader := strings.NewReader(tt.input) | ||
| result, err := GetYesNoInputContext(context.Background(), "Confirm?", reader) | ||
| require.NoError(t, err) | ||
| assert.False(t, result) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestGetYesNoInputContext_CancelledContext(t *testing.T) { | ||
| pr, pw := io.Pipe() | ||
| defer pw.Close() | ||
|
|
||
| ctx, cancel := context.WithCancel(context.Background()) | ||
| cancel() | ||
|
|
||
| _, err := GetYesNoInputContext(ctx, "Confirm?", pr) | ||
| require.ErrorIs(t, err, context.Canceled) | ||
| } | ||
|
|
||
| func TestPrintJSON_ValidData(t *testing.T) { | ||
| // PrintJSON writes to stdout; verify it doesn't panic | ||
| data := map[string]string{"key": "value"} | ||
| assert.NotPanics(t, func() { | ||
| PrintJSON(data) | ||
| }) | ||
| } | ||
|
|
||
| func TestPrintJSON_InvalidData(t *testing.T) { | ||
| // Channels cannot be marshaled to JSON | ||
| assert.NotPanics(t, func() { | ||
| PrintJSON(make(chan int)) | ||
| }) | ||
| } | ||
|
|
||
| func TestRenderMarkdown_Empty(t *testing.T) { | ||
| // Should return without error on empty input | ||
| assert.NotPanics(t, func() { | ||
| RenderMarkdown("") | ||
| }) | ||
| } | ||
|
|
||
| func TestRenderMarkdown_ValidContent(t *testing.T) { | ||
| assert.NotPanics(t, func() { | ||
| RenderMarkdown("# Hello\n\nThis is **bold**") | ||
| }) | ||
| } | ||
|
|
||
| func TestPrintResult_PlainText(t *testing.T) { | ||
| assert.NotPanics(t, func() { | ||
| PrintResult("plain text output") | ||
| }) | ||
| } | ||
|
|
||
| func TestPrintResult_MarkdownContent(t *testing.T) { | ||
| assert.NotPanics(t, func() { | ||
| PrintResult("# Header\n\nSome **bold** text") | ||
| }) | ||
| } | ||
|
|
||
| func TestPrintResultWithKey(t *testing.T) { | ||
| assert.NotPanics(t, func() { | ||
| PrintResultWithKey("Result", "plain text output") | ||
| }) | ||
| } | ||
|
Comment on lines
+136
to
+180
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TestInteractivePromptContext_CancelledContextclaims to use a blocking reader, butstrings.NewReader("")returns EOF immediately, so this test doesn’t reliably exercise the context-cancellation branch. Consider using a truly blocking reader (e.g., anio.Pipewith no writer activity) and assert the returned error matchescontext.Canceled(orerrors.Is(err, context.Canceled)) to validate cancellation behavior rather than just "some error".