diff --git a/internal/mire/diff_test.go b/internal/mire/diff_test.go index b8334ab..f30c6ef 100644 --- a/internal/mire/diff_test.go +++ b/internal/mire/diff_test.go @@ -4,6 +4,8 @@ import ( "bytes" "strings" "testing" + + "mire/internal/testutil" ) func TestFirstMismatchingLineReturnsFirstChangedLine(t *testing.T) { @@ -110,8 +112,6 @@ func TestCompareOutputDoesNotIgnoreMissingLine(t *testing.T) { } func TestWriteScenarioMismatchPrintsOnlyFirstMismatch(t *testing.T) { - t.Setenv("NO_COLOR", "1") - var buf bytes.Buffer writeScenarioMismatch(&buf, &testMismatchError{ expected: []byte("$ echo x\nx\n$ \nexit\n"), @@ -123,7 +123,7 @@ func TestWriteScenarioMismatchPrintsOnlyFirstMismatch(t *testing.T) { }, }) - got := buf.String() + got := testutil.StripANSI(buf.String()) for _, want := range []string{ "Expected\n", "$ echo x\n", @@ -146,8 +146,6 @@ func TestWriteScenarioMismatchPrintsOnlyFirstMismatch(t *testing.T) { } func TestWriteScenarioMismatchFormatsMissingLine(t *testing.T) { - t.Setenv("NO_COLOR", "1") - var buf bytes.Buffer writeScenarioMismatch(&buf, &testMismatchError{ expected: []byte("alpha\nbeta\n"), @@ -159,7 +157,7 @@ func TestWriteScenarioMismatchFormatsMissingLine(t *testing.T) { }, }) - got := buf.String() + got := testutil.StripANSI(buf.String()) if !strings.Contains(got, "beta\n") { t.Fatalf("writeScenarioMismatch() output = %q, want expected mismatching line", got) } @@ -169,8 +167,6 @@ func TestWriteScenarioMismatchFormatsMissingLine(t *testing.T) { } func TestWriteScenarioMismatchItalicizesLabels(t *testing.T) { - t.Setenv("NO_COLOR", "") - var buf bytes.Buffer writeScenarioMismatch(&buf, &testMismatchError{ expected: []byte("alpha\n"), diff --git a/internal/mire/rewrite_test.go b/internal/mire/rewrite_test.go index 4e59a45..d1320b0 100644 --- a/internal/mire/rewrite_test.go +++ b/internal/mire/rewrite_test.go @@ -70,13 +70,14 @@ func TestRewriteContinuesAfterFailureAndReturnsError(t *testing.T) { if !strings.Contains(err.Error(), "1 scenario(s) failed to rewrite") { t.Fatalf("rewrite() error = %q, want failed rewrite summary", err.Error()) } + normalizedStdout := testutil.StripANSI(stdout.String()) for _, want := range []string{ "FAIL bad (", "PASS ok (", "Summary: total=2 passed=1 failed=1", } { - if !strings.Contains(stdout.String(), want) { - t.Fatalf("stdout = %q, want substring %q", stdout.String(), want) + if !strings.Contains(normalizedStdout, want) { + t.Fatalf("stdout = %q, want substring %q", normalizedStdout, want) } } if got := testutil.ReadFile(t, filepath.Join(testDir, "bad", "out")); got != "stale bad\n" { diff --git a/internal/output/output.go b/internal/output/output.go index 7962355..ea2f2d0 100644 --- a/internal/output/output.go +++ b/internal/output/output.go @@ -52,10 +52,6 @@ func Label(text string, color Color) string { return label(text, color) } -func noColor() bool { - return os.Getenv("NO_COLOR") != "" -} - func prefix() string { chevron := NewStyle().FG(palette.chevronTeal).Bold().Italic().Apply("›") return NewStyle().FG(palette.mireGreen).Bold().Italic().Apply("mire") + " " + chevron + " " diff --git a/internal/output/output_test.go b/internal/output/output_test.go index 5420f0f..000572c 100644 --- a/internal/output/output_test.go +++ b/internal/output/output_test.go @@ -1,14 +1,11 @@ package output import ( - "os" "strings" "testing" ) -func TestFormatIncludesANSIByDefault(t *testing.T) { - t.Setenv("NO_COLOR", "") - +func TestFormatIncludesANSI(t *testing.T) { got := Format("hello\n") if !strings.Contains(got, "\x1b[") { t.Fatalf("Format() = %q, want ANSI styling", got) @@ -18,41 +15,24 @@ func TestFormatIncludesANSIByDefault(t *testing.T) { } } -func TestFormatPlainWhenNoColorSet(t *testing.T) { - t.Setenv("NO_COLOR", "1") - - if got := Format("hello\n"); got != "mire › hello\n" { - t.Fatalf("Format() = %q, want %q", got, "mire › hello\n") - } -} - -func TestLabelsPlainWhenNoColorSet(t *testing.T) { - t.Setenv("NO_COLOR", "1") - - if got := Label("RUN", Info); got != "RUN" { - t.Fatalf("Label() = %q, want %q", got, "RUN") - } - if got := Label("PASS", Pass); got != "PASS" { - t.Fatalf("Label() = %q, want %q", got, "PASS") - } - if got := Label("FAIL", Fail); got != "FAIL" { - t.Fatalf("Label() = %q, want %q", got, "FAIL") - } -} - -func TestFormatReadsNoColorAtRuntime(t *testing.T) { - t.Setenv("NO_COLOR", "") - - styled := Format("hello\n") - if err := os.Setenv("NO_COLOR", "1"); err != nil { - t.Fatalf("Setenv() error = %v", err) - } - - plain := Format("hello\n") - if !strings.Contains(styled, "\x1b[") { - t.Fatalf("styled Format() = %q, want ANSI styling", styled) - } - if plain != "mire › hello\n" { - t.Fatalf("plain Format() = %q, want %q", plain, "mire › hello\n") +func TestLabelIncludesANSI(t *testing.T) { + for _, tc := range []struct { + name string + text string + color Color + }{ + {name: "info", text: "RUN", color: Info}, + {name: "pass", text: "PASS", color: Pass}, + {name: "fail", text: "FAIL", color: Fail}, + } { + t.Run(tc.name, func(t *testing.T) { + got := Label(tc.text, tc.color) + if !strings.Contains(got, "\x1b[") { + t.Fatalf("Label() = %q, want ANSI styling", got) + } + if !strings.Contains(got, tc.text) { + t.Fatalf("Label() = %q, want text %q", got, tc.text) + } + }) } } diff --git a/internal/output/termstyle.go b/internal/output/termstyle.go index 5822780..4538fe2 100644 --- a/internal/output/termstyle.go +++ b/internal/output/termstyle.go @@ -40,7 +40,7 @@ func (s Style) BG(rgb uint32) Style { } func (s Style) Apply(text string) string { - if noColor() || (!s.bold && !s.italic && s.fg == nil && s.bg == nil) { + if !s.bold && !s.italic && s.fg == nil && s.bg == nil { return text } diff --git a/internal/testutil/testutil.go b/internal/testutil/testutil.go index c1ada4d..44f36b4 100644 --- a/internal/testutil/testutil.go +++ b/internal/testutil/testutil.go @@ -6,14 +6,16 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "strings" "sync" "testing" ) +var ansiRegexp = regexp.MustCompile(`\x1b\[[0-9;]*[A-Za-z]`) + func CaptureOutput(t *testing.T, fn func()) (string, string) { t.Helper() - t.Setenv("NO_COLOR", "1") stdoutReader, stdoutWriter, err := os.Pipe() if err != nil { @@ -52,12 +54,11 @@ func CaptureOutput(t *testing.T, fn func()) (string, string) { t.Fatalf("stderr copy error = %v", err) } - return stdoutBuf.String(), stderrBuf.String() + return StripANSI(stdoutBuf.String()), StripANSI(stderrBuf.String()) } func CapturePromptedOutput(t *testing.T, sessionInput, promptMarker, promptInput string, fn func()) (string, string) { t.Helper() - t.Setenv("NO_COLOR", "1") stdinReader, stdinWriter, err := os.Pipe() if err != nil { @@ -159,7 +160,11 @@ func CapturePromptedOutput(t *testing.T, sessionInput, promptMarker, promptInput t.Fatalf("stderr copy error = %v", err) } - return stdoutBuf.String(), stderrBuf.String() + return StripANSI(stdoutBuf.String()), StripANSI(stderrBuf.String()) +} + +func StripANSI(text string) string { + return ansiRegexp.ReplaceAllString(text, "") } func WriteFile(t *testing.T, path, content string) {