项目文件夹

文件
2026-07-13 13:12:56 +08:00

351 行
8.2 KiB
Go

package main
import (
"bytes"
"flag"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
"testing"
"github.com/aymanbagabas/go-udiff"
)
var binary = "./test/freeze-test"
func init() {
if runtime.GOOS == "windows" {
binary += ".exe"
}
}
var (
update = flag.Bool("update", false, "update golden files")
png = flag.Bool("png", false, "update pngs")
)
func TestMain(m *testing.M) {
flag.Parse()
cmd := exec.Command("go", "build", "-o", binary)
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
exit := m.Run()
err = os.Remove(binary)
if err != nil {
fmt.Println(err)
}
os.Exit(exit)
}
func TestFreeze(t *testing.T) {
cmd := exec.Command(binary)
err := cmd.Run()
if err != nil {
t.Fatal(err)
}
}
func TestFreezeOutput(t *testing.T) {
output := "artichoke-test.svg"
defer os.Remove(output)
cmd := exec.Command(binary, "test/input/artichoke.hs", "-o", output)
err := cmd.Run()
if err != nil {
t.Fatal(err)
}
_, err = os.Stat(output)
if err != nil {
t.Fatal(err)
}
}
func TestFreezeHelp(t *testing.T) {
out := bytes.Buffer{}
cmd := exec.Command(binary)
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
t.Fatal("unexpected error")
}
got := out.String()
contains := []string{
"Generate images of code and terminal output.",
"freeze main.go [-o code.svg] [--flags]",
"--theme", "Theme to use for syntax highlighting",
"--border.color", "Border color.",
"--shadow.blur", "Shadow Gaussian Blur.",
"--font.family", "Font family to use for code.",
}
for _, c := range contains {
if !strings.Contains(got, c) {
t.Fatalf("expected %s to contain \"%s\"", got, c)
}
}
}
func TestFreezeErrorFileMissing(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("this fails on windows for some reason")
}
out := bytes.Buffer{}
cmd := exec.Command(binary, "this-file-does-not-exist")
cmd.Stdout = &out
err := cmd.Run()
if err == nil {
t.Fatal("expected error")
}
got := out.String()
contains := []string{"ERROR", "File not found", "open this-file-does-not-exist: no such file or directory"}
for _, c := range contains {
if !strings.Contains(got, c) {
t.Fatalf("expected %s to contain \"%s\"", got, c)
}
}
}
func TestFreezeConfigurations(t *testing.T) {
tests := []struct {
input string
flags []string
output string
}{
{
input: "test/input/artichoke.hs",
flags: []string{"--config", "test/configurations/base.json"},
output: "artichoke-base",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--config", "test/configurations/full.json"},
output: "artichoke-full",
},
{
input: "test/input/eza.ansi",
flags: []string{"--config", "full"},
output: "eza",
},
{
flags: []string{"--execute", `echo "Hello, world!"`},
output: "execute",
},
{
input: "test/input/bubbletea.model",
flags: []string{"--language", "go", "--height", "800", "--width", "750", "--config", "full", "--window=false", "--show-line-numbers"},
output: "bubbletea",
},
{
input: "test/input/layout.ansi",
flags: []string{},
output: "layout",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--language", "haskell"},
output: "haskell",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--theme", "dracula"},
output: "dracula",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--border.radius", "8"},
output: "border-radius",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--border.radius", "8", "--window"},
output: "window",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--border.radius", "8", "--window", "--border.width", "1"},
output: "border-width",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--border.radius", "8", "--window", "--border.width", "1", "--padding", "30,50,30,30"},
output: "padding",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--border.radius", "8", "--window", "--border.width", "1", "--padding", "30,50,30,30", "--margin", "50,60,100,60"},
output: "margin",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--config", "full"},
output: "shadow",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--width", "1920", "--height", "1080"},
output: "dimensions",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--margin", "50", "--width", "600", "--height", "300"},
output: "dimensions-margin",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--margin", "50", "--width", "600", "--height", "300", "--show-line-numbers"},
output: "dimensions-margin-line-numbers",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--padding", "50", "--width", "600", "--height", "300"},
output: "dimensions-padding",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--config", "full", "--width", "600", "--height", "300"},
output: "dimensions-config",
},
{
input: "test/input/goreleaser-full.yml",
flags: []string{"--config", "full", "--width", "600", "--height", "900"},
output: "overflow",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--config", "full", "--lines", "4,8", "--show-line-numbers"},
output: "lines",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--font.size", "28"},
output: "font-size-28",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--font.size", "14"},
output: "font-size-14",
},
{
input: "test/input/artichoke.hs",
flags: []string{"--line-height", "2"},
output: "line-height-2",
},
{
input: "test/input/goreleaser-full.yml",
flags: []string{"--config", "full", "--height", "2000", "--show-line-numbers"},
output: "overflow-line-numbers",
},
{
input: "test/input/helix.ansi",
flags: []string{"--background", "#0d1116"},
output: "helix",
},
{
input: "test/input/glow.ansi",
flags: []string{},
output: "glow",
},
{
input: "test/input/tab.go",
flags: []string{},
output: "tab",
},
{
input: "test/input/wrap.go",
flags: []string{"--wrap", "80", "--width", "600"},
output: "wrap",
},
}
err := os.RemoveAll("test/output/svg")
if err != nil {
t.Fatal("unable to remove output files")
}
err = os.MkdirAll("test/output/svg", 0o755)
if err != nil {
t.Fatal("unable to create output directory")
}
err = os.MkdirAll("test/golden/svg", 0o755)
if err != nil {
t.Fatal("unable to create output directory")
}
err = os.MkdirAll("test/output/png", 0o755)
if err != nil {
t.Fatal("unable to create output directory")
}
for _, tc := range tests {
t.Run(tc.output, func(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("this fails on windows for some reason")
}
// output SVG
out := bytes.Buffer{}
args := []string{tc.input}
args = append(args, tc.flags...)
args = append(args, "--output", "test/output/svg/"+tc.output+".svg")
cmd := exec.Command(binary, args...)
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
t.Log(err)
t.Log(out.String())
t.Fatal("unexpected error")
}
gotfile := "test/output/svg/" + tc.output + ".svg"
got, err := os.ReadFile(gotfile)
if err != nil {
t.Fatal("no output file for:", gotfile)
}
goldenfile := "test/golden/svg/" + tc.output + ".svg"
if *update {
if err := os.WriteFile(goldenfile, got, 0o644); err != nil {
t.Log(err)
t.Fatal("unexpected error")
}
}
want, err := os.ReadFile(goldenfile)
if err != nil {
t.Fatal("no golden file for:", goldenfile)
}
if normalizeNewlines(want) != normalizeNewlines(got) {
t.Log(udiff.Unified("want", "got", normalizeNewlines(want), normalizeNewlines(got)))
t.Fatalf("%s != %s", goldenfile, gotfile)
}
// output PNG
if png != nil && *png {
out = bytes.Buffer{}
args = []string{tc.input}
args = append(args, tc.flags...)
args = append(args, "--output", "test/output/png/"+tc.output+".png")
cmd = exec.Command(binary, args...)
cmd.Stdout = &out
err = cmd.Run()
if err != nil {
t.Log(err)
t.Log(out.String())
t.Fatal("unexpected error")
}
}
})
}
}
func normalizeNewlines[T string | []byte](s T) string {
return strings.ReplaceAll(string(s), "\r\n", "\n")
}