130 lines
4.3 KiB
Go
130 lines
4.3 KiB
Go
package test
|
|
|
|
import (
|
|
domain "RenewCMS/internal/domain/image"
|
|
"bytes"
|
|
"errors"
|
|
"image"
|
|
"image/color"
|
|
"image/gif"
|
|
"testing"
|
|
)
|
|
|
|
func bandedTallImage() *image.NRGBA {
|
|
canvas := image.NewNRGBA(image.Rect(0, 0, 20, 60))
|
|
for y := 0; y < 60; y++ {
|
|
fill := variantGreen
|
|
if y < 15 {
|
|
fill = variantRed
|
|
}
|
|
if y >= 45 {
|
|
fill = variantBlue
|
|
}
|
|
for x := 0; x < 20; x++ {
|
|
canvas.SetNRGBA(x, y, fill)
|
|
}
|
|
}
|
|
return canvas
|
|
}
|
|
|
|
func globalPaletteGIF(t *testing.T, frames int) []byte {
|
|
t.Helper()
|
|
palette := color.Palette{color.White, color.Black, color.RGBA{R: 255, A: 255}, color.RGBA{B: 255, A: 255}}
|
|
animation := &gif.GIF{Config: image.Config{ColorModel: palette, Width: 8, Height: 8}}
|
|
for frame := 0; frame < frames; frame++ {
|
|
paletted := image.NewPaletted(image.Rect(0, 0, 8, 8), palette)
|
|
paletted.SetColorIndex(frame, frame, 1)
|
|
animation.Image = append(animation.Image, paletted)
|
|
animation.Delay = append(animation.Delay, 10)
|
|
}
|
|
var buffer bytes.Buffer
|
|
if err := gif.EncodeAll(&buffer, animation); err != nil {
|
|
t.Fatalf("gif encode failed: %v", err)
|
|
}
|
|
return buffer.Bytes()
|
|
}
|
|
|
|
func TestVariantGeometryPixelGaps(t *testing.T) {
|
|
t.Run("Cover on a tall source keeps the middle band", func(t *testing.T) {
|
|
rendered := renderVariant(t, encodePNG(t, bandedTallImage()), variantSettings(20, 20, domain.FitCover, domain.FormatPNG))
|
|
|
|
decoded, _ := decodeImage(t, rendered.Content)
|
|
if decoded.Bounds().Dx() != 20 || decoded.Bounds().Dy() != 20 {
|
|
t.Fatalf("output = %v", decoded.Bounds())
|
|
}
|
|
for _, y := range []int{0, 10, 19} {
|
|
if got := pixelAt(decoded, 10, y); got != variantGreen {
|
|
t.Errorf("pixel 10,%d = %v, want green", y, got)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("Inside on a tall source scales the whole picture", func(t *testing.T) {
|
|
rendered := renderVariant(t, encodePNG(t, bandedTallImage()), variantSettings(10, 30, domain.FitInside, domain.FormatPNG))
|
|
|
|
decoded, _ := decodeImage(t, rendered.Content)
|
|
if decoded.Bounds().Dx() != 10 || decoded.Bounds().Dy() != 30 {
|
|
t.Fatalf("output = %v", decoded.Bounds())
|
|
}
|
|
want := map[int]color.NRGBA{1: variantRed, 15: variantGreen, 28: variantBlue}
|
|
for y, expected := range want {
|
|
assertNearColor(t, pixelAt(decoded, 5, y), expected)
|
|
}
|
|
})
|
|
|
|
t.Run("Contain pads horizontally around a narrow source", func(t *testing.T) {
|
|
rendered := renderVariant(t, encodePNG(t, variantSolidImage(20, 40, variantRed)), variantSettings(40, 40, domain.FitContain, domain.FormatPNG))
|
|
|
|
decoded, _ := decodeImage(t, rendered.Content)
|
|
for y := 0; y < 40; y += 13 {
|
|
for _, x := range []int{0, 9, 30, 39} {
|
|
if got := pixelAt(decoded, x, y); got.A != 0 {
|
|
t.Fatalf("pixel %d,%d = %v, want transparent", x, y, got)
|
|
}
|
|
}
|
|
for _, x := range []int{10, 19, 29} {
|
|
if got := pixelAt(decoded, x, y); got != variantRed {
|
|
t.Fatalf("pixel %d,%d = %v, want red", x, y, got)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("Contain keeps a box that is larger in one direction only", func(t *testing.T) {
|
|
for _, row := range []struct{ width, height, wantWidth, wantHeight int }{
|
|
{200, 100, 200, 100},
|
|
{100, 200, 100, 200},
|
|
} {
|
|
rendered := renderVariant(t, solidPNG(t, 100, 100), variantSettings(row.width, row.height, domain.FitContain, domain.FormatPNG))
|
|
|
|
width, height := decodedSize(t, rendered.Content)
|
|
if width != row.wantWidth || height != row.wantHeight {
|
|
t.Errorf("output = %dx%d, want %dx%d", width, height, row.wantWidth, row.wantHeight)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestAnimatedGIFDetectionWithGlobalPalette(t *testing.T) {
|
|
animated, err := domain.IsAnimatedGIF(bytes.NewReader(globalPaletteGIF(t, 2)))
|
|
if err != nil || !animated {
|
|
t.Errorf("two frames: animated = %v, err = %v", animated, err)
|
|
}
|
|
|
|
animated, err = domain.IsAnimatedGIF(bytes.NewReader(globalPaletteGIF(t, 1)))
|
|
if err != nil || animated {
|
|
t.Errorf("one frame: animated = %v, err = %v", animated, err)
|
|
}
|
|
}
|
|
|
|
func TestVariantRequestErrorMessages(t *testing.T) {
|
|
unknown := domain.NewUnknownVariantError("thumb")
|
|
if unknown.Error() != "unknown variant: thumb" || !errors.Is(unknown, domain.ErrUnknownVariant) {
|
|
t.Errorf("unknown = %q", unknown.Error())
|
|
}
|
|
unsupported := domain.NewUnsupportedParameterError("w")
|
|
if unsupported.Error() != "unsupported parameter: w" || !errors.Is(unsupported, domain.ErrUnsupportedParameter) {
|
|
t.Errorf("unsupported = %q", unsupported.Error())
|
|
}
|
|
}
|