Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions tests/e2e_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package tests

import (
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)

var glowBin string

func TestMain(m *testing.M) {
tmp, err := os.MkdirTemp("", "glow-e2e-*")
if err != nil {
panic("failed to create temp dir: " + err.Error())
}
defer os.RemoveAll(tmp)

glowBin = filepath.Join(tmp, "glow-test")
cmd := exec.Command("go", "build", "-o", glowBin, "..")
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic("failed to build glow: " + err.Error())
}

os.Exit(m.Run())
}

func TestRenderMarkdownFile(t *testing.T) {
out, err := exec.Command(glowBin, "testdata/test.md").CombinedOutput()
if err != nil {
t.Fatalf("glow testdata/test.md failed: %v\n%s", err, out)
}
if len(out) == 0 {
t.Error("expected non-empty output")
}
}

func TestRenderWithStyle(t *testing.T) {
out, err := exec.Command(glowBin, "-s", "dark", "testdata/test.md").CombinedOutput()
if err != nil {
t.Fatalf("glow -s dark failed: %v\n%s", err, out)
}
if len(out) == 0 {
t.Error("expected non-empty output")
}
}

func TestRenderWithWidth(t *testing.T) {
out, err := exec.Command(glowBin, "-w", "40", "testdata/test.md").CombinedOutput()
if err != nil {
t.Fatalf("glow -w 40 failed: %v\n%s", err, out)
}
if len(out) == 0 {
t.Error("expected non-empty output")
}
}

func TestRenderWithLineNumbers(t *testing.T) {
out, err := exec.Command(glowBin, "-l", "testdata/test.md").CombinedOutput()
if err != nil {
t.Fatalf("glow -l failed: %v\n%s", err, out)
}
if len(out) == 0 {
t.Error("expected non-empty output")
}
}

func TestStdinPipe(t *testing.T) {
cmd := exec.Command(glowBin)
cmd.Stdin = strings.NewReader("# Hello\n\nWorld")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("echo | glow failed: %v\n%s", err, out)
}
if !strings.Contains(string(out), "Hello") {
t.Errorf("expected output to contain 'Hello', got: %s", out)
}
}

func TestInvalidFile(t *testing.T) {
err := exec.Command(glowBin, "nonexistent.md").Run()
if err == nil {
t.Error("expected non-zero exit for nonexistent file")
}
}

func TestHelpFlag(t *testing.T) {
out, err := exec.Command(glowBin, "--help").CombinedOutput()
if err != nil {
t.Fatalf("glow --help failed: %v\n%s", err, out)
}
output := string(out)
if !strings.Contains(strings.ToLower(output), "glow") {
t.Errorf("expected help output to contain 'glow', got: %s", output)
}
}
23 changes: 23 additions & 0 deletions tests/testdata/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Test Document

This is a **bold** and *italic* test document.

## Features

- Item one
- Item two
- Item three

## Code Example

```go
package main

import "fmt"

func main() {
fmt.Println("Hello, world!")
}
```

That's all folks.
114 changes: 114 additions & 0 deletions ui/markdown_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package ui

import (
"testing"
"time"
)

func TestNormalize(t *testing.T) {
tests := []struct {
name string
input string
want string
wantErr bool
}{
{"diacritics cafe", "café", "cafe", false},
{"diacritics naive", "naïve", "naive", false},
{"diacritics Munchen", "München", "Munchen", false},
{"ASCII unchanged", "hello world", "hello world", false},
{"empty string", "", "", false},
{"mixed diacritics", "résumé.md", "resume.md", false},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := normalize(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("normalize() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("normalize(%q) = %q, want %q", tt.input, got, tt.want)
}
})
}
}

func TestRelativeTime(t *testing.T) {
now := time.Now()

tests := []struct {
name string
when time.Time
want string
}{
{
name: "just now",
when: now.Add(-10 * time.Second),
want: "just now",
},
{
name: "minutes ago",
when: now.Add(-5 * time.Minute),
want: "5 minutes ago",
},
{
name: "hours ago",
when: now.Add(-3 * time.Hour),
want: "3 hours ago",
},
{
name: "days ago",
when: now.Add(-2 * 24 * time.Hour),
want: "2 days ago",
},
{
name: "old date uses formatted date",
when: time.Date(2020, 1, 15, 10, 30, 0, 0, time.UTC),
want: "15 Jan 2020 10:30 UTC",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := relativeTime(tt.when)
if got != tt.want {
t.Errorf("relativeTime() = %q, want %q", got, tt.want)
}
})
}
}

func TestBuildFilterValue(t *testing.T) {
tests := []struct {
name string
note string
want string
}{
{
name: "plain text",
note: "readme",
want: "readme",
},
{
name: "diacritics stripped",
note: "café résumé",
want: "cafe resume",
},
{
name: "empty note",
note: "",
want: "",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
md := &markdown{Note: tt.note}
md.buildFilterValue()
if md.filterValue != tt.want {
t.Errorf("buildFilterValue() filterValue = %q, want %q", md.filterValue, tt.want)
}
})
}
}
Loading