107 lines
2.8 KiB
Go
107 lines
2.8 KiB
Go
package platepdf
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"printer.backend/internal/layout"
|
|
"printer.backend/internal/model"
|
|
"printer.backend/internal/svgtemplate"
|
|
)
|
|
|
|
const sampleItemSVG = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="80mm" height="80mm" viewBox="-13 -13 106 106">
|
|
<defs>
|
|
<clipPath id="item-mask">
|
|
<rect x="0" y="0" width="80" height="80" rx="5" ry="5" />
|
|
</clipPath>
|
|
</defs>
|
|
<rect x="-13" y="-13" width="106" height="106" fill="#f9f9f9" />
|
|
<g clip-path="url(#item-mask)">
|
|
<rect x="-2" y="-2" width="84" height="84" fill="#00ff00" opacity="0.7" />
|
|
</g>
|
|
</svg>`
|
|
|
|
func requireRsvg(t *testing.T) {
|
|
t.Helper()
|
|
if !rsvgAvailable() {
|
|
t.Skip("rsvg-convert not available")
|
|
}
|
|
}
|
|
|
|
func TestBuildCompositeSVG(t *testing.T) {
|
|
requireRsvg(t)
|
|
|
|
plate := model.Plate{
|
|
WidthMM: 300, HeightMM: 400,
|
|
MarginTop: 10, MarginRight: 10, MarginBottom: 10, MarginLeft: 10,
|
|
}
|
|
spec := model.ItemSpec{SizeMM: 80, BleedMM: 2, MarginMM: 5, PaddingMM: 3}
|
|
preview := layout.Pack(plate, spec, 2)
|
|
|
|
out, err := BuildCompositeSVG(plate, spec, []byte(sampleItemSVG), preview)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
s := string(out)
|
|
if !strings.Contains(s, `viewBox="0 0 300`) {
|
|
t.Fatalf("expected plate viewBox, got: %s", s[:min(200, len(s))])
|
|
}
|
|
if preview.Count > 0 && !strings.Contains(s, `<image `) {
|
|
t.Fatal("expected embedded item images")
|
|
}
|
|
if preview.Count > 0 && !strings.Contains(s, `x="10.0000"`) {
|
|
t.Fatal("expected items at plate margin (footprint origin)")
|
|
}
|
|
}
|
|
|
|
func TestBuildCompositeSVGInvalid(t *testing.T) {
|
|
requireRsvg(t)
|
|
|
|
_, err := BuildCompositeSVG(model.Plate{}, model.ItemSpec{}, []byte("not svg"), model.LayoutPreview{})
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid svg")
|
|
}
|
|
}
|
|
|
|
func TestGeneratePDF(t *testing.T) {
|
|
requireRsvg(t)
|
|
|
|
plate := model.Plate{
|
|
WidthMM: 200, HeightMM: 200,
|
|
MarginLeft: 10, MarginTop: 10, MarginRight: 10, MarginBottom: 10,
|
|
}
|
|
spec := model.ItemSpec{SizeMM: 80, BleedMM: 2, MarginMM: 5, PaddingMM: 3}
|
|
preview := layout.Pack(plate, spec, 2)
|
|
|
|
var buf bytes.Buffer
|
|
if err := svgtemplate.Write(&buf, svgtemplate.Build(spec.SizeMM, spec.BleedMM, spec.MarginMM, spec.PaddingMM)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
path := t.TempDir() + "/item.svg"
|
|
if err := os.WriteFile(path, buf.Bytes(), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
pdf, err := Generate(plate, spec, path, preview)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(pdf) < 4 || string(pdf[:4]) != "%PDF" {
|
|
t.Fatalf("expected PDF header, got %d bytes", len(pdf))
|
|
}
|
|
}
|
|
|
|
func TestGenerateRequiresRsvg(t *testing.T) {
|
|
if rsvgAvailable() {
|
|
t.Skip("rsvg-convert is available")
|
|
}
|
|
_, err := Generate(model.Plate{}, model.ItemSpec{}, "/nonexistent", model.LayoutPreview{})
|
|
if err == nil || !strings.Contains(err.Error(), "rsvg-convert") {
|
|
t.Fatalf("expected rsvg error, got: %v", err)
|
|
}
|
|
}
|